shenghua

shenghua

Spring AOP 最终版实现
 

Spring AOP 最终版实现

引言


spring AOP 是面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。


其实,我们在系统中通过AOP实现权限、日志、异常等等非业务服务横切到我们的业务服务中,并且在不修改代码的形式,通常情况要是需要修改XML文件的,而且,当我们修改了非业务服务的时候,所有的业务服务中的代码都会修改。


代码实现:


目录:



AOPClient:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.client;  
  2.   
  3. import com.tgb.config.ClassPathXmlApplicationContext;  
  4. import com.tgb.config.ContainerBeans;  
  5. import com.tgb.dao.UserDao;  
  6. import com.tgb.domain.User;  
  7.   
  8. /** 
  9.  * AOP效果测试 
  10. * @ClassName: AopClientTest  
  11. * @Description:  
  12. * @author [qmx]  
  13. * @date  
  14. * 
  15.  */  
  16. public class AopClient {  
  17.   
  18.     public static void main(String[] args) throws Exception {  
  19.   
  20.         ContainerBeans factory = new ClassPathXmlApplicationContext();  
  21.   
  22.         User user = new User();  
  23.         user.setUserName("hanyankun");  
  24.   
  25.         Object proxyObject = factory.getBean("UserDao");  
  26.         UserDao userDao = (UserDao) proxyObject;  
  27.   
  28.         System.out.println("----启用aop一");  
  29.           
  30. //      userDao.before(user);  
  31.         userDao.update(user);  
  32.         userDao.save(user);  
  33.       
  34.   
  35.         //  
  36.   
  37.     }  
  38. }  

ClientTest:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.client;  
  2.   
  3. import com.tgb.config.ClassPathXmlApplicationContext;  
  4. import com.tgb.config.ContainerBeans;  
  5. import com.tgb.dao.StudentDao;  
  6. import com.tgb.dao.TeacherDao;  
  7. import com.tgb.daoImpl.StudentDaoImpl;  
  8. import com.tgb.domain.User;  
  9.   
  10. /** 
  11.  * 容器效果测试,测试增删对象 
  12. * @ClassName: ClientTest  
  13. * @Description: TODO(这里用一句话描述这个类的作用)  
  14. * @author [qmx]  
  15. * @date   
  16. * 
  17.  */  
  18. public class ClientTest {  
  19.   
  20.     public static void main(String[] args) throws Exception {  
  21.   
  22.         ContainerBeans containerBeans = new ClassPathXmlApplicationContext();// new  
  23.                                                                                 // 为  
  24.                                                                                 // 装配容器过程  
  25.   
  26.         User user = new User();  
  27.         user.setUserName("hanyankun"); // 参数设置  
  28.   
  29.         containerBeans.printAllbeanId();  
  30.         System.out.println("\n");  
  31.   
  32.         //增加对象  
  33.         StudentDao studentrDao = new StudentDaoImpl();  
  34.         containerBeans.put("studentDao", studentrDao);  
  35.   
  36.         System.out.println("----放入对象-studentDao---");  
  37.         containerBeans.printAllbeanId();  
  38.         System.out.println("\n");  
  39.           
  40.         //获取添加的对象  
  41.         System.out.println("-----拿出来的studentDao-执行方法--syaName-");  
  42.         StudentDao studentrDaoBean = (StudentDao) containerBeans.getBean("studentDao");  
  43.         TeacherDao teacherDao = (TeacherDao) containerBeans.getBean("TeacherDao");  
  44.           
  45.         teacherDao.save(user);  
  46.         studentrDaoBean.syaName();  
  47.         System.out.println("\n");  
  48.   
  49.         //删除对象测试  
  50.         System.out.println("-----删除对象TeacherDao 和 UserDao--");  
  51.         containerBeans.remove("TeacherDao");  
  52.         containerBeans.remove("UserDao");  
  53.         containerBeans.printAllbeanId();  
  54.     }  
  55.   
  56. }  

AspectCachBean:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.config;  
  2.   
  3.   
  4. /** 
  5. * @ClassName: AspectCachBean  
  6. * @Description:  
  7. * 缓存服务类,实现了对缓存的,前置,后置, 保存的方法 
  8. * @author [qmx]  
  9. * @date  
  10. * 
  11.  */  
  12. public class AspectCachBean {  
  13.       
  14.     /** 
  15.      *  
  16.     * @Title: cacheBefore  
  17.     * @Description: 缓存前置增强方法 
  18.     * @param @param proxy    代理参数 
  19.     * @return void    返回类型  
  20.     * @throws 
  21.      */  
  22.     public  void cacheBefore(Object proxy) {  
  23.   
  24.         System.out.println("---这是切入 类AspectCachBean  cacheBefore()-方法--");  
  25.     }  
  26.   
  27.     /** 
  28.      *  
  29.     * @Title: cacheAfter  
  30.     * @Description: 缓存后置增强方法 
  31.     * @param @param proxy    返回的代理参数 
  32.     * @return void    返回类型  
  33.     * @throws 
  34.      */  
  35.     public static void cacheAfter(Object proxy) {  
  36.         System.out.println("---这是切入 类AspectCachBean  cacheAfter()-方法--");  
  37.     }  
  38.       
  39.     /** 
  40.     * @Title: cacheSave  
  41.     * @Description: 缓存保存方法  
  42.     * @param @param proxy    代理参数 
  43.     * @return void    返回类型  
  44.     * @throws 
  45.      */  
  46.     public void cacheSave(Object proxy){  
  47.         System.out.println("---这是切入 类AspectCachBean  cacheSave()-方法--");  
  48.     }  
  49. }  

