https://www.zhihu.com/question/20794107
代理模式:代理模式(Proxy)是通过代理对象访问目标对象,这样可以在目标对象基础上增强额外的功能,如添加权限,访问控制和审计等功能
代理角色:
抽象主题:一般实现为接口,是对(被代理对象的)行为的抽象。
被代理角色(目标类):直接实现上述接口,是抽象主题的具体实现。
代理角色(代理类):实现上述接口,是对被代理角色的增强,代理对象应该是目标对象的增强,否则我们就没有必要使用代理了。
分为静态代理和动态代理
静态代理:静态代理的实现模式一般是:首先创建一个接口(JDK代理都是面向接口的),然后创建具体实现类来实现这个接口,然后再创建一个代理类同样实现这个接口,不同之处在于,具体实现类的方法中需要将接口中定义的方法的业务逻辑功能实现,而代理类中的方法只要调用具体类中的对应方法即可,这样我们在需要使用接口中的某个方法的功能时直接调用代理类的方法即可,将具体的实现类隐藏在底层。
动态代理:可以在程序运行期间根据需要动态的创建代理类及其实例来完成具体的功能。动态代理实现分为两种:JDK动态代理和Cglib代理。
动态代理
JDK动态代理管理类:
package dynamicproxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
//代理管理类,创建并返回一个代理类。通过这个处理程序 自动生成代理类
public class JDKProxy implements InvocationHandler{
//被代理的接口
private Object target;
//绑定真实对象, 并生成代理类
public Object binding(Object target) {
this.target = target;
//创建并返回代理对象的方法
return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//Method method, Object[] args 对应调用的方法及参数。处理代理实例,返回结果
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("进入动态代理");
see();
Object invoke = method.invoke(target, args);
after();
return invoke;
}
private void after() {
System.out.println("这是代理类增强的第二个方法");
}
private void see() {
System.out.println("这是代理类增强的第一个方法");
}
}
package dynamicproxy;
public class DynamicProxy {
public static void main(String[] args) {
//真实角色
Hello hello = new HelloImpl();
//代理角色:现在没有,通过处理程序生成
JDKProxy jdkProxy = new JDKProxy();
//通过处理程序生成代理类binding,binding是动态生成的
Hello binding = (Hello) jdkProxy.binding(hello);
binding.sayHello();
}
}
JDK提供了java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy类,这两个类相互配合,入口是Proxy,所以我们先聊它。
Proxy有个静态方法:getProxyClass(ClassLoader, interfaces),只要你给它传入类加载器和一组接口,它就给你返回代理Class对象。
用通俗的话说,getProxyClass()这个方法,会从你传入的接口Class中,“拷贝”类结构信息到一个新的Class对象中,但新的Class对象带有构造器,是可以创建对象的。打个比方,一个大内太监(接口Class),空有一身武艺(类信息),但是无法传给后人。现在江湖上有个妙手神医(Proxy类),发明了克隆大法(getProxyClass),不仅能克隆太监的一身武艺,还保留了小DD(构造器)...(这到底是道德の沦丧,还是人性的扭曲,欢迎走进动态代理)
所以,一旦我们明确接口,完全可以通过接口的Class对象,创建一个代理Class,通过代理Class即可创建代理对象。