代理模式
首先了解一下什么是代理模式, 现在有个有个Job, 我想要在执行work前后加上日志,那么如果没有代理类的话,我们需要修改实现类中work方法,在方法第一行加个日志,最后返回前加个日志. 日志原本与work无有直接关系,却和work直接耦合在了一起, 这违反了开闭原则.
代理模式通过一个代理类,代理类包含一个被代理对象,同样要加日志的话,只需要在代理类调用work方法前后加日志就行,而非修改work原有业务逻辑.
代理模式结构图
静态代理虽然解决了上诉问题 但是还是存在问题:
当有很多个不同的类 (interface Job) 然后需要代理的功能是一样的 ,这样就需要很多个代理类.
这时候就需要动态代理来解决.
动态代理
通过创建一个日志处理类LogHandler 运行时动态前后加日志, 与被代理类无关,这样多少个需要这样加前后日志的都只需要一个LogHandler处理就行了.
JDK动态代理示例
动态代理涉及两个类:
java.lang.reflect.Proxy
java.lang.reflect.InvocationHandler
示例代码github.
示例开始
被代理接口Job
/**
* @Author: xc
* @Date: 2020/6/5
* 被代理接口
*/
public interface Job {
void work();
}
Job接口实现类
/**
* @Author: xc
* @Date: 2020/6/5
*/
public class Person implements Job {
private String name;
Person(String name){
this.name = name;
}
@Override
public void work() {
System.out.println(name + " 上班开始写bug了");
}
}
代理类
/**
* @Author: xc
* @Date: 2020/6/5
* 工作日志处理代理类
*/
public class LogHandler<T> implements InvocationHandler {
//被代理对象
private T target;
public LogHandler(T target) {
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object obj=method.invoke(target,args);
after();
return obj;
}
public void before(){
System.out.println("上班啦...打卡成功!");
}
private void after(){
System.out.println("下班啦...打开成功!");
}
}
代理测试类
/**
* @Author: xc
* @Date: 2020/6/5
*/
public class ProxyTest {
@Test
public void testProxy(){
Job job = new Person("张三");
InvocationHandler logHandler=new LogHandler<>(job);
//参数 代理类加载器,被代理接口,调用处理器
Job jobProxy = (Job)Proxy.newProxyInstance(Job.class.getClassLoader(),new Class<?>[]{Job.class},logHandler);
jobProxy.work();
}
}
输出
上班啦...打卡成功!
张三 上班开始写bug了
下班啦...打开成功!
总结
动态代理 相对于 静态代理的好处:
当有很多个 (interface Job) 然后需要代理的功能是一样的 上下班打卡,这样就需要很多个代理类.
而动态代理只需要一个自动打卡的处理类LogHandler , 和Job无关.