静态代理
-
定义接口
public interface Subject {
void visit();
}
-
创建真正实现的类
public class RealSubject implements Subject {
private String name = "proxy.state";
@Override
public void visit() {
System.out.println(name);
}
}
- 创建静态代理类
public class ProxySubject implements Subject {
private Subject subject;
public ProxySubject(Subject subject) {
this.subject = subject;
}
@Override
public void visit() {
subject.visit();
}
}
- 使用例子
public class Client {
public static void main(String[] args) {
ProxySubject subject = new ProxySubject(new RealSubject());
subject.visit();
RealSubject realSubject = new RealSubject();
realSubject.visit();
}
}
静态代理类优缺点
代理类接受一个Subject接口的对象,任何实现该接口的对象,都可以通过代理类进行代理,增加了通用性。
但是也有缺点,每一个代理类都必须实现一遍委托类(也就是realsubject)的接口,
如果接口增加方法,则代理类也必须跟着修改。
其次,代理类每一个接口对象对应一个委托对象,
如果委托对象非常多,则静态代理类就非常臃肿,难以胜任。
动态代理类
-
定义接口
public interface Subject {
void visit();
}
-
创建真正实现的类
public class RealSubject implements Subject {
private String name = "proxy.dynamic";
@Override
public void visit() {
System.out.println(name);
}
}
- 创建动态代理类
public class DynamicProxy implements InvocationHandler {
private Object object;
public DynamicProxy(Object object) {
this.object = object;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
before(methodName);
Object result = method.invoke(object, args);
after(methodName);
return result;
}
/**
* 前置通知
* @param method
*/
public void before(String method){
System.out.println("before the method of "+method);
}
/**
* 后置通知
* @param method
*/
public void after(String method){
System.out.println("after the method of "+method);
}
}
- 使用例子
public class Client {
public static void main(String[] args) {
Subject realSubject = new RealSubject();
DynamicProxy proxy = new DynamicProxy(realSubject);
ClassLoader classLoader = realSubject.getClass().getClassLoader();
Subject subject = (Subject) Proxy.newProxyInstance(classLoader, new Class[]{Subject.class}, proxy);
subject.visit();
}
}
动态代理总结
之前我们发现了静态代理会产生许多重复代码,不能很好的进行代码复用,而动态代理能够很好的解决这个问题,代理类TransactionHandler实现了InvocationHandler接口,并且它持有的目标对象类型是Object,因此事务控制代理类TransactionHandler能够代理任意的对象,为任意的对象添加事务控制的逻辑。因此动态代理才真正的将代码中横向切面的逻辑剥离了出来,起到代码复用的目的。但是动态代理也有缺点,一是它的实现比静态代理更加复杂也不好理解;二是它存在一定的限制,例如它要求需要代理的对象必须实现了某个接口;三是它不够灵活,动态代理会为接口中的声明的所有方法添加上相同的代理逻辑。当然,这只是JDK动态代理所存在的一些缺陷,动态代理还有另外的实现如使用CGLIB库