继续Spring AOP的学习,总所周知,aop的魅力所在就是它能在方法前后起拦截作用,以便我们定义横切逻辑代码。增强大致分为5类:前置增强(就是在目标方法调用前拦截),后置增强(就是在目标方法调用之后拦截),异常增强(就是在目标方法抛出后拦截),引介增强(它是一种特殊的增强,可以在目标类添加属性和方法,通过拦截定义一个接口,让目标代理实现这个接口,它的连接点是类级别的),而前面三种增强则是方法级别的。以上四种增强接口是Spring定义的,还有只用环绕增强(目标方法前后拦截)是AOP联盟定义的接口。其实aop增强很简单,通过实现这些增强接口,在实现这些接口的方法中定义横切逻辑,然后通过配置spring配置文件,就可以完成将增强织入到目标方法中了。
首先,以前置增强为例,大家都知道如果我们到餐厅去,服务员首先会欢迎顾客,然后再为我们提供服务。这里我们一个
Waiter类:
package com.me.services;
public interface Waiter {
void greetTo(String name);
void serveTo(String name);
}
现在我们来看一个训练不足的服务生的服务情况:
package com.me.services.imp;
import com.me.services.Waiter;
public class LuceyWaiter implements Waiter {
public void greetTo(String name) {
System.out.println("greet to "+name);
}
public void serveTo(String name) {
System.out.println("server "+name);
}
}
Lucey走到闷不做声走到顾客面前, 提供服务,那么,我们就需要对每个服务生进行规范,在服务之前要行礼貌用语。
package com.me.advice;
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;
public class GreetingBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] args, Object obj)
throws Throwable {
String clientName = args[0].toString();
System.out.println("How are you,"+clientName+"!");
}
}
这里我们就用到了前置增强,通过实现org.springframework.aop.MethodBeforeAdvice接口的before方法定义逻辑代码。before中的三个参数分别代表:目标方法,目标方法的参数列表,目标实例。
目标对象也有了,增强也有了,接下来如何把增强织入的目标对象生成代理呢?上一次博客写到spring的代理机制,我们知道可以通过JDK和CGLib两种方式动态创建代理。但是那样我们代码太过麻烦,要自定义一个类实现指定接口,那有没有简单的方法呢?当然,spring为我们提供了ProxyFactoryBean,它帮我们完成了上面通过JDK,CGLib创建代理那些复杂的工作,我们只需要在spring中配置一下即可完成织入工作,^-^
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd">
<!-- 需要代理的业务类 -->
<bean id="target" class="com.me.services.imp.LuceyWaiter"></bean>
<!-- 指定增强,一个业务类可以有多个增强形成增强链,调用顺序与添加顺序一致 -->
<bean id="greetAdvice" class="com.me.advice.GreetingBeforeAdvice"></bean>
<!-- 利用ProxyFactoryBean创建代理 -->
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理要实现的接口,可以是多个接口 -->
<property name="proxyInterfaces" value="com.me.services.Waiter"/>
<property name="target" ref="target"/>
<!-- 需要织入目标对象的0增强数组 -->
<property name="interceptorNames">
<list>
<value>greetAdvice</value>
</list>
</property>
</bean>
</beans>
关于ProxyFactoryBean的工作原理将在以后写到,但需要进一步了解它的几个常用配置属性,除上面的属性外,还有singleton:返回代理是否为单实例,默认true.
optimize:当设置为true时,强制使用CGLib代理。对于单实例推荐配置true,但对于作用域类型的代理推荐false.
proxyTargetClass:是否对类代理(不是对接口进行代理),设置为true使用CGLib代理。当然如果设置为true就不必设置proxyInterfaces属性了,及时设置了也将被忽略。下面来一段测试代码吧:
package com.me.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.me.services.Waiter;
public class TestBeforeAdvice {
public static void main(String[] args) {
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
Waiter waiter = (Waiter)cxt.getBean("waiter");
waiter.greetTo("John");
}
}
后置增强,异常抛出增强和环绕增强用法差不多,只是实现的接口不一样罢了。下面就做说明了,我将测试代码上传供大家学习。接下来,来谈谈我们类级别的增强,即引介增强,我们还是根据上一篇博客代理机制的示例来学习引介增强。我们前面用到监测用户添加和删除性能,现在将起改为可控的。即维护人员可控制是否采用性能监控。
首先定义一个用于标志目标类是否支持性能监控的接口:
package com.me.advice;
public interface Monitorable {
/**
* @param IsActive
* true:性能监控功能激活
* false: 性能监控功能关闭
*/
public void setMonitorActive(boolean IsActive);
}
通过继承DelegatingIntroductionInterceptor为目标类引入性能监控功能,代码如下:
package com.me.util;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.support.DelegatingIntroductionInterceptor;
@SuppressWarnings("serial")
public class ControllablePerformanceMonitor extends
DelegatingIntroductionInterceptor implements Monitorable {
//为了解决线程安全问题
private ThreadLocal<Boolean> statusMap = new ThreadLocal<Boolean>();
public void setMonitorActive(boolean IsActive) {
statusMap.set(new Boolean(IsActive));
}
public Object invoke(MethodInvocation mi)throws Throwable{
Object obj = null;
if(statusMap.get()!=null && statusMap.get().booleanValue()){
PerformanceMonitor pm = new PerformanceMonitor();
pm.start(mi.getClass().getName()+"."+mi.getMethod().getName());
obj = super.invoke(mi);
pm.end();
}else{
obj = super.invoke(mi);
}
return obj;
}
}
配置引介增强
<bean id="target" class="com.me.services.imp.UserServiceImp"/>
<bean id="pmonitor" class="com.me.util.ControllablePerformanceMonitor"/>
<!-- 创建代理 -->
<bean id="userService" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 引介增强所实现的接口 -->
<property name="interfaces">
<value>com.me.util.Monitorable</value>
</property>
<property name="target" ref="target"/>
<property name="interceptorNames">
<idref local="pmonitor"/>
</property>
<!-- 由于引介增强通过子类创建代理,所以强制使用CGLib代理实现机制 -->
<property name="proxyTargetClass" value="true"/>
</bean>
测试引介增强
package com.me.test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.me.services.UserService;
import com.me.entity.*;
import com.me.util.Monitorable;
public class TestCotrollerPerformance {
/**
* @param args
*/
public static void main(String[] args) {
ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
UserService service = (UserService)cxt.getBean("userService");
service.deleteUser(1);
service.insertUser(new User());
//这里强制成果,说明返回的代理引入了Monitorable接口
Monitorable monitor = (Monitorable)service;
monitor.setMonitorActive(true);
service.deleteUser(1);
service.insertUser(new User());
}
}
分享到:
相关推荐
Spring AOP之5种增强方法应用范例 ,具体效果和过程看博文 http://blog.csdn.net/evankaka/article/details/45241863
Spring AOP 使用纯 Java 实现,不需要专门的编译过程和类加载器,在运行期间通过代理方式向目标类植入增强的代码。 课程内容非常详细的介绍Spring AOP全栈技术点,开篇帮助同学们进行知识储备,夯实基础就是核心!...
Spring3.2 版本中已不再提供第三放jar包,而在实际“AOP”应用中需要引入其他的jar包;此为,已知的jar包(最新版本)。
spring AOP的代码实例,了解面向切面编程思想的精髓,
主要介绍了线程池中使用spring aop事务增强,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
(3)Advice(通知):AOP在特定的切入点上执行的增强处理,有before,after,afterReturning,afterThrowing,around (4)Pointcut(切入点):就是带有通知的连接点,在程序中主要体现为书写切入点表达式 (5)AOP代理:AOP框架...
Spring AOP 学习记录 AOP(面向切面编程)方面的知识又是看了忘忘了看,今天有空记录下AOP的知识点。主要分为以下几方面: 1、AOP相关术语 2、基础知识及示例 3、增强分类 1、AOP相关术语 连接点...
切点用于来限定Spring-AOP启动的范围,通常我们采用表达式的方式来设置,所以关键词 是范围 通知(Advice) 通知是织入到目标类连接点上的一段程序代码。在Spring中,像 BeforeAdvice等还带有方位信息 通知是直译...
SpringAOP发展到现在出现的全部3种配置方式。 由于Spring强大的向后兼容性,实际代码中往往会出现很多配置混杂的情况,而且居然还能工作,本文希望帮助大家理清楚这些知识。 我们先来把它们的概念和关系说说清楚。 ...
NULL 博文链接:https://jackyin5918.iteye.com/blog/1918076
sping AOP面向切面的编程,程序运行过程中动态加入所需代码等,对公共的问题进行集中处理,具体的实现有动态代理与静态代理,本文通过对AOP的代理机制,前置、后置、环绕、异常的通知进行了综合总结和运用!
主要介绍了spring AOP的Around增强实现方法,结合实例形式分析了spring面向切面AOP的Around增强具体步骤与相关操作方法,需要的朋友可以参考下
微信公众号:吉姆餐厅ak学习更多原始知识,欢迎关注。 概述Spring Aop在Spring框架中的布局举足轻重,主要用于实现事务,缓存,安全等功能。... advice :通知,也就是aop中增强的方法。对以上三类核心类对应的UML分别
主要介绍了spring AOP的After增强实现方法,结合实例形式分析了spring面向切面AOP的After增强实现步骤与相关操作技巧,需要的朋友可以参考下
Spring AOP使用的动态代理,所谓的动态代理就是说AOP框架不会去修改字节码,而是在内存中临时为方法生成一个AOP对象,这个AOP对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。...
aopalliance.jar,aspectjrt.jar,aspectjweaver.jar包全部打包在这里了,省的到处找地方了
1. 定义一个MyClass类(或接口),包括math()、english()和physics()方法,可以简单模拟输出:上数学课/英语课/物理...请选择使用JDK动态代理、CGLIB代理、ProxyFactoryBean或者AspectJ中的某一种方式来实现增强处理。