zoukankan      html  css  js  c++  java
  • Spring的 AOP底层用到两种代理机制

    JDK 的动态代理:针对实现了接口的类产生代理。
    CGlib 的动态代理:针对没有实现接口的类产生代理,应用的是底层的字节码增强的技术 生成当前类的子类对象

    JDK动态代理实现
    1. 创建接口和对应实现类

    1 public interface UserService {
    2 void login();
    3 void loginOut();
    4 }
    1 //实现类
    2 public class UserServiceImpl implements UserService {
    3 public void login() {
    4 System.out.println("login方法触发");
    5 }
    6 public void loginOut() {
    7 System.out.println("loginOut方法触发");
    8 }
    9 }

    2.创建动态代理类

     1 public class PerformHandler implements InvocationHandler {
     2 private Object target; //目标对象
     3 public PerformHandler(Object target){
     4 this.target = target;
     5 }
     6 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
     7 //本方法中的其他输出输入增强
     8 System.out.println("方法触发了");
     9 //执行被代理类 原方法
    10 Object invoke = method.invoke(target, args);
    11 System.out.println("执行完毕了");
    12 return invoke;
    13 }
    14 }

    测试

     1 @Test
     2 public void test1(){
     3 //测试JDK动态代理技术
     4 UserService userService = new UserServiceImpl();
     5 PerformHandler performHandler = new PerformHandler(userService);
     6 userService = (UserService)
     7 Proxy.newProxyInstance(userService.getClass().getClassLoader(),
     8 userService.getClass().getInterfaces(),
     9 performHandler
    10 );
    11 userService.login();
    12 }

    测试结果: 在调用接口方法的前后都会添加代理类的方法!

    CGlib实现代理
    使用JDK创建代理有一个限制,它只能为接口创建代理实例.这一点可以从Proxy的接口方法
    newProxyInstance(ClassLoader loader,Class [] interfaces,InvocarionHandler h)中看的很清楚
    第二个入参 interfaces就是需要代理实例实现的接口列表.
    对于没有通过接口定义业务方法的类,如何动态创建代理实例呢? JDK动态代理技术显然已经黔驴技穷,CGLib
    作为一个替代者,填补了这一空缺.
    GCLib采用底层的字节码技术,可以为一个类创建子类,在子类中采用方法拦截的技术拦截所有父类方法的调用
    并顺势织入横切逻辑.

    1. 创建创建CGLib代理器

     1 public class CglibProxy implements MethodInterceptor {
     2 
     3     private Enhancer enhancer = new Enhancer();
     4     //设置被代理对象
     5     public Object getProxy(Class clazz){
     6     enhancer.setSuperclass(clazz);
     7     enhancer.setCallback(this);
     8     return enhancer.create();
     9     }
    10     @Override
    11     public Object intercept(Object obj, Method method,
    12             Object[] objects,
    13             MethodProxy methodProxy) throws Throwable {
    14         System.out.println("CGLig代理之前之前");
    15         Object invoke = methodProxy.invokeSuper(obj,objects);
    16         System.out.println("CGLig代理之前之后");
    17         return invoke;
    18     }
    19 
    20 }

    测试

    1 @Test
    2 public void test2(){
    3 //TODO CGlib实现
    4 CglibProxy cglibProxy = new CglibProxy();
    5 UserServiceImpl userService= (UserServiceImpl)
    6 cglibProxy.getProxy(UserServiceImpl.class);
    7 userService.login();
    8 }

    结果:

  • 相关阅读:
    编程中Visual Studio常用的快捷键
    解决博易博客后台文章管理页面无法显示分页的问题
    iReaper for WP7 顺利完工
    Visual Studio中web应用程序和网站区别
    SQL批处理
    SQL安全性
    实习之路之篇
    python 日志文件
    后端调用python遥感功能的方式
    C#使用系统的“显示桌面”功能(Shell.Application)
  • 原文地址:https://www.cnblogs.com/sueyyyy/p/9277160.html
Copyright © 2011-2022 走看看