深入理解Spring--动态代理(Jdk和Cglib)

一、原理区别:

java动态代理:是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前调用InvokeHandler来处理。

cglib动态代理:是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。

1、如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP

2、如果目标对象实现了接口,可以强制使用CGLIB实现AOP

3、如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换

ii. 如何强制使用CGLIB实现AOP?
(1)添加CGLIB库,SPRING_HOME/cglib/*.jar
(2)在spring配置文件中加入

iii. JDK动态代理和CGLIB字节码生成的区别?
(1)JDK动态代理只能对实现了接口的类生成代理,而不能针对类
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final

二.动态代理,Cglib和Jdk代码实现

1.User接口及实现类

  1. public interface UserService {
  2. void addUser(String username,String pwd);
  3. }
  4. public class UserServiceImpl implements UserService{
  5. @Override
  6. public void addUser(String username, String pwd) {
  7. System.out.println("传参:"+username+","+pwd);
  8. }
  9. }

2.Jdk代理

  1. import java.lang.reflect.InvocationHandler;
  2. import java.lang.reflect.Method;
  3. import java.lang.reflect.Proxy;
  4. public class JdkProxy implements InvocationHandler{
  5. //创建代理对象
  6. private Object target;
  7. //监听
  8. public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  9. System.out.println("JDK动态代理,监听开始!!!!!!");
  10. System.out.println("方法调用前,可以做什么");
  11. Object result = method.invoke(target,args);
  12. System.out.println("方法调用后,可以做什么");
  13. System.out.println("JDK动态代理,监听结束!!!!!!");
  14. return result;
  15. }
  16. //定义获取代理对象的方法
  17. private Object getJdkProxy(Object targetObject){
  18. this.target = targetObject;
  19. // * @param loader the class loader to define the proxy class
  20. // * @param interfaces the list of interfaces for the proxy class
  21. // * to implement
  22. // * @param 将方法调用分派到的调用处理程序
  23. return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
  24. targetObject.getClass().getInterfaces(),this);
  25. }
  26. public static void main(String[] args) {
  27. //创建代理对象实例
  28. JdkProxy jdkProxy = new JdkProxy();
  29. UserService user = (UserService) jdkProxy.getJdkProxy(new UserServiceImpl());
  30. user.addUser("root","root");
  31. }
  32. }

3.Cglib代理

  1. import com.shiro.service.UserService;
  2. import com.shiro.service.UserServiceImpl;
  3. import net.sf.cglib.proxy.Enhancer;
  4. import net.sf.cglib.proxy.MethodInterceptor;
  5. import net.sf.cglib.proxy.MethodProxy;
  6. import java.lang.reflect.Method;
  7. public class CglibProxy implements MethodInterceptor {
  8. private Object target;
  9. /**
  10. * 拦截方法,监听
  11. * @param o
  12. * @param method
  13. * @param objects
  14. * @param methodProxy
  15. * @return
  16. * @throws Throwable
  17. */
  18. public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  19. System.out.println("Cglib,监听开始");
  20. Object invoke = method.invoke(target,objects);//方法执行,参数:target 目标对象 arr参数数组
  21. System.out.println("Cglib,监听结束");
  22. return invoke;
  23. }
  24. //定义获取代理对象的方法
  25. public Object getProxy(Object objectTarget){
  26. this.target = objectTarget;
  27. //创建抽象类生成实例
  28. Enhancer enhancer = new Enhancer();
  29. //设置父类,因为Cglib是针对指定的类生成一个子类,所以需要指定父类
  30. enhancer.setSuperclass(objectTarget.getClass());
  31. //设置回调
  32. enhancer.setCallback(this);
  33. //创建并返回代理对象实例
  34. return enhancer.create();
  35. }
  36. public static void main(String[] args) {
  37. CglibProxy cglibProxy = new CglibProxy();
  38. UserService userService = (UserService) cglibProxy.getProxy(new UserServiceImpl());
  39. userService.addUser("cglib root","12345");
  40. }
  41. }

发表评论

表情:
评论列表 (有 0 条评论,25人围观)

还没有评论,来说两句吧...

相关阅读

    相关 JDK动态代理CGLib动态代理

        JDK 动态代理是 JVM 根据传进来的对象,动态的创建对象的代理对象并返回。     CGLib 动态代理比较复杂,它是通过继承的方式来实现类的代理。 JDK