java反射の动态代理与静态代理

静态代理弊端:

之前博客中有讲静态代理机制的,特征是代理类和目标对象的类都是在编译期间确定下来的,不利于程序的扩展。同时,每一个代理类只能为一个接口服务,这样一来程序开发中必然产生过多的代理

 

最好可以通过一个代理类完成全部代理功能

动态代理

定义

动态代理是指客户通过代理类来调用其他对象的方法,并且是在程序运行时根据需要动态创建目标类的代理对象。

使用场合

调试

远程方法调用

代理设计模式的原理

使用一个代理将对象包装起来(对象成为代理类属性),然后用该代理对象取代原始对象。任何对原始对象的调用都要通过代理,代理对象决定是否以及何时将方法调用转到原始对象上

 

3.动态代理--反射的应用,体会反射的动态性

静态代理:

要求被代理类和代理类同时实现相应的一套接口;

通过被代理类的对象调用重写接口的方法时,直接上执行的是被代理类的同样的方法调用

动态代理:

反射的动态性

在程序运行时根据被代理类及其实现的接口,动态的创建一个代理类,当调用代理类实现的抽象方法时,就发起对被代理类方法的调用。

技术点

实现了InvocationHandler接口实现类,并重写invoke()方法

Proxy.newInstance(obj.getClass.getClassLoader,obj.getClass().getInterfaces(),h);    obj是被代理类的对象h是实现了InvocationHandler接口实现类的对象

package myNetDemo;

//静态代理模式
//接口
interface ClothesFactory {
	void productCloth();
}

// 被代理类
class NikeClothFactory implements ClothesFactory {

	@Override
	public void productCloth() {
		System.out.println("Nike工厂生产衣服");
	}

}

// 代理类
class ProxyFactory implements ClothesFactory {
	ClothesFactory cf;// 虽然声明的是总接口,但实例化时实际传进去的是具体被代理实现类

	// 在构造器内完成初始化
	public ProxyFactory(ClothesFactory cf) {
		this.cf = cf;
	}

	@Override
	public void productCloth() {
		System.out.println("代理类开始执行,收代理费");
		cf.productCloth();// 实际调用的是实际被代理类的实现方法
	}

}

public class TestProductClothes {
	public static void main(String[] args) {
		NikeClothFactory nikeClothFactory = new NikeClothFactory();// 创建被代理类的对象
		ProxyFactory pFactory = new ProxyFactory(nikeClothFactory);// 创建爱你代理类的对象
		pFactory.productCloth();// 实际调用的是被代理类方法

		// 若再有一个接口,还要在于一个接口的实现类(被代理类,目标类),在造一个代理类实现接口
		// 于是想要动态代理

	}
}

package myNetDemo;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

//动态代理的使用
//反射式动态语言的关键,不在编译的时候,而是在运行的时候动态的创建被代理类
interface Subject {
	void action();
}

// 被代理类
class RealSubject implements Subject {

	@Override
	public void action() {
		System.out.println("我是被代理类");
	}

}

// 凡是与动态代理相关的必须要实现这个接口,实现这个接口的抽象方法
class MyInvocationHandler implements InvocationHandler {

	Object obj;// 实现了接口的被代理类的对象的声明

	// 方法有两个作用①创建代理类时初始化被代理类对象②返回一个代理类对象
	// ①给被代理类的对象实例化②返回一个代理类的对象
	public Object blind(Object object) {
		this.obj = object;
		// ②返回一个代理类的对象()
		return Proxy.newProxyInstance(object.getClass().getClassLoader(),
				object.getClass().getInterfaces(), this);// h第三个参数,指的是实现了InvocationHandler接口的对象
	}

	// 当通过代理类的对象发起对被重写的方法的调用时,都对转化为对如下的invoke方法的调用
	@Override
	public Object invoke(Object proxy, Method method, Object[] args)
			throws Throwable {
		// 抽象方法的返回值,method方法的返回值.返回定义抽象接口的对象
		Object returnVal = method.invoke(obj, args);
		return returnVal;
	}

}

public class TestProxy {
	public static void main(String[] args) {
		//被代理类的对象
		RealSubject real=new RealSubject();
		
		//创建一个实现了InvacationHandler接口的对象
		MyInvocationHandler handler=new MyInvocationHandler();
		
		//调用blind方法,动态的返回一个同样实现了real所在类实现的接口Subject的代理类的对象
		Object obj=handler.blind(real);//返回定义接口的对象
		Subject sub=(Subject)obj;//此时的sub就是代理类的对象
		
		sub.action();//转到对InvacationHandler实现类的invoke方法的调用

		
		//在举一例
		NikeClothFactory nike=new NikeClothFactory();
		ClothesFactory proxyCloth=(ClothesFactory)handler.blind(nike);//proxyCloth即为代理类的对象
		proxyCloth.productCloth();
		
	}
}

你可能感兴趣的:(java,Java全部基础)