AspectCertifiyBean:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.config;  
  2.   
  3. /** 
  4.  *  
  5. * @ClassName: AspectCertifiyBean  
  6. * @Description: 认证服务类,提供了认证前, 认证后,认证保存的方法  
  7. * @author [qmx]  
  8. * @date  
  9. * 
  10.  */  
  11. public class AspectCertifiyBean {  
  12.   
  13.     /** 
  14.      *  
  15.     * @Title: certifiyBefore  
  16.     * @Description: 认证前置增强方法 
  17.     * @param @param proxy    被代理对象的参数  
  18.     * @return void    返回类型  
  19.     * @throws 
  20.      */  
  21.     public void certifiyBefore(Object proxy) {  
  22.   
  23.         System.out.println("---这是切入 类AspectCertifiyBean  certifiyBefore()-方法--");  
  24.     }  
  25.   
  26.     /** 
  27.      *  
  28.     * @Title: certifyAfter  
  29.     * @Description: 认证后置增强方法 
  30.     * @param @param proxy    被认证对象参数 
  31.     * @return void    返回类型  
  32.     * @throws 
  33.      */  
  34.     public  void certifyAfter(Object proxy) {  
  35.         System.out.println("---这是切入 类AspectCertifiyBean  certifyAfter()-方法--");  
  36.     }  
  37.   
  38.     /** 
  39.      *  
  40.     * @Title: certifySave  
  41.     * @Description:认证保存增强方法 
  42.     * @param @param proxy   被认证对象参数 
  43.     * @return void    返回类型  
  44.     * @throws 
  45.      */  
  46.     public void certifySave(Object proxy) {  
  47.         System.out.println("---这是切入 类AspectCertifiyBean  certifySave()-方法--");  
  48.     }  
  49. }  

