温故知新: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 都较瘦 阅读(103) 评论(0)  编辑  收藏 所属分类: containerFramework


只有注册用户登录后才能发表评论。


网站导航:
 
<2024年11月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

公告

博客定位:囿于目前的水平,博客定位在记录自己的学习心得和随手的练习

常用链接

留言簿

随笔分类

随笔档案

文章分类

文章档案

搜索

最新评论

阅读排行榜

评论排行榜