Spring_8
Spring学习(23)--- AOP之Introductions应用
注意:Aspect instantiation models
·schema-defined aspects(基于配置)只支持singleton model(单例模式)
- 简介允许一个切面声明一个实现指定接口的通知对象,并且提供了一个接口实现类来代表这些对象
- 由<aop:aspect>中的<aop:declare-parents>元素声明该元素用于声明所匹配的类型拥有一个新的parents(因此得名)
配置:
<aop:aspect id="usageTrackerAspect" ref="usageTracking"> <aop:declare-parents types-matching="com.xyz.myapp.service.*+" implement-interface="com.xyz.myapp.service.tracking.UsageTracked" default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/> </aop:aspect>
public void recordUsage(){ usageTracked.incrementUseCount(); }
UsageTracked usageTracked = (UsageTracked) context.getBean("myservice");
例子:
新建接口Fit及实现类FitImpl
package com.aop.schema; public interface Fit { void filter(); }
package com.aop.schema; public class FitImpl implements Fit { @Override public void filter() { System.out.println("FitImpl.filter"); } }
切面类(同上节,不做修改了):
package com.aop.schema.advice; import org.aspectj.lang.ProceedingJoinPoint; /** * * 切面类 * */ public class MyAspect { public void before(){ System.out.println("MyAspect.before"); } public void afterreturning(){ System.out.println("MyAspect.afterreturning"); } public void afterthrowing(){ System.out.println("MyAspect.afterthrowing"); } public void after(){ System.out.println("MyAspect.after"); } public void around(ProceedingJoinPoint pjp) { try { System.out.println("MyAspect.around_1"); Object obj=pjp.proceed(); System.out.println("MyAspect.around_2"); } catch (Throwable e) { e.printStackTrace(); } } public void around_init(ProceedingJoinPoint pjp,String name,int age) { System.out.println(name+" "+age); try { System.out.println("MyAspect.around_1"); Object obj=pjp.proceed(); System.out.println("MyAspect.around_2"); } catch (Throwable e) { e.printStackTrace(); } } }
XML配置:
<?xml version="1.0" encoding="UTF-8"?> <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" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <bean id="myAspect" class="com.aop.schema.advice.MyAspect"></bean> <aop:config> <aop:aspect id="myAspectAOP" ref="myAspect"> <!-- com.aop.schema.advice.*+ 指的是advice包下的所有类 --> <aop:declare-parents types-matching="com.aop.schema.advice.*+" implement-interface="com.aop.schema.Fit" default-impl="com.aop.schema.FitImpl"/> </aop:aspect> </aop:config> </beans>
单元测试:
package com.aop.schema; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.aop.schema.advice.ApsectBiz; public class UnitTest { @Test public void test(){ ApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring-aop.xml"); Fit fit = (Fit)context.getBean("myAspect"); fit.filter(); } }
测试结果:
七月 11, 2015 1:15:13 下午 org.springframework.context.support.AbstractApplicationContext prepareRefresh INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@31b3c607: startup date [Sat Jul 11 13:15:13 CST 2015]; root of context hierarchy 七月 11, 2015 1:15:13 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions INFO: Loading XML bean definitions from class path resource [spring-aop.xml] FitImpl.filter
PS:说明为指定的类型强制指定了一个父类。
===Advisors========================================
Advisor:
·advisor就像一个小的自包含的方面,只有一个advise
·切面自身通过一个bean表示,并且必须实现某个advice接口,同时,advisor也可以很好地利用AspectJ的切入点表达式
·Spring通过配置文件中<aop:advisor>元素支持advisor实际使用中,大多数情况下它会和transactional(事务) advice配合使用
· 为了定义一个advisor的优先级以便让advice可以有序,可以使用order属性来定义advisor的顺序
使用Spring事务控制时经常使用的一种方式
<aop:config> <aop: pointcut id="bussinessService" "execution(* com.xyz.myapp.service..(..))"/> <aop: advisor pointcut-ref ="bussinessService" advice-ref="tx-advice"/> </aop:config> <tx:advice id="tx-advice"> <tx:attributes> <tx:method name="*" propagation="REQUIRED"/> </tx:attributes> </tx:advice>
例子:
配置文件:
<?xml version="1.0" encoding="UTF-8"?> <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.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="com.imooc.aop.schema"></context:component-scan> <aop:config> <aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor"> <aop:pointcut id="idempotentOperation" expression="execution(* com.imooc.aop.schema.advisors.service.*.*(..)) " /> <!-- expression="execution(* com.imooc.aop.schema.service.*.*(..)) and --> <!-- @annotation(com.imooc.aop.schema.Idempotent)" /> --> <aop:around pointcut-ref="idempotentOperation" method="doConcurrentOperation" /> </aop:aspect> </aop:config> <bean id="concurrentOperationExecutor" class="com.imooc.aop.schema.advisors.ConcurrentOperationExecutor"> <property name="maxRetries" value="3" /> <property name="order" value="100" /> </bean> </beans>
切面代码
1 package com.imooc.aop.schema.advisors; 2 3 import org.aspectj.lang.ProceedingJoinPoint; 4 import org.springframework.core.Ordered; 5 import org.springframework.dao.PessimisticLockingFailureException; 6 7 public class ConcurrentOperationExecutor implements Ordered { 8 9 private static final int DEFAULT_MAX_RETRIES = 2; 10 11 private int maxRetries = DEFAULT_MAX_RETRIES; 12 13 private int order = 1; 14 15 public void setMaxRetries(int maxRetries) { 16 this.maxRetries = maxRetries; 17 } 18 19 public int getOrder() { 20 return this.order; 21 } 22 23 public void setOrder(int order) { 24 this.order = order; 25 } 26 27 public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable { 28 int numAttempts = 0; 29 PessimisticLockingFailureException lockFailureException; 30 do { 31 numAttempts++; 32 System.out.println("Try times : " + numAttempts); 33 try { 34 return pjp.proceed(); 35 } catch (PessimisticLockingFailureException ex) { 36 lockFailureException = ex; 37 } 38 } while (numAttempts <= this.maxRetries); 39 System.out.println("Try error : " + numAttempts); 40 throw lockFailureException; 41 } 42 }
代码
package com.imooc.aop.schema.advisors.service; import org.springframework.dao.PessimisticLockingFailureException; import org.springframework.stereotype.Service; @Service public class InvokeService { public void invoke() { System.out.println("InvokeService ......"); } public void invokeException() { throw new PessimisticLockingFailureException(""); } }
单元测试:
package com.imooc.test.aop; import org.junit.Test; import org.junit.runner.RunWith; import org.junit.runners.BlockJUnit4ClassRunner; import com.imooc.aop.schema.advisors.service.InvokeService; import com.imooc.test.base.UnitTestBase; @RunWith(BlockJUnit4ClassRunner.class) public class TestAOPSchemaAdvisors extends UnitTestBase { public TestAOPSchemaAdvisors() { super("classpath:spring-aop-schema-advisors.xml"); } @Test public void testSave() { InvokeService service = super.getBean("invokeService"); service.invoke(); System.out.println(); service.invokeException(); } }