ClassPathXmlApplicationContext:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.config;  
  2.   
  3. import java.lang.reflect.InvocationTargetException;  
  4. import java.lang.reflect.Method;  
  5. import java.util.HashMap;  
  6. import java.util.HashSet;  
  7. import java.util.Iterator;  
  8. import java.util.List;  
  9. import java.util.Map;  
  10. import java.util.Map.Entry;  
  11. import java.util.Set;  
  12. import java.util.TreeSet;  
  13.   
  14. import org.jdom.Document;  
  15. import org.jdom.Element;  
  16. import org.jdom.input.SAXBuilder;  
  17.   
  18. /** 
  19.  *  
  20. * @ClassName: ClassPathXmlApplicationContext  
  21. * @Description:  容器组装类, 装载 业务容器 和 服务容器。 分别将其中的 颗粒装载到各自的 beans 中 
  22. * 同时提供了对容器的增删,遍历等公共方法 
  23. * @author [qmx]  
  24. * @date   
  25. * 
  26.  */  
  27. public class ClassPathXmlApplicationContext implements ContainerBeans {  
  28.   
  29.     // 业务容器beans  
  30.     private Map<String, Object> businessBeans = new HashMap<String, Object>();  
  31.   
  32.     // 公共服务容器beans  
  33.     private Map<String, Object> aspectBeans = new HashMap<String, Object>();  
  34.   
  35.     //关系集合配置  
  36.     private Map<String, Object> relationBeans = new HashMap<String, Object>();  
  37.   
  38.     // 设置是否需要aop  
  39.     private boolean isAop = true;  
  40.   
  41.       
  42.     /** 
  43.      *  
  44.     * <p>Title: 构造函数 </p>  
  45.     * <p>Description: 构造函数加载所有配置文件,初始化每个容器内对象</p>  
  46.     * @throws Exception 
  47.      */  
  48.     public ClassPathXmlApplicationContext() throws Exception {  
  49.         SAXBuilder sb = new SAXBuilder();  
  50.   
  51.         // 扫描业务文档,将xml转为文档对象  
  52.         Document businessDoc = sb.build(Thread.currentThread().getContextClassLoader()  
  53.                 .getResourceAsStream("business.xml"));  
  54.   
  55.         // 扫描切入文档,将xml转为文档对象  
  56.         Document aspectDoc = sb.build(Thread.currentThread().getContextClassLoader()  
  57.                 .getResourceAsStream("aspecbeans.xml"));  
  58.   
  59.         //扫描关系文档,将xml转为文档对象  
  60.         Document reliationDoc = sb.build(Thread.currentThread().getContextClassLoader()  
  61.                 .getResourceAsStream("relationbean.xml"));  
  62.   
  63.         // 设置切面容器  
  64.         getAspectBeans(aspectDoc);  
  65.   
  66.         // 设置业务容器bean  
  67.         getBusinessDoc(businessDoc);  
  68.         //关系集合设置  
  69.         getRelationBeans(reliationDoc);  
  70.     }  
  71.   
  72.     /*** 
  73.      * 设置业务容器装配 
  74.      *  
  75.      * @param doc 
  76.      * @throws ClassNotFoundException 
  77.      * @throws IllegalAccessException 
  78.      * @throws InstantiationException 
  79.      * @throws SecurityException 
  80.      * @throws NoSuchMethodException 
  81.      * @throws InvocationTargetException 
  82.      * @throws IllegalArgumentException 
  83.      */  
  84.     private void getBusinessDoc(Document businessDoc) throws InstantiationException,  
  85.             IllegalAccessException, ClassNotFoundException, NoSuchMethodException,  
  86.             SecurityException, IllegalArgumentException, InvocationTargetException {  
  87.   
  88.         Element root = businessDoc.getRootElement();//读取文档根目录  
  89.         List list = root.getChildren("bean");  
  90.   
  91.         // 调用装备对象方法,装配业务对象  
  92.         putAllBeans(list, businessBeans);  
  93.   
  94.     }  
  95.   
  96.     /** 
  97.      * 获取关系集合中 业务容器与切面容器的关系 
  98.      * @param reliationDoc  
  99.      */  
  100.     private void getRelationBeans(Document reliationDoc) {  
  101.   
  102.         Element root = reliationDoc.getRootElement(); //读取文档根目录  
  103.         Element aopElement = (Element) root.getChildren("aop").get(0); //获取aop节点信息  
  104.   
  105.         isAop = Boolean.parseBoolean(aopElement.getAttributeValue("isaop")); //aop节点属性  
  106.         List aopBeforeList = root.getChildren("aspectbefore");// 前置增强节点  
  107.         List aopAfterList = root.getChildren("aspectafter");//后置增强  
  108.         //辨别增强节点是否有配置,放入bean关系容器  
  109.         if (aopBeforeList != null) {  
  110.             relationBeans.put("aspectbefore", aopBeforeList);  
  111.   
  112.         }  
  113.         if (aopAfterList != null) {  
  114.             relationBeans.put("aspectafter", aopAfterList);  
  115.         }  
  116.     }  
  117.   
  118.     /** 
  119.      * 设置切入容器装配对象 
  120.      *  
  121.      * @param aspectDoc 切入配置文件 
  122.      * @throws InstantiationException 
  123.      * @throws IllegalAccessException 
  124.      * @throws ClassNotFoundException 
  125.      * @throws InvocationTargetException 
  126.      * @throws IllegalArgumentException 
  127.      * @throws SecurityException 
  128.      * @throws NoSuchMethodException 
  129.      */  
  130.     private void getAspectBeans(Document aspectDoc) throws InstantiationException,  
  131.             IllegalAccessException, ClassNotFoundException, NoSuchMethodException,  
  132.             SecurityException, IllegalArgumentException, InvocationTargetException {  
  133.   
  134.         Element root = aspectDoc.getRootElement();  
  135.         List aspectElements = root.getChildren("aspectbean");// 读取切入配置文件  
  136.         putAllBeans(aspectElements, aspectBeans);  
  137.   
  138.     }  
  139.   
  140.     /** 
  141.      * 对象装配方法 
  142.      *  
  143.      * @param list 
  144.      *            读取的配置文件 
  145.      * @param allBeans 
  146.      *            设置装配的容器对象 
  147.      * @throws InstantiationException 
  148.      * @throws IllegalAccessException 
  149.      * @throws ClassNotFoundException 
  150.      * @throws NoSuchMethodException 
  151.      * @throws SecurityException 
  152.      * @throws IllegalArgumentException 
  153.      * @throws InvocationTargetException 
  154.      */  
  155.     public void putAllBeans(List list, Map<String, Object> allBeans)  
  156.             throws InstantiationException, IllegalAccessException,  
  157.             ClassNotFoundException, NoSuchMethodException, SecurityException,  
  158.             IllegalArgumentException, InvocationTargetException {  
  159.   
  160.         for (int i = 0; i < list.size(); i++) {  
  161.             //获取传入父亲节点中的每个子节点,为行element  
  162.             Element element = (Element) list.get(i);  
  163.             //获取子节点中的id属性  
  164.             String id = element.getAttributeValue("id");  
  165.             //获取子节点中的class属性  
  166.             String clazz = element.getAttributeValue("class");  
  167.             //实例化class  
  168.             Object o = Class.forName(clazz).newInstance();  
  169.   
  170.             //将实例化的class放入容器  
  171.             allBeans.put(id, o);  
  172.   
  173.             //for循环获取 bean中的 属性property  
  174.             for (Element propertyElement : (List<Element>) element  
  175.                     .getChildren("property")) {  
  176.                 //获取property属性中的name属性  
  177.                 String name = propertyElement.getAttributeValue("name"); // userDAO  
  178.                   
  179.                 //获取property属性中的ref属性  
  180.                 String bean = propertyElement.getAttributeValue("ref"); //   
  181.                   
  182.                 //获取子属性的试题  
  183.                 Object beanObject = allBeans.get(bean);// UserDAOImpl  
  184.   
  185.                 //调用 依赖实体中的set方法(为子实体的方法)  
  186.                 String methodName = "set" + name.substring(01).toUpperCase()  
  187.                         + name.substring(1);  
  188.   
  189.                 // 获取依赖注入对象的父类,如: userDaoImp 获取的为祈父类接口 userDao{eanObject.getClass().getInterfaces()[0]}  
  190.                 Method m = o.getClass().getMethod(methodName, //若依赖对象没有父类接口,该方法中的参数需要修改为类本身引用  
  191.                         beanObject.getClass().getInterfaces()[0]);  
  192.                 m.invoke(o, beanObject); //调用o中 set方法,设置注入对象  
  193.             }  
  194.   
  195.         }  
  196.     }  
  197.   
  198.     /** 
  199.      * 获取容器中指定对象 
  200.      *  
  201.      * @param id 
  202.      *            对象名称如: getBean("user") 
  203.      * @return 
  204.      */  
  205.     public Object getBean(String id) {  
  206.   
  207.         //读取是否配置aop节点属性,若是返回aop代理类  
  208.         if (!isAop) {  
  209.             return businessBeans.get(id);  
  210.         }  
  211.         return new JDKDynamicProxy(businessBeans.get(id), aspectBeans, businessBeans,relationBeans)  
  212.                 .getProxy();  
  213.     }  
  214.   
  215.     /** 
  216.      * 容器中放入对象 
  217.      *  
  218.      * @param k 
  219.      * @param v 
  220.      * @return 
  221.      */  
  222.     public Object put(String k, Object v) {  
  223.   
  224.         return businessBeans.put(k, v);  
  225.     }  
  226.   
  227.     /** 
  228.      * 打印容器中所有对象类型 
  229.      */  
  230.     public void printTypeName() {  
  231.   
  232.         Set<String> hashSet = new HashSet<String>();  
  233.         //set集合获取map中的所有值  
  234.         Set<Entry<String, Object>> entryset = businessBeans.entrySet();  
  235.         {  
  236.             //iterator获取迭代属性  
  237.             Iterator iterator = entryset.iterator();  
  238.             //while循环获取每个值  
  239.             while (iterator.hasNext()) {  
  240.                 Entry<String, Object> entry = (Entry<String, Object>) iterator.next();  
  241.                 hashSet.add(entry.getValue().getClass().getSimpleName());  
  242.             }  
  243.   
  244.         }  
  245.         for (String setType : hashSet) {  
  246.             System.out.println(setType);  
  247.         }  
  248.   
  249.     }  
  250.   
  251.     /** 
  252.      * 获取容器中所有对象 
  253.      *  
  254.      * @return Map<string(对象类型),Object(对象)> 
  255.      */  
  256.     public Map<String, Object> getAllBean() {  
  257.         Map<String, Object> beanList = new HashMap<String, Object>();  
  258.         //获取得带属性  
  259.         Iterator iterator = businessBeans.entrySet().iterator();  
  260.           
  261.         //while循环获取每个值  
  262.         while (iterator.hasNext()) {  
  263.             Entry<String, Object> entry = (Entry<String, Object>) iterator.next();  
  264.             beanList.put(entry.getValue().getClass().getSimpleName(), entry.getValue());  
  265.         }  
  266.         return beanList;  
  267.   
  268.     }  
  269.   
  270.     /*** 
  271.      * 删除指定对象 
  272.      */  
  273.     public void remove(String id) {  
  274.         businessBeans.remove(id);  
  275.   
  276.     }  
  277.   
  278.     /*** 
  279.      * 打印所有注入对象 
  280.      */  
  281.     public void printAllbeanId() {  
  282.         Set<Entry<String, Object>> entryset = businessBeans.entrySet();  
  283.   
  284.         Set<String> linkSet = new TreeSet<String>();  
  285.         {  
  286.             Iterator iterator = entryset.iterator();  
  287.             while (iterator.hasNext()) {  
  288.                 Entry<String, Object> entry = (Entry<String, Object>) iterator.next();  
  289.                 linkSet.add(entry.getKey());  
  290.                 // System.out.println(entry.getKey());  
  291.             }  
  292.   
  293.             System.out.println("容器中含有对象是" + this.size() + "个,分别是:");  
  294.             System.out.println(linkSet.toString());  
  295.               
  296.         }  
  297.   
  298.     }  
  299.   
  300.     /** 
  301.      * 获取容器中对象的个数 
  302.      */  
  303.     public int size() {  
  304.         return businessBeans.size();  
  305.     }  
  306. }  


