代理学过好多次了就是在不改变源码的基础上,对代码的信息进行增强。Spring中的AOP的概念就是典型的动态代理。
按照代理的创建时期,代理类可以分为两种:
静态:由程序员创建代理类或特定工具自动生成源代码再对其编译。在程序运行前代理类的.class文件就已经存在了。
动态:在程序运行时运用反射机制动态创建而成。
静态代理类优缺点
优点:
代理使客户端不需要知道实现类是什么,怎么做的,而客户端只需知道代理即可(解耦合),对于如上的客户端代码,newUserManagerImpl()可以应用工厂将它隐藏,如上只是举个例子而已。
缺点:
1)代理类和委托类实现了相同的接口,代理类通过委托类实现了相同的方法。这样就出现了大量的代码重复。如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
2)代理对象只服务于一种类型的对象,如果要服务多类型的对象。势必要为每一种对象都进行代理,静态代理在程序规模稍大时就无法胜任了。如上的代码是只为UserManager类的访问提供了代理,但是如果还要为其他类如Department类提供代理的话,就需要我们再次添加代理Department的代理类。
在Java中要想实现动态代理机制,需要java.lang.reflect.InvocationHandler接口和 java.lang.reflect.Proxy 类的支持
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @Classname SubjectProxy
* @Description TODO
* @Date 2020/3/21 16:33
* @Created by mmz
*/
public class SubjectProxy implements InvocationHandler {
private Subject subject;
public SubjectProxy(Subject subject) {
this.subject = subject;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("begin");
Object invoke =method.invoke(subject,args);
System.out.println("end");
return invoke;
}
}
package proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
/**
* @Classname SubjectTest
* @Description TODO
* @Date 2020/3/21 16:34
* @Created by mmz
*/
public class SubjectTest {
public static void main(String[] args) {
Subject subject = new SubjectImpl();
InvocationHandler i = new SubjectProxy(subject);
Subject proxyInstance = (Subject) Proxy.newProxyInstance(i.getClass().getClassLoader(), subject.getClass().getInterfaces(), i);
proxyInstance.hello("world");
}
}