spring学习笔记(8)AOP增强(advice)配置与应用
2016-03-20 21:14
741 查看
增强类型
增强(advice)主要包括如下五种类型1. 前置增强(BeforeAdvice):在目标方法执行前实施增强
2. 后置增强(AfterReturningAdvice):在目标方法执行后实施增强
3. 环绕增强(MrthodInterceptor):在目标方法执行前后实施增强
4. 异常抛出增强(ThrowsAdvice):在目标方法抛出异常后实施增强
5. 引介增强(IntroductionIntercrptor):在目标类中添加一些新的方法和属性
前置增强和后置增强配置
下面通过实例代码来分析前置增强,假如现在要作日志记录,记录了什么人调用什么方法。前置增强的配置可归纳为如下步骤:1. 配置代理接口:
package test.aop; public interface ITarget { String speak(String name); }
2. 定义被代理对象
package test.aop; //被代理对象 public class Target implements ITarget{ private static final String name = "zenghao"; @Override public String speak(Integer age){ System.out.println("hello I'm " + age + " years old"); return "I'm return value"; } public static String getName() { return name; } }
3. 配置增强
package test.aop; import java.lang.reflect.Method; import org.springframework.aop.MethodBeforeAdvice; public class BeforeAdvice implements MethodBeforeAdvice { /** * @param method:目标类的方法 * args: 目标类的方法入参 * obj:目标类实例 * */ @Override public void before(Method method, Object[] args, Object target) throws Throwable { if(target instanceof Target){ System.out.println("前置日志记录: " + ((Target)target).getName() + "调用了" + method.getName() + "方法,传入参数为:" + args[0] ); } } } /*------------------分割线---------------------*/ package test.aop; import java.lang.reflect.Method; import org.springframework.aop.AfterReturningAdvice; import org.springframework.aop.MethodBeforeAdvice; public class AfterAdvice implements AfterReturningAdvice { /** * @param * returnValue 返回值 * method:目标类的方法 * args: 目标类的方法入参 * obj:目标类实例 * */ @Override public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable { if(target instanceof Target){ System.out.println("后置日志记录: " + ((Target)target).getName() + "调用了" + method.getName() + "方法,返回值为:" + returnValue ); } } }
4. 配置代理对象ProxyFactoryBean
PeoxyFactoryBean是FactoryBean的实现类,我们知道FactoryBean负责初始化Bean,而ProxyFactoryBean则负责为其他Bean创建代理实例,通过在xml中配置后注入使用<!-- 配置被代理对象 --> <bean id="mytarget" class="test.aop.Target" /> <!-- 配置前置增强 --> <bean id="myBeforeAdvice" class="test.aop.BeforeAdvice" /> <!-- 配置后置增强 --> <bean id="myAfterReturnAdvice" class="test.aop.AfterAdvice" /> <!-- 配置代理对象 --> <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean" > <!-- 配置代理接口集 --> <property name="proxyInterfaces" value="test.aop.ITarget" /> <!-- 代理目标对象需要实现的接口,可以通过<list>标签设置多个 --> <!-- 把通知织入代理对象 --> <property name="interceptorNames" > <list> <idref bean="myBeforeAdvice"/> <idref bean="myAfterReturnAdvice"/> </list> </property><!-- 配置实现了Advice增强接口的Bean,以bean名字进行指定 --> <property name="targetName" value="mytarget"></property><!-- 代理的目标对象 --> </bean>
5. 测试
package test.aop; import org.junit.Before; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class TestAOP { private ApplicationContext ac; @Before public void setup(){ ac = new ClassPathXmlApplicationContext("classpath:test/aop/aop.xml"); } @Test public void test(){ ITarget iTarget = (ITarget) ac.getBean("proxyFactoryBean"); iTarget.speak(21); } }
测试打印:
前置日志记录: zenghao调用了speak方法,传入参数为:21
hello I’m 21 years old
后置日志记录: zenghao调用了speak方法,返回值为:I’m return value
环绕增强配置
在前面的基础上,我们新增环绕增强类:package test.aop; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class AroundAdvice implements MethodInterceptor { @Override public Object invoke(MethodInvocation invocation) throws Throwable { System.out.println(invocation.getArguments()[0] + "——" + invocation.getStaticPart() + "——" + invocation.getThis().getClass() + "——" + invocation.getMethod().getName()); invocation.proceed();//反射调用目标对象方法 System.out.println("环绕增强调用结束"); return "I'm around return value"; } }
在aop.xml中类似前置增强增加环绕增强配置,运行测试方法,得到结果:
前置日志记录: zenghao调用了speak方法,传入参数为:21
21——public abstract java.lang.String test.aop.ITarget.speak(java.lang.Integer)——class test.aop.Target——speak
hello I’m 21 years old
环绕增强调用结束
后置日志记录: zenghao调用了speak方法,返回值为:I’m around return value
从以上我们能看到,当同时使用环绕增强和前后置增强时,它们的执行顺序
异常增强配置
常用场景为配置实物管理器,当进行数据库操作的方法发生异常时,可被异常增强捕获,进行失误回滚等操作。一个抛出异常增强的实例如下所示:package test.aop; import java.lang.reflect.Method; import java.sql.SQLException; import org.springframework.aop.ThrowsAdvice; public class ExceptionAdvice implements ThrowsAdvice { public void AfterThrowing(SQLException e){ System.out.println(e.getMessage()); } public void AfterThrowing(RuntimeException e){ System.out.println(e.getMessage()); } public void AfterThrowing(Method method, Object[] args, Object target,SQLException e){ System.out.println(e.getMessage()); } }
其中有几点是需要注意的:
1. 方法名必须为:afterThrowing
2. 三个入参Method method, Object[] args, Object target 要么一起提供,要么都不提供,而最后一个入参必须为Throwable或其子类。当目标对象抛出异常时,增强会调用相似度最高的匹配异常类的方法(在类的继承树上,两个类的距离越近,相似度就越高)
关于引介增强,它可以动态地为类增加新的接口或方法,具有难以想象的动态特性,在后面的学习中我们会再单独提到。
相关文章推荐
- selenium在Eclipse中打开fireFox浏览器是报报错connect to host 127.0.0.1 on port 7055
- 随堂笔记160316内部类
- Java并发编程:sleep、wait、yield对比
- 随堂笔记160315工厂和代理模式
- 随堂笔记160314适配器和多态
- ServletConfig与ServletContext对象详解
- Java 套接字使用
- 20145317彭垚《Java程序设计》第3周学习总结
- eclipse通过maven插件添加Jersey archetype
- Java枚举类的高级用法说明
- java常用设计模式
- 20144303 《Java程序设计》第三周学习总结
- 第七届蓝桥杯Java语言B组真题(省赛)
- 《Java程序设计》第三周学习总结
- struts 标签库select、datepicker、checkboxlist、doubleselect标签使用学习笔记
- 20145312 《Java程序设计》第三周学习总结
- java双缓冲
- JAVA CAS单点登录之三:CAS代理模式演练
- Java继承与初始化
- Java并发编程:volatile关键字解析