• Spring 容器AOP的实现原理——动态代理


    参考:http://wiki.jikexueyuan.com/project/ssh-noob-learning/dynamic-proxy.html(from极客学院

    一、介绍

    Spring的动态代理有两种:一是JDK的动态代理;另一个是cglib动态代理(通过修改字节码来实现代理)。

    今天主要讨论JDK动态代理的方式。

    JDK的代理方式主要就是通过反射跟动态编译来实现的,主要搭配InvocationHandler和Proxy来实现,下面的例子中使用了两层代理(即代理上加了一层代理)。

    二、实例

    1. 公共接口

    1 package com.tgb.proxy;
    2 
    3 public interface UserMgr {
    4 
    5     void addUser();
    6     void delUser();
    7     
    8 }

    2. 实现类

     1 package com.tgb.proxy;
     2 
     3 public class UserMgrImpl implements UserMgr {
     4 
     5     @Override
     6     public void addUser() {
     7         System.out.println("添加用户....");
     8     }
     9 
    10     @Override
    11     public void delUser() {
    12         System.out.println("删除用户.....");
    13     }
    14 
    15 }

    3. TransactionHandler(InvocationHandler的实现)

     1 package com.tgb.proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 
     6 public class TransactionHandler implements InvocationHandler {
     7 
     8     private Object target;
     9     
    10     public TransactionHandler(Object target){
    11         super();
    12         this.target = target;
    13     }
    14 
    15     @Override
    16     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    17         
    18         System.out.println("开启事务...");
    19         
    20         method.invoke(target);
    21         
    22         System.out.println("提交事务...");
    23         
    24         return null;
    25     }
    26     
    27 
    28 }

    4. TimeHandler(InvocationHandler的实现)

     1 package com.tgb.proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Method;
     5 import java.util.Calendar;
     6 
     7 public class TimeHandler implements InvocationHandler {
     8 
     9     private Object target;
    10 
    11     public TimeHandler(Object target) {
    12         super();
    13         this.target = target;
    14     }
    15 
    16     @Override
    17     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    18 
    19         Calendar calendar = Calendar.getInstance();
    20 
    21         System.out.println("start time:" + calendar.get(Calendar.HOUR_OF_DAY));
    22 
    23         method.invoke(target);
    24 
    25         System.out.println("end time:" + calendar.get(Calendar.HOUR_OF_DAY));
    26 
    27         return null;
    28     }
    29 
    30 }

    5. 测试类

     1 package com.tgb.proxy;
     2 
     3 import java.lang.reflect.InvocationHandler;
     4 import java.lang.reflect.Proxy;
     5 
     6 public class Client {
     7 
     8     public static void main(String[] args) {
     9 
    10         UserMgr userMgr = new UserMgrImpl();
    11 
    12         // 1.第一层代理----------通过动态代理,添加事务处理
    13         InvocationHandler handler = new TransactionHandler(userMgr);
    14         UserMgr userMgrProxy = (UserMgr) Proxy.newProxyInstance(userMgr.getClass().getClassLoader(),
    15                 userMgr.getClass().getInterfaces(), handler);
    16 
    17         // 2.第二层代理----------通过动态代理,添加时间处理
    18         InvocationHandler handler2 = new TimeHandler(userMgrProxy);
    19         UserMgr userMgrProxy2 = (UserMgr) Proxy.newProxyInstance(userMgrProxy.getClass().getClassLoader(),
    20                 userMgrProxy.getClass().getInterfaces(), handler2);
    21 
    22         userMgrProxy2.addUser();
    23 
    24         System.out.println("========================================");
    25 
    26         userMgrProxy2.delUser();
    27 
    28     }
    29 }

    输出结果:

    start time:Tue Aug 09 23:54:54 CST 2016
    开启事务...
    添加用户....
    提交事务...
    end time:Tue Aug 09 23:54:54 CST 2016
    ========================================
    start time:Tue Aug 09 23:54:54 CST 2016
    开启事务...
    删除用户.....
    提交事务...
    end time:Tue Aug 09 23:54:54 CST 2016
  • 相关阅读:
    DIV高度设置全屏
    Yii2使用PHPExcel读取excel
    关于linux centos7 vmware 和windows7 文件共享笔记
    mysql rpm包安装
    linux crontab 计划任务脚本
    linux php5.6 安装
    linux上安装php phpredis扩展
    让微信小程序每次请求的时候不改变session_id的方法
    mysql主从配置
    mysql存储过程之游标遍历数据表
  • 原文地址:https://www.cnblogs.com/jiangyi-uestc/p/5755133.html
Copyright © 2020-2023  润新知