ContainerBeans:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.config;  
  2.   
  3. import java.util.Map;  
  4.   
  5. /** 
  6.  *  
  7. * @ClassName: ContainerBeans  
  8. * @Description: 容器接口,提供容器公共服务方法, 增加,删除,遍历,获取对象,遍历类型,容器大小等方法 
  9. * @author [qmx]  
  10. * @date  
  11. * 
  12.  */  
  13. public interface ContainerBeans {  
  14.       
  15.     /** 
  16.      * 获取容器中指定对象 
  17.      *  
  18.      * @param id 
  19.      *            对象名称如: getBean("user") 
  20.      * @return 
  21.      */  
  22.     public Object getBean(String id);  
  23.   
  24.       
  25.     /** 
  26.      * 容器中放入对象 
  27.      *  
  28.      * @param k 
  29.      * @param v 
  30.      * @return 
  31.      */  
  32.     public Object put(String k, Object v);  
  33.   
  34.       
  35.     /** 
  36.      * 打印容器中所有对象类型 
  37.      */  
  38.     public void printTypeName();  
  39.   
  40.       
  41.     /** 
  42.      * 获取容器中所有对象 返回类型 Map<string(对象类型),Object(对象)> 
  43.      * @return Map<string(对象类型),Object(对象)> 
  44.      */  
  45.     public Map<String, Object> getAllBean();  
  46.       
  47.       
  48.     /** 
  49.      * 获取容器所有bean 
  50.      */  
  51.     public void printAllbeanId();  
  52.   
  53.       
  54.     /** 
  55.      *  
  56.     * @Title: remove  
  57.     * @Description: 删除容器指定对象 
  58.     * @param @param id    删除对象的id  
  59.     * @return void    返回类型  
  60.     * @throws 
  61.      */  
  62.     public void remove(String id);  
  63.   
  64.       
  65.     /** 
  66.      * 容器中对象的数量 
  67.      * @return 
  68.      */  
  69.     public int size();  
  70. }  

