在Spring中实现AOP根据版本不同,可以有大致四种配置方式。现简单列一下。在介绍Spring的AOP配置方式前,先要注意Spring中Advisor的概念。在Spring中Advisor是Advice和Pointcut的结合,但它还不是AOP概念上的Aspect。因为在Spring中Advisor还是Spring用来生成Aspect对象的一个原型,根据配置的不同,Spring可以只对某个类生成Aspect,也可以对所有的类生成Aspect。
1 基于xml配置文件的代理配置方式
这种方式在20以后很少用了,原因是配置项过多,过于繁琐。但对于理解Spring AOP还是很有帮助的
11 定义通知
<bean id="advice" class="yourAdviceImpl" />
12 定义切点
要定义一个切点,可以选择使用正则表达式方式声明的切点或者AspectJ方式声明的切点。对正则表达式切点,使用Perl5RegexpMethodPointcut或JdkRegexpMethodPointcut(Java
14以上版本,不需要Jakarta ORO的支持了);对AspectJ切点,使用AspectJExpressPointcut
<bean id="pointcut" class="orgspringframeworkaopsupportJdkRegexpMethodPointcut">
<property name="pattern" value="yourRegularExpression" />
</bean>
<bean id="pointcut" class="orgspringframeworkaopaspectjAspectJExpressionPointcut">
<property name="expression" value="yourAspectJExpression" />
</bean>
13 定义通知者
DefaultPointcutAdvisor是Spring提供的默认通知者,它需要提供通知和切点的引用。
Spring也提供了RegexpMethodPointcutAdvisor和AspectJExpressionPointcutAdvisor来对应两种声明切点的方式,不用再单独定义切点。
<bean id="advisor" class="orgspringframeworkaopsupportDefaultPointcutAdvisor">
<property name="advice" ref="advice" />
<property name="pointcut" ref="pointcut" />
</bean>
<bean id="advisor" class="orgspringframeworkaopsupportRegexpMethodPointcutAdvisor">
<property name="advice" ref="advice" />
<property name="pattern" value="yourRegularExpression" />
</bean>
<bean id="advisor" class="orgspringframeworkaopaspectjAspectJExpressionPointcut">
<property name="advice" ref="advice" />
<property name="expression" value="yourAspectjExpression" />
</bean>
14 定义ProxyFactoryBean
<bean id="yourBean" class="orgspringframeworkaopframeworkProxyFactoryBean>
<property name="target" ref="yourTargetBean" />
<property name="interceptorNames" value="advisor" />
<property name="proxyInterfaces" value="interfaceClass" />
</bean>
interceptorNames和proxyInterfaces都是数组属性,所以可以声明要使用的一个list,也可以让Spring自动把单个值转化为数组
上面明确定义了要对那个targetBean应用代理生成切面实例。如果不想限制targetBean,可以让Spring为所有匹配切点声明的bean生成切面实例,这样就不用一个个定义ProxyFactoryBean了,只需要定义
<bean class="orgspringframeworkaopframeworkautoproxyDefaultAdvisorAutoProxyCreator" />
这是一个BeanPostProcessor,所以Spring会自动识别并在bean的声明周期使用
2 利用20以后使用aop标签
<aop:config>
<aop:aspect ref="">
<aop:pointcut id="performance" expression="execution( perform())" />
<aop:before method="" pointcut-ref="performance" />
<aop:before method="" pointcut="execution( perform())" />
<aop:after-returning method="" pointcut="execution( perform())" />
<aop:after-throwing method="" pointcut="execution( perform())" />
</aop:aspect>
</aop:config>
3 利用Annotation
31 利用@Aspect将一个POJO类声明为一个切面。
32 定义切点
@Pointcut("execution( perform())")
public void performance(){}
通过@Pointcut定义的切点的名字就是它所注解的方法的名字,因此例子中的切点名字是
performance()。这里声明的performance()方法实际圣只是一个标记,为@Pointcut提供附加的点,并不要求有实际意义。
33 定义通知
对要执行切面的方法,通过@Before("performance()"),@AfterReturning
("performance()")来定义通知。注意这里提供的切点名称,是performance(),而不是performance
如果对上面的两点不是很理解,也可以省略@Pointcut,而将AspectJ表达式直接定义在@Before等通知中,将上面的两步合为一步,如@Before("execution( perform())")
34 通知Spring创建代理
<aop:aspectj-autoproxy>
这实际上相当于声明了一个AnnotationAwareAspectJAutoProxyCreator,从而根据@Pointcut声明的切点来自动代理匹配的bean实例
4 在Spring中结合进AspectJ
对于超出Spring AOP支持范围的,可以采用这种方式。只需要在Spring中配置AspectJ的Class实例时让Spring能够获得AspectJ类的实例就可以了,比如
<bean class="a_aspectj_class" factory-method="aspectOf">
<preperty />
</bean>
最近在项目有一个 *** 作时间监控功能
项目采用的是 spring31 mvc -control注解
为了对所有的 *** 作进行执行时间监控,编写了一个AOP
配置mvc aop的时候,刚开始按照普通的aspect注解的方式配置,无法生效。
后面查了相关的资料,有的说@control不支持AOP ,有的说支持,但笔者最后还是成功的找到了
相关的配置方法,因为笔者喜欢Aspect的注解风格。所以笔者只提供Aspect风格的相关配置。相关jar网上搜下。笔者只讲mvc 切面生效的配置。
前提条件MVC配置成功。
编写AOP类
package comwxaoptimer;
import orgapachelog4jLogger;
import orgaspectjlangProceedingJoinPoint;
import orgaspectjlangannotationAround;
import orgaspectjlangannotationAspect;
import orgspringframeworkstereotypeComponent;
@Component
@Aspect
public class Timer {
private Logger logger =LoggergetLogger(getClass());
//可以尝试下这两种注解
// @Around("execution( orgspringframeworkwebservletmvcannotationAnnotationMethodHandlerAdapterhandle())")
@Around("@annotation(orgspringframeworkwebbindannotationRequestMapping)")
public Object logTimer(ProceedingJoinPoint thisJoinPoint) throws Throwable {
String clazzName = thisJoinPointgetTarget()getClass()getName();
String methodName = thisJoinPointgetSignature()getName();
// 计时并调用目标函数
long start = SystemcurrentTimeMillis();
Object result = thisJoinPointproceed();
long time = SystemcurrentTimeMillis() - start;
// 输出计时信息
loggerinfo(" *** 作计时:" + time + "ms 类名: " + clazzName+ " 方法名:" + methodName + "()");
return result;
}
}
spring-servlet配置文件加入下面配置语句:
<aop:aspectj-autoproxy proxy-target-class="true" /> <!-- aspect注解生效-->
<!-- aop切面 -->
<bean id="timer" class="comwxaoptimerTimer" />
笔者mvc配置文件为spring-servletxml整个配置文件如下:
<xml version="10" encoding="UTF-8">
<beans xmlns=">
有配置的,代码示例如下:
这是业务测试类:
package aopannotationservice;
import orgspringframeworkcontextannotationScope;
import orgspringframeworkstereotypeService;
@Service("deptSerivceImpl")
@Scope("prototype")
public class DeptSerivceImpl implements DeptService {
public DeptSerivceImpl(){}
public void delete() {
try {
Threadsleep(200);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
Systemoutprintln("删除部门");
}
public void save() {
try {
Threadsleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
eprintStackTrace();
}
Systemoutprintln("保存部门");
}
}
这个是切面测试类:
package aopannotationaspect;
import orgaspectjlangProceedingJoinPoint;
import orgaspectjlangannotationAround;
import orgaspectjlangannotationAspect;
import orgaspectjlangannotationBefore;
import orgaspectjlangannotationPointcut;
import orgspringframeworkstereotypeComponent;
import orgspringframeworkutilStopWatch;
@Aspect
@Component("timeHander")
public class TimeHander {
@Pointcut("bean (Service)")
public void myPointCut(){};
@Before("maPointCut()")
public void myBefore(){
Systemoutprintln("-----执行前置处理-------");
}
@Around("myPointCut()")
public Object handerTime(ProceedingJoinPoint pjp){
try {
// 开始计时
StopWatch watch=new StopWatch(pjpgetTarget()getClass()getName());
watchstart(pjpgetSignature()getName());
Object obj=pjpproceed();
// 停止计时
watchstop();
Systemoutprintln(watchprettyPrint());
return obj;
} catch (Throwable e) {
// TODO Auto-generated catch block
eprintStackTrace();
return null;
}//执行目标
}
}
title: Spring之AOP二
date: 2017-03-25 02:42:16
tags:
execution
日常使用最多的标识符,使用execution标识符的Pointcut表达式格式:
within
指定类型,类型下所有方法。可以使用 和 扩展,like: within(tkzhanghspring)
this和target
Spring中使用this和target实际作用类似
args
指定参数类型,指定参数数量
与execution标识符不同,args标识符会在运行期间动态检查参数类型
@within
指定类型,类型下的所有方法,要求类型标记了指定注解,like:
@target
指定标记了给定注解类型的目标对象的所有方法
@args
指定参数类型,要求参数参数类型标记了指定注解
@annotation
指定标记了指定注解的方法,@Transctional的实现方式
所有@AspectJ形式声明的这些Pointcut表达式最终都会转化成Pointcut的具体实现。
AspectJExpressionPointcut如同他的名字面向AspectJ的pointcut实现,整个继承体系:
使用@Aspect注解标记的类中,具体的Advice形式由具体的Advice注解标示。
注解的方法中需要访问上下文信息最主要的方式:将方法的第一个参数声明为JoinPoint类型
以事务为例,事务管理也是使用AOP,具体是@annotation形式的Pointcut声明(这样我就不用声明Advice了)
当在aFun内调用bFun时事务没有开启,也就是AOP没有生效,原因:
我们期望虚线的调用方式,实际上调用时红色的路线,添加在代理对象上的AOP逻辑在嵌套调用时根本没有机会触发。在事务处理时尤其要注意避免这样的嵌套调用问题。
解决:
不管是那种方式都要注入相关Bean,具体那种更优雅由你来决定了。
在初始化容器的最后,会创建业务bean。创建bean的流程与BeanPostProcessor的创建流程一样( Spring注解--AOP原理(三):BeanPostProcessor创建与注册 )。只是由于在此之前BeanPostProcessor(AnnotationAwareAspectJAutoProxyCreator)已经注入到容器中,于是在创建业务bean的时候,就可以利用该后置处理器的postProcessAfterInitialization方法中的wrapIfNecessary方法来创建代理对象,进而可以对业务对象进行拦截。请参考 Spring注解--AOP原理(二):AnnotationAwareAspectJAutoProxyCreator
如果业务bean有代理对象,则返回代理对象;否则返回业务bean本身。
最后进入 DefaultAopProxyFactory 类,创建代理对象
最后将代理bean注入到容器中。
以上就是关于spring配置aop的方式有哪些全部的内容,包括:spring配置aop的方式有哪些、如何在sping3.1 MVC中应用aspect注解之AOP、Spring 配置AOP切面注解报错,求教大虾等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)