动态代理的作用:在不改变源码的情况下增强方法;
举个例子,在进行简单的jdbc操作的时候,你想做到每执行一次sql语句就打印一句话,作为日志.
说明:本例子是基于子类(任何一个java普通类)的动态代理,(当然也有基于接口的动态代理模式了)[点击这里连接到](https://blog.csdn.net/weixin_45127611/article/details/104523192);
首先定义简单类,定义一个简单的功能吧:
public class Producter{
@Override
public Float saleProduct(Float money) {
System.out.println("卖了"+money);
return money;
}
}
好,类出来了,现在给你出个问题,你怎么能够在不改变源码的情况下,让每次执行这个方法之前打印一行字,或者是改变money参数的倍数等简单操作??
这些问题用JDK官方提供的 Proxy 类,就没有办法解决了,因为这个java类没有实现任何的接口,只是一个java的简单类;但是这也是有办法增强的,不过要用到三方jar包(cglib和asm)少一不可
接下来是类代码:
public class TestCglib {
//要代理的对象
private static IProduct target = new ProductImpl();
public TestCglib(IProduct target){
this.target = target;
}
public IProduct getlLoggingProxy(){
IProduct proxy = null;
//代理对象由哪一个类加载器负责加载
Class loader = target.getClass();
//代理对象的类型,即其中有哪些方法
MethodInterceptor met = new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
Object returnValue = null;
if("saleProduct".equals(arg1.getName())) {
Float money = (float) (0.8*(Float)arg2[0]);
returnValue = arg1.invoke(target, money);
}
return returnValue;
}
};
return proxy = (IProduct)Enhancer.create(loader,met);
}
public static void main(String[] args) {
TestCglib tc = new TestCglib(new ProductImpl());
IProduct pr = tc.getlLoggingProxy();
pr.saleProduct(1000f);
/*
IProduct proxy = (IProduct)Enhancer.create(target.getClass(),
new MethodInterceptor() {
@Override
public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable {
Object returnValue = null;
if("saleProduct".equals(arg1.getName())) {
Float money = (float) (0.8*(Float)arg2[0]);
returnValue = arg1.invoke(target, money);
}
return returnValue;
}
});
proxy.saleProduct(1000f);
*/
}
}
两种方法运行的结果都是:
卖了800.0
写到最后:用这种方式的(基于子类的动态代理)中,无需被代理类有什么特殊的要求只需要是一个java的简单类就行了,然后用到了这个类的生命;
还有一种基于接口的动态代理:jdk自带的动态代理
https://blog.csdn.net/weixin_45127611/article/details/104523192