aop-链接:http://pandonix.iteye.com/blog/336873
链接: http://z-xiaofei168.iteye.com/blog/1040231
Spring中AOP代理由Spring的IoC容器负责生成,管理,其依赖关系也由IoC容器负责管理。因此AOP代理可以直接使用容器中的其他Bean实例作为目标,这种关系可由Ioc容器的依赖注入提供。
Spring AOP采用基于代理的AOP实现方案,AspectJ则采用编译时增强的解决方案。
Spring AOP应用:
方式一:采用Annotation注解方式实现
---定义切面Bean:
@Aspect public class AspectTest { //定义类的其他类容 ...... }
当我们使用 @Aspect 来修饰一个 Java 类之后,Spring 将不会把该 Bean 当成组件 Bean 处理,因此负责自动增强的后处理 Bean 将会略过该 Bean,不会对该 Bean 进行任何增强处理。
开发时无须担心使用 @Aspect 定义的方面类被增强处理,当 Spring 容器检测到某个 Bean 类使用了 @Aspect 标注之后,Spring 容器不会对该 Bean 类进行增强。
---定义Before增强处理
使用@Before来标注一个方法,使该方法作为一个Before增强处理。使用@Before标注时,通常需要指定一个value值,改值指定一个切入表达式,用于指定该增强处理将被织入哪些切入点。
<?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <!-- 指定自动搜索Bean组件、自动搜索切面类 --> <context:component-scan base-package="org.crazyit.app.service ,org.crazyit.app.advice"> <context:include-filter type="annotation" expression="org.aspectj.lang.annotation.Aspect"/> </context:component-scan> <!-- 启动@AspectJ支持 --> <aop:aspectj-autoproxy/> </beans>
@Aspect public class BeforeAdviceTest { //匹配org.crazyit.app.service.impl包下所有类的、 //所有方法的执行作为切入点 @Before("execution(* org.crazyit.app.service.impl.*.*(..))") public void authority() { System.out.println("模拟执行权限检查"); } }
定义AfterThrowing 增强处理
@Aspect public class AfterThrowingAdviceTest { //匹配org.crazyit.app.service.impl包下所有类的、 //所有方法的执行作为切入点 @AfterThrowing(throwing="ex" , pointcut="execution(* org.crazyit.app.service.impl.*.*(..))") public void doRecoveryActions(Throwable ex) { System.out.println("目标方法中抛出的异常:" + ex); System.out.println("模拟抛出异常后的增强处理..."); } }
---定义AfterReturning增强处理
---定义After 增强处理
---定义Around 增强处理
---访问目标方法的参数:访问目标方法的做法是定义增强处理时将第一个参数定义为JoinPoint类型,当该增强处理方法被调用时,该JoinPoint 参数就代表了织入增强处理的连接点。
@Aspect public class FourAdviceTest { //定义Around增强处理执行 @Around("execution(* org.crazyit.app.service.impl.*.*(..))") public Object processTx(ProceedingJoinPoint jp) throws java.lang.Throwable { System.out.println("Around增强:执行目标方法之前,模拟开始事务..."); //访问执行目标方法的参数 Object[] args = jp.getArgs(); //当执行目标方法的参数存在, //且第一个参数是字符串参数 if (args != null && args.length > 0 && args[0].getClass() == String.class) { //改变第一个目标方法的第一个参数 args[0] = "被改变的参数"; } //执行目标方法,并保存目标方法执行后的返回值 Object rvt = jp.proceed(args); System.out.println("Around增强:执行目标方法之后,模拟结束事务..."); return rvt + " 新增的内容"; } //定义Before增强处理执行 @Before("execution(* org.crazyit.app.service.impl.*.*(..))") public void authority(JoinPoint jp) { System.out.println("Before增强:模拟执行权限检查"); //返回被织入增强处理的目标方法 System.out.println("Before增强:被织入增强处理的目标方法为:" + jp.getSignature().getName()); //访问执行目标方法的参数 System.out.println("Before增强:目标方法的参数为:" + Arrays.toString(jp.getArgs())); //访问被增强处理的目标对象 System.out.println("Before增强:被织入增强处理的目标对象为:" + jp.getTarget()); } //定义AfterReturning增强处理执行 @AfterReturning(pointcut="execution(* org.crazyit.app.service.impl.*.*(..))" , returning="rvt") public void log(JoinPoint jp , Object rvt) { System.out.println("AfterReturning增强:获取目标方法返回值:" + rvt); System.out.println("AfterReturning增强:模拟记录日志功能..."); //返回被织入增强处理的目标方法 System.out.println("AfterReturning增强:被织入增强处理的目标方法为:" + jp.getSignature().getName()); //访问执行目标方法的参数 System.out.println("AfterReturning增强:目标方法的参数为:" + Arrays.toString(jp.getArgs())); //访问被增强处理的目标对象 System.out.println("AfterReturning增强:被织入增强处理的目标对象为:" + jp.getTarget()); } //定义After增强处理执行 @After("execution(* org.crazyit.app.service.impl.*.*(..))") public void release(JoinPoint jp) { System.out.println("After增强:模拟方法结束后的释放资源..."); //返回被织入增强处理的目标方法 System.out.println("After增强:被织入增强处理的目标方法为:" + jp.getSignature().getName()); //访问执行目标方法的参数 System.out.println("After增强:目标方法的参数为:" + Arrays.toString(jp.getArgs())); //访问被增强处理的目标对象 System.out.println("After增强:被织入增强处理的目标对象为:" + jp.getTarget()); } }
---定义切入点:
为一个切入表达式起一个名称,从而允许在多个增强处理中重用该名称。SpringAOP只支持以SpringBean的方法执行组作为连接点,所以可以把切入点看错所有能和切入表达式匹配的Bean方法。
//1. @Aspect public class SystemArchitecture { @Pointcut("execution(* org.crazyit.app.service" + ".impl.Chin*.say*(..))") public void myPointcut() { } }
//2. @Aspect public class LogAspect { //直接使用SystemArchitecture切面类的myPointcut切入点 //args(msg)保证该切入点只匹配只有一个字符串参数的方法 @AfterReturning(pointcut="SystemArchitecture.myPointcut()" + "&&args(msg)" , returning="retVal") public void writeLog(String msg, Object retVal) { System.out.println(msg); System.out.println(retVal); System.out.println("模拟记录日志...."); } }
方式二:采用XML方式配置
//Xml配置aop <?xml version="1.0" encoding="GBK"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"> <aop:config> <!-- 将fourAdviceBean转换成切面Bean,切面Bean的新名称为:fourAdviceAspect--> <aop:aspect id="fourAdviceAspect" ref="fourAdviceBean"> <!-- 定义一个After增强处理, 直接指定切入点表达式 以切面Bean中的release()方法作为增强处理方法 --> <aop:after pointcut="execution(* org.crazyit.app.service.impl.*.*(..))" method="release"/> <!-- 定义一个Before增强处理, 直接指定切入点表达式 以切面Bean中的authority()方法作为增强处理方法 --> <aop:before pointcut="execution(* org.crazyit.app.service.impl.*.*(..))" method="authority"/> <!-- 定义一个AfterReturning增强处理, 直接指定切入点表达式 以切面Bean中的log()方法作为增强处理方法 --> <aop:after-returning pointcut="execution(* org.crazyit.app.service.impl.*.*(..))" method="log" returning="rvt"/> <!-- 定义一个Around增强处理, 直接指定切入点表达式 以切面Bean中的processTx()方法作为增强处理方法 --> <aop:around pointcut="execution(* org.crazyit.app.service.impl.*.*(..))" method="processTx"/> </aop:aspect> </aop:config> <!-- 定义一个普通组件Bean --> <bean id="chinese" class="org.crazyit.app.service.impl.Chinese"/> <!-- 定义一个普通Bean实例,该Bean实例将被作为Aspect Bean --> <bean id="fourAdviceBean" class="org.crazyit.app.advice.FourAdviceTest"/> </beans> //XML配置PointCut <aop:config> <!-- 定义一个切入点:myPointcut,直接指定它对应的切入点表达式 --> <aop:pointcut id="myPointcut" expression="execution(* org.crazyit.app.service.impl.*.*(..))"/> <aop:aspect id="afterThrowingAdviceAspect" ref="afterThrowingAdviceBean" order="1"> <!-- 定义一个AfterThrowing增强处理,指定切入点 以切面Bean中的doRecoveryActions()方法作为增强处理方法 --> <aop:after-throwing pointcut-ref="myPointcut" method="doRecoveryActions" throwing="ex"/> </aop:aspect> </aop:config> <!-- 再定义一个普通Bean实例,该Bean实例将被作为Aspect Bean --> <bean id="afterThrowingAdviceBean" class="org.crazyit.app.advice.AfterThrowingAdviceTest"/>
注:摘自轻量级JavaEE企业应用实战第三版