1、背景
在项目中,可能遇到一种情况就是原来代码中有个地方调用了类A的方法,现在要在类A之前或者之后进行别的业务逻辑的处理。此时最好不要直接对该方法进行修改,因为这个类可能在别的地方也被调用,只是你不清楚而已,你一改可能影响到别的项目,所以代理模式呼之欲出。
2、代理和代理模式
代理分为动态代理和静态代理,动态代理是根据需要通过反射机制在程序运行期动态的为目标对象创建代理对象,代理的行为可以代理多个方法,即满足生产需要的同时又达到代码的通用目的。静态代理比较简单,这里不说。
代理模式其实就是java动态代理的一种应用,解决背景中所述的问题。
3、代码及说明
public interface Searcher {
void searchSomething();
}
public class SearchImpl implements Searcher {
@Override
public void searchSomething(){
System.out.println("*********search*********");
}
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class SearchProxy implements InvocationHandler {
private Object object;
public SearchProxy(Object object){
//接收传入的对象
this.object = object;
}
public Object getProxy(){
//创建代理对象。三个参数的意义分别是:1、用哪个类加载器去加载代理对象:采用SearchProxy的类加载器去加载代理对象
// 2、动态代理类需要实现的接口:入参object的类(这里是SearchImpl的接口Searcher)的接口
// 3、动态代理方法在执行时,会调用h里面的invoke方法去执行:调用SearchProxy的invoke方法
//结果:返回一个入参object 的实例,这里是返回一个类型为 SearchImpl 的实例
return Proxy.newProxyInstance(this.getClass().getClassLoader(),object.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{
//利用反射机制调用目标对象的方法,并增强行为
beforeSearch();
Object result = method.invoke(object,args);
afterSearch();
return result;
}
private void beforeSearch(){
System.out.println("调用反射,在search之前......");
}
private void afterSearch(){
System.out.println("调用反射,在search之后......");
}
}
public class Main {
public static void main(String[] args){
Searcher searcher = new SearchImpl();
//第一处直接调用 searcher的搜索方法
searcher.searchSomething();
//第二处采用动态代理调用searcher的方法
SearchProxy searchProxy = new SearchProxy(searcher);
Searcher a = (Searcher)searchProxy.getProxy();
a.searchSomething();
}
}
假设在第一处是我们原来的业务逻辑调用了searchSomething方法,此时有个需求是希望在调用searchSomething方法前后进行什么逻辑。那么可以在第二处采用动态代理的方式解决。在代理对象searchProxy 的invoke方法前后可添加逻辑。这样就符合的程序设计的开闭原则。
4、优缺点
优点:
1、能够协调调用者和被调用者,在一定程度上降低了系统的耦合度。
2、客户端可以针对抽象主题角色进行编程,增加和更换代理类无须修改源代码,符合开闭原
则,系统具有较好的灵活性和可扩展性。
缺点:
1、慢,java反射导致的。
2、实现代理模式需要额外的工作。