JDKDynamicProxy:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.config;  
  2.   
  3. import java.lang.reflect.InvocationHandler;  
  4. import java.lang.reflect.InvocationTargetException;  
  5. import java.lang.reflect.Method;  
  6. import java.lang.reflect.Proxy;  
  7. import java.util.Iterator;  
  8. import java.util.List;  
  9. import java.util.Map;  
  10. import java.util.Map.Entry;  
  11.   
  12. import org.jdom.Element;  
  13.   
  14. /** 
  15.  *  
  16. * @ClassName: JDKDynamicProxy  
  17. * @Description: AOP实现对业务容器 的增强,对业务容器中每个对象增强 服务类中的方法,根据 关系容器配置, 
  18. * 实现特性方法增强 
  19. * @author [qmx]  
  20. * @date  
  21. * 
  22.  */  
  23. public class JDKDynamicProxy implements InvocationHandler {  
  24.   
  25.     private Object target;//被代理对象  
  26.   
  27.     private Map<String, Object> aspectBeans; // 服务容器  
  28.     private Map<String, Object> businessBeans;// 业务容器  
  29.     private Map<String, Object> relationBeans;// 关系容器  
  30.   
  31.     /*** 
  32.      *  
  33.      * @param target 
  34.      *            被代理对象 
  35.      * @param aspectBeans 
  36.      *            切容器 
  37.      * @param businessBeans 
  38.      *            业务容器 
  39.      * @param relationBeans 
  40.      *            关系集合 
  41.      */  
  42.     public JDKDynamicProxy(Object target, Map<String, Object> aspectBeans,  
  43.             Map<String, Object> businessBeans, Map<String, Object> relationBeans) {  
  44.         this.target = target;  
  45.         this.aspectBeans = aspectBeans;  
  46.         this.businessBeans = businessBeans;  
  47.         this.relationBeans = relationBeans;  
  48.     }  
  49.   
  50.     /** 
  51.     * @Title: getProxy  
  52.     * @Description: 创建被代理对象  
  53.     * @param @return     
  54.     * @return T    返回类型  被代理对象 类型 
  55.     * @throws 
  56.      */  
  57.     @SuppressWarnings("unchecked")  
  58.     public <T> T getProxy() {  
  59.         return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target  
  60.                 .getClass().getInterfaces(), this);  
  61.     }  
  62.   
  63.     // 回调注册切入对象方法  
  64.     @Override  
  65.     public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
  66.   
  67.         List beforeList = (List) relationBeans.get("aspectbefore");// 获取关系容器中的关系  
  68.         invokeAspectName(beforeList, method, args);// 调用切面类中匹配方法  
  69.         Object result = method.invoke(target, args);// 调用 被代理类本身方法  
  70.   
  71.         return result;  
  72.     }  
  73.   
  74.     /** 
  75.      * 拦截方法匹配规则 
  76.      *  
  77.      * @param beforeList 
  78.      *            拦截器的所有对象 
  79.      * @param method 
  80.      * @param args 
  81.      * @throws NoSuchMethodException 
  82.      * @throws SecurityException 
  83.      * @throws IllegalAccessException 
  84.      * @throws IllegalArgumentException 
  85.      * @throws InvocationTargetException 
  86.      */  
  87.     public void invokeAspectName(List beforeList, Method method, Object[] args)  
  88.             throws NoSuchMethodException, SecurityException, IllegalAccessException,  
  89.             IllegalArgumentException, InvocationTargetException {  
  90.           
  91.         //判断关系容器中是否指定了特性方法拦截,若无,则对 代理对象 执行所有服务类方法增强  
  92.         if (beforeList != null && beforeList.size() != 0) {  
  93.   
  94.             for (int i = 0; i < beforeList.size(); i++) {  
  95.   
  96.                 Element element = (Element) beforeList.get(i);  
  97.                 String aspectClass = element.getAttributeValue("aspectId");// 获取容器中切入类名称  
  98.                 String aspectName = element.getAttributeValue("aspectMethod");// 执行的切入方法  
  99.                   
  100.                 if (aspectBeans.get(aspectClass) == null) {  
  101.                     System.out.println("未找到" + aspectClass + "切入类,请查看配置的切入类名称是否正确");  
  102.                     return;  
  103.                 }  
  104.                   
  105.                 Class clazz = aspectBeans.get(aspectClass).getClass(); // 获取切入类  
  106.                 String elementMethod = element.getAttributeValue("method");// 获取被切入类方法  
  107.   
  108.                 //1  关系容器中某个拦截配置,若未声明执行某个服务类中的方法,则执行所有服务类中方法,  
  109.                 //2 若未指定某个拦截方法,但指定了被拦截对象的方法,则所有服务类只对该方法拦截  
  110.                 //3   
  111.                 if (aspectName == null) {  
  112.   
  113.                     //声明了拦截某个对象方法,执行指定方法拦截  
  114.                     if (method.getName() != null) {  
  115.                         if (method.getName().equals(elementMethod)) {  
  116.                             //,执行该服务类中所有方法  
  117.                             getAllMethod(clazz, aspectClass, args);  
  118.                         }  
  119.   
  120.                     }  
  121.                     //执行所有服务类中的所有方法  
  122.                     aspactAllClass(aspectClass, args == null ? new Object[1] : args);  
  123.                       
  124.                 } else {  
  125.                     // 声明切入方法,则执行指定切入方法  
  126.                     if (method.getName().equals(elementMethod)) {  
  127.                         Method jinectmethod = clazz.getMethod(aspectName, Object.class); // 反射调用切入类方法  
  128.                         jinectmethod.invoke(aspectBeans.get(aspectClass),  
  129.                                 args == null ? new Object[1] : args);  
  130.                     }  
  131.                     aspactAllClass(aspectClass, args == null ? new Object[1] : args);  
  132.                 }  
  133.   
  134.             }  
  135.   
  136.         } else {  
  137.   
  138.             //默认执行所有服务类中的方法增强  
  139.             Iterator aspectClass = aspectBeans.entrySet().iterator();  
  140.             while (aspectClass.hasNext()) {  
  141.                 Entry<String, Object> entry = (Entry<String, Object>) aspectClass.next();  
  142.                 Class clazz = entry.getValue().getClass();// 获取服务类  
  143.                 // 获取服务类中的所有公共方法  
  144.                 Method[] methods = clazz.getDeclaredMethods();  
  145.                 for (int j = 0; j < methods.length; j++) {  
  146.   
  147.                     // 反射获取服务类中每个方法名称,获取该服务类方法  
  148.                     Method jinectmethod = clazz.getMethod(methods[j].getName(),  
  149.                             Object.class);  
  150.                     jinectmethod.invoke(entry.getValue(), args == null ? new Object[1]  
  151.                             : args);  
  152.                 }  
  153.             }  
  154.         }  
  155.     }  
  156.   
  157.   
  158.     /** 
  159.      *  
  160.     * @Title: aspactAllClass  
  161.     * @Description: 除了自身,执行其他所有服务类中方法。 
  162.     * @param @param aspectId 
  163.     * @param @param args 
  164.     * @param @throws NoSuchMethodException 
  165.     * @param @throws SecurityException 
  166.     * @param @throws IllegalAccessException 
  167.     * @param @throws IllegalArgumentException 
  168.     * @param @throws InvocationTargetException    设定文件  
  169.     * @return void    返回类型  
  170.     * @throws 
  171.      */  
  172.     public void aspactAllClass(String aspectId, Object[] args)  
  173.             throws NoSuchMethodException, SecurityException, IllegalAccessException,  
  174.             IllegalArgumentException, InvocationTargetException {  
  175.         Iterator aspectClass = aspectBeans.entrySet().iterator();  
  176.         while (aspectClass.hasNext()) {  
  177.             Entry<String, Object> entry = (Entry<String, Object>) aspectClass.next();  
  178.               
  179.             //  
  180.             if (!aspectId.equals(entry.getKey())) {  
  181.                 Class clazz = entry.getValue().getClass();// 获取切入类  
  182.                 Method[] methods = clazz.getDeclaredMethods();  
  183.                 for (int j = 0; j < methods.length; j++) {  
  184.                     // 反射获取服务类中每个方法名称,获取该服务类方法  
  185.                     Method jinectmethod = clazz.getMethod(methods[j].getName(),  
  186.                             Object.class);  
  187.                     // 反射调用切入类方法  
  188.                     jinectmethod.invoke(entry.getValue(), args == null ? new Object[1]  
  189.                             : args);  
  190.   
  191.                 }  
  192.             }  
  193.         }  
  194.     }  
  195.   
  196.   
  197.     /** 
  198.      *  
  199.     * @Title: getAllMethod  
  200.     * @Description:  执行某个服务类中的所有方法, 
  201.     * @param @param clazz 服务类 
  202.     * @param @param aspectClass aop关系集合中设定执行 拦截的方法 
  203.     * @param @param args 被拦截对象的参数 
  204.     * @param @throws IllegalAccessException 
  205.     * @param @throws IllegalArgumentException 
  206.     * @param @throws InvocationTargetException 
  207.     * @param @throws NoSuchMethodException 
  208.     * @param @throws SecurityException    设定文件  
  209.     * @return void    返回类型  
  210.     * @throws 
  211.      */  
  212.     public void getAllMethod(Class clazz, String aspectClass, Object[] args)  
  213.             throws IllegalAccessException, IllegalArgumentException,  
  214.             InvocationTargetException, NoSuchMethodException, SecurityException {  
  215.           
  216.         // 获取服务类中的所有公共方法  
  217.         Method[] methods = clazz.getDeclaredMethods();  
  218.         for (int j = 0; j < methods.length; j++) {  
  219.   
  220.             // 反射获取服务类中每个方法名称,获取该服务类方法  
  221.             Method jinectmethod = clazz.getMethod(methods[j].getName(), Object.class);  
  222.             // 反射调用服务类中方法  
  223.             jinectmethod.invoke(aspectBeans.get(aspectClass),  
  224.                     args == null ? new Object[1] : args);  
  225.   
  226.         }  
  227.     }  
  228. }  

