cglib动态代理
1.示例需要代码
1.接口代码
public interface People {
public String workAndGetReward();
public String reward();
}
2.接口实现类代码
public class Programmer implements People {
@Override
public String workAndGetReward() {
System.out.println("Programmer works hard under 996.");
return reward();
}
@Override
public String reward() {
return "Then he goes icu.";
}
}
3.动态代理处理类代码
import java.lang.reflect.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import net.sf.cglib.proxy.Enhancer;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
public class CglibProxy implements MethodInterceptor {
private static Logger logger = LoggerFactory.getLogger(Programmer.class);
@Override
public Object intercept(Object proxy, Method method, Object[] params, MethodProxy methodProxy) throws Throwable {
logger.info("before invoke:" + method.getName() + " - " + System.currentTimeMillis());
Object retObj = methodProxy.invokeSuper(proxy, params);
logger.info("after invoke:" + method.getName() + " - " + System.currentTimeMillis());
return retObj;
}
// 返回目标对象的代理对象
public Object newProxy(Object target) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
enhancer.setClassLoader(target.getClass().getClassLoader());
return enhancer.create();
}
}
4.main代码
public class App {
public static void main(String[] args) {
// 要代理的真实对象
Programmer programmer = new Programmer();
// 生成MethodInterceptor对象
CglibProxy proxy = new CglibProxy();
// 根据真实对象生成代理对象
Programmer proxyProgrammer = (Programmer) proxy.newProxy(programmer);
System.out.println(proxyProgrammer.workAndGetReward() + " - " + System.currentTimeMillis());
}
}
2.代码分析
cglib动态代理的核心是
Enhancer对象
我们可以通过以下步骤实现动态代理
- 创建Enhancer实例
- 通过setSuperclass方法来设置目标类
- 通过setCallback 方法来设置拦截对象
- create方法生成Target的代理类,并返回代理类的相应代理对象实例
通过这个方法和三个参数我们得到传入类型的代理对象,然后在调用方法时,会经过我们自定义的代理方法增强了,如以下输出:
[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:workAndGetReward - 1554827985920
[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:reward - 1554827985929
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:reward - 1554827985929
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:workAndGetReward - 1554827985929
Programmer works hard under 996.
Then he goes icu. - 1554827985929
从控制台的输出可以看出来workAndGetReward()方法受到了动态代理的增强
在workAndGetReward()里调用的reward()方法也受到增强
3.代码修改一
cglib也可以不用实现接口来进行动态代理
修改后的真实对象类代码:
public class Programmer {
public String workAndGetReward() {
System.out.println("Programmer works hard under 996.");
return reward();
}
public String reward() {
return "Then he goes icu.";
}
}
输出:
[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:workAndGetReward - 1554828540025
[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:reward - 1554828540034
Programmer works hard under 996.
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:reward - 1554828540034
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:workAndGetReward - 1554828540034
Then he goes icu. - 1554828540034
可以看到输出顺序略有不同,猜测还会产生其他影响
4.代码修改二
如果我们把内部调用的方法改为final(private方法也会被隐形标记为final)
修改后的真实对象类代码:
public class Programmer {
public String workAndGetReward() {
System.out.println("Programmer works hard under 996.");
return reward();
}
private String reward() {
return "Then he goes icu.";
}
}
输出:
[main] INFO 反射.cglib动态代理.v1.Programmer - before invoke:workAndGetReward - 1554828701583
[main] INFO 反射.cglib动态代理.v1.Programmer - after invoke:workAndGetReward - 1554828701592
Programmer works hard under 996.
Then he goes icu. - 1554828701592
可以看出此时内部调用的reward()方法不会被代理类增强了
cglib是通过生成被代理类的子类覆写被代理类里的所有非final的方法实现方法增强,与方法是内部调用还是外部调用无关,只与方法有没有被final修饰有关(private方法会被隐形修饰为final)
还没有评论,来说两句吧...