jdk动态代理 & cglib动态代理
注意:这里为了方便代码展示,代理的方法都是匿名类部内进行的重写
jdk动态代理和cglib动态代理最大的区别是jdk必须要实现接口,否则无法代理,cglib则不需要实现接口,他会在目标类基础上创建一个子类进行增强
jdk和cglib在springaop应用,后续在了解了aop后会知道他的强大之处,很多全局的日志,全局异常处理,目标方法增强都会用到,大大减少我们的重复代码反射和动态代理的学习及其重要!
jdk动态代理demo
第一步: 新建一个接口
package com.proxy;
public interface JdkClass {
String print();
}
第二步:写一个实现类继承上面的接口
package com.proxy;
public class jdkClassImpl implements JdkClass {
@Override
public String print() {
System.out.println("我是一个jdk动态代理实现类....");
return "OK";
}
}
第三步:写jdk增强的实现代码
package com.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JdkDynamicClass<T> {
//把目标方法通过构造方法注入
private T target;
public JdkDynamicClass(T target) {
this.target = target;
}
//这里是代理类的创建
public T getProxy(){
//这里是处理增强的类
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//proxy参数传递的即是代理实现类的实例
System.out.println("jdk动态代理前置增强....");
String result =(String) method.invoke(target, args);
System.out.println(result);
System.out.println("jdk动态代理后置增强....");
return result;
}
};
//执行增强并运行的方法!
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),invocationHandler);
}
}
第四步: 测试
package com.proxy;
public class JDKRunTest {
public static void main(String[] args) {
//可以看到,目标类的add方法前后已经加入了自定义的切面逻辑,AOP拦截机制生效了。
// 再看class com.sun.proxy.$Proxy0。这里进一步证明JDK动态代理的核心是InvocationHandler接口和Proxy类
JdkDynamicClass<jdkClassImpl> jdkDynamicClass = new JdkDynamicClass<>(new jdkClassImpl());
//这里的proxyInstance就是我们目标类的增强代理类
JdkClass proxy = jdkDynamicClass.getProxy();
proxy.print();
System.out.println("======>"+ proxy.getClass());
}
}
运行结果:
cglib动态代理demo
第一步: 写一个普通的class类
package com.proxy;
public class CglibClass {
public void add(){
System.out.println("cglib动态代理...");
}
}
第二步: 测试,具体的cglib代码一起写在main方法中了,方便大家查看,也可以单独写一个类进行处理
package com.proxy;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibTest {
public static void main(String[] args) {
//对目标类进行增强
MethodInterceptor cglibProxy = new MethodInterceptor() {
@Override //参数1: 目标代理对象 参数2:目标类的method方法 , 参数3:目标类的参数列表 参数4:目标类的代理方法
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("cglib 前置增强...");
//注意这里一定要用setSuperClass 它去找的是父类,编译看父类,执行走子类的实现! 这是java的基础
//如果用invoke方法会出现无限循环,找不到父类,就会报栈溢出
//proxy.invoke(0,objects) 执行的是原始方法!
Object target = methodProxy.invokeSuper(o, objects);
System.out.println("cglib 后置增强...");
return target;
}
};
//enhancer增强子,用于执行最后的增强!
Enhancer enhancer = new Enhancer();
//设置cglib的父类
enhancer.setSuperclass(CglibClass.class);
//增强的代理类
enhancer.setCallback(cglibProxy);
CglibClass cglibClass = (CglibClass)enhancer.create();
//执行方法
cglibClass.add();
Class<? extends CglibClass> aClass = cglibClass.getClass();
System.out.println("生成的cglib代理增强类: " + aClass);
System.out.println("========分割线=========");
//这一步打印cglib代理的父类,说明cglib是为目标类创建了一个子类,再对子类的增强... 所以他是不需要目标类实现一个接口的
String name = aClass.getSuperclass().getName();
System.out.println("cglib的父类:" + name);
}
}