如果我们想在原先已经写好的方法前后加一些东西,如生成日志文件等等,要怎么办呢?
考虑到代码的开闭性原则,我们最好不要在源代码中进行修改,这样会导致两点不便:①可能导致之前代码不可用 ②如果每个方法都要加生成日志的代码,会导致代码冗余和可维护性差。
这个时候我们就会用到动态代理,动态代理分为两种。JDK动态代理和Cgilb动态代理。
两种用法分情况使用,如果方法类实现了接口,可以使用JDK动态代理或者强制使用cglib动态代理
如果方法类没有实现接口,只能使用cglib动态代理。
一、个人理解JDK动态代理
动态代理比较原生,底层用到的是反射机制。原理步骤为:
1.首先有一个目标对象(就是最原本的对象),实现一个接口
2.有一个增强对象(里面为最终要实现的方法的对象,包括前缀后缀和目标对象的原方法),该方法要实现invocationhandler接口,并重写invoke方法
3.将目标对象和增强对象结合起来生成一个代理对象
4.调用代理对象的方法
代码体现:
目标对象
public class Mi implements Imi{
public void Note() {
System.out.println("生产Note");
}
public void Note2() {
System.out.println("生产Note2");
}
}
目标对象实现的接口
public interface Imi {
void Note();
void Note2();
}
增强对象
public class ProxyMi implements InvocationHandler{
//获取到当前要代理的对象
private Object target;
public ProxyMi(Object target) {
// TODO Auto-generated constructor stub
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// TODO Auto-generated method stub
method.invoke(target, args);
System.out.println("销售");
return null;
}
测试文件
public class MyTest {
public static void main(String[] args) {
//声明目标对象(相当于代理对象的父亲)
Mi mi=new Mi();
//将目标对象和增强对象结合(增强对象相当于代理对象的母亲,这一步相当于父母结合)
ProxyMi proxyMi = new ProxyMi(mi);
Class[] classes= {Imi.class};
//通过接口类、增强对象创建代理对象(相当于生了个孩子有父母两个人的特性)
Object newProxyInstance = Proxy.newProxyInstance(Mi.class.getClassLoader(), classes,proxyMi);
Imi mi2=(Imi)newProxyInstance;
//最后调用代理对象的方法
mi2.Note2();
}
}
}
二、个人理解cglib动态代理
不同于JDK动态代理,他不是对应相应的接口生成一个新的类,而是针对之前的方法类生成一个他的子类。
输出结果
完成