StudentDao:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.dao;  
  2.   
  3.   
  4. /** 
  5.  * studendao,打印方法 
  6. * @ClassName: StudentDao  
  7. * @Description: TODO(这里用一句话描述这个类的作用)  
  8. * @author [qmx]  
  9. * @date  
  10. * 
  11.  */  
  12. public interface StudentDao {  
  13.   
  14.     public void syaName();  
  15. }  

TeacherDao:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.dao;  
  2.   
  3. import com.tgb.domain.User;  
  4. /* 
  5.  * TeacherDao对象,增加删除,保存方法 
  6.  */  
  7.   
  8. public interface TeacherDao {  
  9.   
  10.     void save(User user);  
  11.       
  12.     void update(User user);  
  13.       
  14.     public void delete( User user);  
  15.   
  16. }  

UserDao:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.dao;  
  2.   
  3. import com.tgb.domain.User;  
  4. /* 
  5.  * userdao对象,增加删除,保存方法 
  6.  */  
  7. public interface UserDao {  
  8.   
  9.     void save(User user);  
  10.       
  11.     void update(User user);  
  12.       
  13.     public void delete( User user);  
  14.       
  15. }  

StudentDaoImpl:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.daoImpl;  
  2.   
  3. import com.tgb.dao.StudentDao;  
  4. /* 
  5.  * StudentDaoImpl对象,打印方法 
  6.  */  
  7. public class StudentDaoImpl implements StudentDao {  
  8.   
  9.     @Override  
  10.     public void syaName() {  
  11.         System.out.println("----my name is hanyk--");  
  12.           
  13.     }  
  14.   
  15. }  

