1、Spring Aop中使用到了动态代理技术,对于jdk动态代理,要求必须代理接口,底层是java的反射机制,对于类,使用cglib字节码增强来动态代理
2、设计模式中简单的代理模式实现
3、jdk动态代理的实现方法
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; //实现了InvocationHandler接口并实现了它的invoke方法 public class ProxyTest implements InvocationHandler{ //目标代理对象 private Object target; public ProxyTest(){ } //带参的构造函数,用于传递目标代理对象 public ProxyTest(Object target){ this.target = target; } public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("执行方法前"); //代理对象执行对应的方法 在前面后后面都加上了代码,这是Aop的一种实现方式,面向切面编程 method.invoke(target, args); System.out.println("执行方法后"); return target; } public static void main(String[] args) { //创建需要被代理的对象 Sky sky1 = new ProxyTest().new SkyImpl(); //创建代理对象 ProxyTest proxyTest = new ProxyTest(sky1); //生成代理对象 Sky sky = (Sky)Proxy.newProxyInstance(SkyImpl.class.getClassLoader(), SkyImpl.class.getInterfaces(),proxyTest ); //执行方法 sky.rain(); } interface Sky{ void rain(); } class SkyImpl implements Sky{ public void rain() { System.out.println("天下雨了"); } } }
4、运行结果
5、反编译过后,实际上是代理类继承了Proxy类并且实现了对应代理的接口,由于java只能支持单继承,所以jdk代理只适用于代理接口,例如 $ProxyClass extends Proxy implements Sky
6、cglib动态代理案例,需要在maven中添加cglib的依赖包
import java.lang.reflect.Method; import net.sf.cglib.proxy.Enhancer; import net.sf.cglib.proxy.MethodInterceptor; import net.sf.cglib.proxy.MethodProxy; public class CglibTest { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); //设置需要代理的类 enhancer.setSuperclass(HelloServiceImpl.class); //设置回调方法 enhancer.setCallback(new HelloMethodInterceptor()); //创建代理对象 HelloServiceImpl helloServiceImpl = (HelloServiceImpl)enhancer.create(); //调用代理对象的方法 helloServiceImpl.sayHello(); } } //被代理的类 class HelloServiceImpl{ public void sayHello(){ System.out.println("Hello,World!"); } } class HelloMethodInterceptor implements MethodInterceptor{ public Object intercept(Object obj, Method method, Object[] args, MethodProxy methodProxy) throws Throwable { System.out.println("方法调用前"); //执行代理对象的方法 在前面后面加通知都可以 methodProxy.invokeSuper(obj, args); System.out.println("方法调用后"); return obj; } }
7、执行的结果
8、cglib是一种字节码增强的动态代理技术,它代理的是类,而具体的实现是代理类继承了需要被代理的类,并增强了它的方法 $ProxyClass extends HelloServiceImpl 注意:cglib不能代理final修饰的类,也不能代理final修饰的方法,因为不能重写