静态代理与动态代理
Posted 十三弦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了静态代理与动态代理相关的知识,希望对你有一定的参考价值。
代理是一种设计模式,它提供了对目标对象的另外的访问方式,通过代理访问目标对象,可以在目标对象实现的基础上增加额外的功能操作,扩展目标对象的功能。
1.动态代理
1)代理对象,不需要实现接口;
2)代理对象的生成,是利用JDKAPI, 动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型;);
3) 动态代理, JDK代理, 接口代理;
public class ProxyFactory { private Object target; public ProxyFactory(Object target){ this.target = target; } //给目标对象生成代理对象 public Object getProxyInstance(){ return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("开启事务"); System.out.println(method.getName()); Object result = method.invoke(target,args); System.out.println("结束事务"); return result; } }); } }
使用动态代理
UserDao userDao = new UserDao(); ProxyFactory proxyFactory = new ProxyFactory(userDao); //强转,注意必须用接口类型接受 IUserDao proxyInstance = (IUserDao) proxyFactory.getProxyInstance(); proxyInstance.save();
生成的代理对象的类名类似于class com.sun.proxy.$Proxy4,为动态代理。
动态代理要求目标对象必须要实现接口,如果目标对象没有实现接口,需要用到cglib代理。
2.cglib代理
CGLIB是一个强大的高性能的代码生成包,它可以在运行期扩展Java类与实现Java接口。它广泛的被许多AOP的框架使用,例如Spring AOP和dynaop,为他们提供方法的interception(拦截)。
CGLIB包的底层是通过使用一个小而快的字节码处理框架ASM,来转换字节码并生成新的类。不鼓励直接使用ASM,因为它要求你必须对JVM内部结构包括class文件的格式和指令集都很熟悉。
1) 需要引入cglib – jar文件, 但是spring的核心包中已经包括了cglib功能,所以直接引入spring-core-3.2.5.jar即可。
2)引入功能包后,就可以在内存中动态构建子类
3)代理的类不能为final, 否则报错。
4) 目标对象的方法如果为final/static, 那么就不会被拦截,即不会执行目标对象额外的业务方法。
public class ProxyFactory implements MethodInterceptor{ private Object target; public ProxyFactory(Object target){ this.target = target; } public Object getProxyInstance(){ //工具类 Enhancer enhancer = new Enhancer(); //设置父类 enhancer.setSuperclass(target.getClass()); //设置回调函数 enhancer.setCallback(this); return enhancer.create(); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println("开始事务"); Object result = method.invoke(target, objects); System.out.println("结束事务"); return result; } }
使用cglib代理
UserDao userDao = new UserDao(); UserDao proxy = (UserDao) new ProxyFactory(userDao).getProxyInstance(); proxy.save();
生成的代理对象类名类似于class com.juaner.proxy.cglib.UserDao$$EnhancerByCGLIB$$aa5d198b。
在Spring的AOP编程中,
如果加入容器的目标对象有实现接口,用JDK代理;
如果目标对象没有实现接口,用Cglib代理;
以上是关于静态代理与动态代理的主要内容,如果未能解决你的问题,请参考以下文章