TeacherDaoImpl:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.daoImpl;  
  2.   
  3. import com.tgb.dao.TeacherDao;  
  4. import com.tgb.dao.UserDao;  
  5. import com.tgb.domain.User;  
  6. /* 
  7.  * TeacherDaoImpl对象,增加删除,保存方法 
  8.  */  
  9. public class TeacherDaoImpl implements TeacherDao {  
  10.   
  11.     @Override  
  12.     public void save(User user) {  
  13.     System.out.println( "这是业务类 "+this.getClass()+"-----的 save()方法-----");  
  14.           
  15.     }  
  16.       
  17.     @Override  
  18.     public void update(User user) {  
  19.         System.out.println( "这是业务类 "+this.getClass()+"-----的 update()方法-----");  
  20.           
  21.     }  
  22.   
  23.     @Override  
  24.     public void delete(User user) {  
  25.         System.out.println( "这是业务类 "+this.getClass()+"-----的 delete()方法-----");  
  26.           
  27.     }  
  28.   
  29. }  

UserDaoImpl:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.daoImpl;  
  2.   
  3. import com.tgb.dao.UserDao;  
  4. import com.tgb.domain.User;  
  5. /* 
  6.  * userdao对象,增加删除,保存方法 
  7.  */  
  8. public class UserDaoImpl implements UserDao {  
  9.   
  10.     @Override  
  11.     public void save(User user) {  
  12.     System.out.println( "这是业务类 "+this.getClass()+"-----的 userDao.save()方法-----");  
  13.           
  14.     }  
  15.   
  16.   
  17.     @Override  
  18.     public void update(User user) {  
  19.         System.out.println( "这是业务类 "+this.getClass()+"-----的 userDao.update()方法-----");  
  20.           
  21.     }  
  22.   
  23.     @Override  
  24.     public void delete(User user) {  
  25.         System.out.println( "这是业务类 "+this.getClass()+"-----的 userDao.delete()方法-----");  
  26.           
  27.     }  
  28.   
  29. }  

