动态代理
1、JDK动态代理:必须有接口
分类:
有实现类,代理可以增强功能,典型场景,Service方法加上事务
没有实现类,代理可以实现功能,典型场景,MyBatis的Mapper接口
例子1:有实现类
编写接口
public interface TargetInterface {
void test1();
int test2(String s);
}
编写实现类
public class TargetClass implements TargetInterface {
@Override
public void test1() {
System.out.println("TargetClass test1");
}
@Override
public int test2(String s) {
System.out.println("TargetClass test2,参数:" + s);
return 10;
}
}
实现InvocationHandler接口的类
public class WnInvocationHandler implements InvocationHandler {
private TargetInterface targetInterface;
public WnInvocationHandler(TargetInterface targetInterface) {
this.targetInterface = targetInterface;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("start transaction"); //执行代理类方法前增强的功能
Object r = method.invoke(targetInterface, args); //执行代理类方法
System.out.println("commit transaction"); 执行代理类方法后增强的功能
return r;
}
}
产生代理对象
public static void main(String[] args) {
TargetClass targetClass = new TargetClass();
targetClass.test1();
//产生代理对象
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(TestJdkProxy.class.getClassLoader(), new Class[]{TargetInterface.class},new WnInvocationHandler(targetClass));
proxy.test1(); //实现功能增强,一定访问的是代理对象
int r=proxy.test2("aaa");
System.out.println(r);
}
}
例子2:无实现类
编写接口
public interface TargetInterface {
void test1();
int test2(String s);
}
产生代理
public static void main(String[] args) {
TargetInterface proxy = (TargetInterface) Proxy.newProxyInstance(TestJdkProxy.class.getClassLoader(), new Class[]{TargetInterface.class}, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("自己的逻辑");
return 1;
}
});
proxy.test1();
int r=proxy.test2("aaa");
System.out.println(r);
}
2、cglib动态代理,无需接口
实现被代理类,不用实现任何接口
public class CglibTarget {
public void test1() {
System.out.println("CglibTarget test1");
}
public int test2(String s) {
System.out.println("CglibTarget test2,s=" + s);
return 10;
}
}
使用cglib产生代理对象
引入依赖
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib-nodep</artifactId>
<version>3.3.0</version>
</dependency>
Java代码:
public static void main(String[] args) {
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(CglibTarget.class); //设置代理类的父类
enhancer.setCallback(new MethodInterceptor() {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("前置增强");
Object r = methodProxy.invokeSuper(o, objects); //调用目标类的方法
System.out.println("后置增强");
return r;
}
});
CglibTarget proxy = (CglibTarget) enhancer.create();
System.out.println(proxy instanceof CglibTarget);
proxy.test1();
System.out.println(proxy.test2("aaa"));
}
3、区分
jdk动态代理产生的代理对象实现了被代理的接口,继承了Proxy类
cglib动态代理产生的代理对象继承了被代理的目标类,重写方法实现功能增强
注意点:
cglib使用的继承并重写方法实现增强功能,被代理类的方法如果是private,final,static其中一个修饰,cglib失效