溫故知新:spring_05動態代理實現AOP

          使用動態代理實現AOP,就無需像靜態代理那樣一對一的去創建代理類,而是創建一個通用的代理類去接收并創建需要代理的對象,并在代理對象中拓展被代理對象的功能。就比如,我們需要拓展DAO所有實現類的功能,在每個實現類的每個方法中都添加記錄日志的功能。

          IUserDao 
          1 package org.duyt.dao;
          2 import org.duyt.annotation.LogMsg;
          3 public interface IUserDao {
          4     public void add();
          5 }
          UserDao
           1 package org.duyt.dao.impl;
           2 import org.duyt.dao.IUserDao;
           3 import org.springframework.context.annotation.Scope;
           4 import org.springframework.stereotype.Repository;
           5 @Repository("userDao")
           6 @Scope("singleton")
           7 public class UserDao implements IUserDao {
           8     public void add() {
           9         System.out.println("用戶增加方法");
          10     }
          11 }
          創建代理類,這個代理類的主要作用就是為傳入的被代理對象,添加方法執行前的記錄日志功能
           1 package org.duyt.dao.proxy;
           2 
           3 import java.lang.reflect.InvocationHandler;
           4 import java.lang.reflect.Method;
           5 import java.lang.reflect.Proxy;
           6 
           7 public class DaoLoggerProxy implements InvocationHandler {
           8     
           9     //使用屬性保存,要代理的目標對象
          10     private Object target;
          11     
          12     //私有空構造
          13     private DaoLoggerProxy(){
          14     }
          15     
          16     //工廠方法
          17     public static Object getInstance(Object o){
          18         DaoLoggerProxy proxy = new DaoLoggerProxy();
          19         //保存要代理的對象
          20         proxy.target = o;
          21         //創建傳入對象的代理對象
          22         Object result = Proxy.newProxyInstance(o.getClass().getClassLoader(), o.getClass().getInterfaces(), proxy);
          23         //返回創建的代理對象
          24         return result;
          25     }
          26 
          27     //被代理對象在調用任何方法的時候,都會先調用代理類的invoke方法,那么在此,就可以在被代理對象方法執行的任意一個流程添加需要的功能
          28     public Object invoke(Object proxy, Method method, Object[] args)
          29             throws Throwable {
          30         
          31         /*if (method.isAnnotationPresent(XXX.class)) {
          32             可以自定義注解給特定方法,規定這些方法執行哪些特殊的操作
          33         }*/
          34         
          35         /*if (method.getName().startsWith("add")) {
          36             對某些約定了方法名的方法拓展需要的功能
          37         }*/
          38         
          39         /*try {
          40             Object obj = method.invoke(target, args);
          41         } catch (Exception e) {
          42             記錄異常的操作,或者回滾操作
          43         }*/
          44         
          45         //在被代理對象方法執行之前進行某些操作
          46         
          47         System.out.println("---->模擬記錄日志<----");
          48         Object obj = method.invoke(target, args);
          49         
          50         //之后進行某些操作
          51         
          52         return obj;
          53     }
          54 
          55 }
          56 
          beans.xml需要作出如下配置
           1 <?xml version="1.0" encoding="UTF-8"?>
           2 <beans xmlns="http://www.springframework.org/schema/beans"
           3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           4     xmlns:context="http://www.springframework.org/schema/context"
           5     xsi:schemaLocation="http://www.springframework.org/schema/beans 
           6                         http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
           7                         http://www.springframework.org/schema/context
           8                         http://www.springframework.org/schema/context/spring-context-3.0.xsd">
           9 
          10     <!-- 開啟注解 -->
          11     <context:annotation-config/>
          12     <!-- 指定哪些需要加入掃描 -->
          13     <context:component-scan base-package="org.duyt.*"/>
          14 
          15     <!-- 限定了私有構造方法,所以不能直接創建代理類,需要傳入被代理對象,使用工廠方法返回代理對象,因此需要指定工廠方法,并且該方法在class屬性指向的類中要為靜態方法 -->
          16     <bean id="daoLoggerProxy" class="org.duyt.dao.proxy.DaoLoggerProxy" factory-method="getInstance">
          17         <!-- 通過構造器參數來傳入被代理的對象 -->
          18         <constructor-arg ref="userDao"/>
          19     </bean>
          20     
          21 </beans>
          配置完畢之后,使用代理注入userDao,@Resource(name = "daoLoggerProxy"),測試
           1 package org.duyt.test;
           2 
           3 import org.duyt.action.UserAction;
           4 import org.junit.Test;
           5 import org.springframework.beans.factory.BeanFactory;
           6 import org.springframework.context.support.ClassPathXmlApplicationContext;
           7 
           8 public class IocTest {
           9 
          10     private BeanFactory factory = new ClassPathXmlApplicationContext("beans.xml");
          11     
          12     @Test
          13     public void test(){
          14         //測試代理類拓展的功能
          15         UserAction ua = (UserAction) factory.getBean("userAction");
          16         ua.addUser();
          17     }
          18     
          19 }
          20 
          結果:
          ---->模擬記錄日志<----
          用戶增加方法

          posted on 2014-11-04 23:24 都較瘦 閱讀(106) 評論(0)  編輯  收藏 所屬分類: containerFramework

          <2025年6月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          293012345

          導航

          統計

          公告

          博客定位:囿于目前的水平,博客定位在記錄自己的學習心得和隨手的練習

          常用鏈接

          留言簿

          隨筆分類

          隨筆檔案

          文章分類

          文章檔案

          搜索

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 绥中县| 庆云县| 乃东县| 尚义县| 道真| 安徽省| 垫江县| 通州区| 逊克县| 珲春市| 龙川县| 花垣县| 宜宾县| 红原县| 增城市| 鄂州市| 龙川县| 德阳市| 平武县| 罗田县| 潞城市| 吴川市| 松原市| 保山市| 盘山县| 蒙自县| 启东市| 临夏县| 广东省| 莫力| 漳州市| 会东县| 莎车县| 涞水县| 阳谷县| 阳山县| 巴南区| 衡阳县| 防城港市| 航空| 略阳县|