User:


[java] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. package com.tgb.domain;  
  2.   
  3. public class User {  
  4.   
  5.     private String userName;  
  6.     private String password;  
  7.     public String getUserName() {  
  8.         return userName;  
  9.     }  
  10.     public void setUserName(String userName) {  
  11.         this.userName = userName;  
  12.     }  
  13.     public String getPassword() {  
  14.         return password;  
  15.     }  
  16.     public void setPassword(String password) {  
  17.         this.password = password;  
  18.     }  
  19.       
  20. }  

aspectbeans.xml:


[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <!--该文件 对是服务类的配置,所有服务类都需要在该文件进行注册-->  
  2. <beans>  
  3.     <!--服务类配置容器,配置缓存服务类,全名称 -->  
  4.     <aspectbean id="aspectCachBean" class="com.tgb.config.AspectCachBean"></aspectbean>  
  5.   
  6.   
  7. <!--     <aspectbean id="aspectCertifiyBean" class="com.tgb.configra.AspectCertifiyBean"></aspectbean> -->  
  8.   
  9. </beans>  

business.xml:


[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <!--该文件是业务类的配置-->  
  2. <beans>  
  3.   
  4.     <!--用户bean注入-->  
  5.     <bean id="UserDao" class="com.tgb.daoImpl.UserDaoImpl" />  
  6.     <!--教师bean注入-->  
  7.     <bean id="TeacherDao" class="com.tgb.daoImpl.TeacherDaoImpl" />  
  8.       
  9. </beans>  

relationbean.xml:


[html] view plain copy
 print?在CODE上查看代码片派生到我的代码片
  1. <!--aop关系配置文件-->  
  2. <beans>     
  3.     <!-- 是否启用aop -->  
  4.     <aop isaop="true"></aop>  
  5.       
  6. <!-- 配置业务颗粒和服务类的增强关系method为业务类匹配的方法,可用正则表达式进行(未实现) ,aspectMethod为服务类拦截方法 -->  
  7.     <aspectbefore  aspectId="aspectCachBean" method="update"  aspectMethod="cacheSave"  ></aspectbefore>  
  8.       
  9. </beans>  
阅读更多
想对作者说点什么? 我来说一句

Spring通过XML实现AOP

2018年04月18日 4.7MB 下载

Spring实现AOP以及AOP的定义

2010年12月10日 616KB 下载

Spring通过注解实现AOP

2018年04月17日 4.7MB 下载

spring aop spring aop

2011年06月29日 23KB 下载

Spring实现AOP的4种方式

2015年10月25日 4.04MB 下载

没有更多推荐了,返回首页

不良信息举报

Spring AOP 最终版实现

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