1 简析
1.1 advisor简析
2 代码演练
2.1 类似顾问通知实现:(代码演练中没有用到顾问标签)
1 简析
顾问:在通知的基础之上,在细化我们的aop切面!
通知和顾问都是切面的实现方式!
通知是顾问的一个属性!
顾问会通过我们的设置,将不同的通知,在不通过的时间点,把切面
织入到不同的切入点!
PointCutAdvisor接口!
比较常用的两个实现类:
NameMatchMethodPointcutAdvisor :根据切入点(主业务方法)名称织入切面!
RegexpMethodPointcutAdvisor :根据自定义的正则表达式织入切面!
正则表达式中常用的三个运算符
. 任意单个字符
+ 表示字符出现一次或者多次
* 表示字符出现0次或者多次
1.1 advisor简析(更加灵活的配置切面,详细的可以参见2.1)
Advisor是Pointcut和Advice的配置器,它包括Pointcut和Advice,是将Advice注入程序中Pointcut位置的代码
<aop:aspectj-autoproxy/> <aop:config proxy-target-class="true"> <aop:pointcut id="servicePointcut" expression="execution(* com.cpic..*Service.*(..))" /> <aop:advisor pointcut-ref="servicePointcut" advice-ref="txAdvice" order="3" /> </aop:config> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="add*" /> <tx:method name="insert*" /> <tx:method name="remove*" /> <tx:method name="save*" /> <tx:method name="update*" /> <tx:method name="delete*" /> <tx:method name="cancel*" /> <tx:method name="trans*" /> <tx:method name="commit*" /> <tx:method name="submit*" /> <tx:method name="issue*" /> <tx:method name="accept*" /> <tx:method name="underwrite*" /> <tx:method name="modify*" /> <tx:method name="calculate*" /> <tx:method name="copy*" /> <tx:method name="print*" /> <tx:method name="create*" /> <tx:method name="send*" /> <tx:method name="activate*" /> <tx:method name="generate*" /> <tx:method name="do*" /> <tx:method name="find*" read-only="true" /> <tx:method name="get*" read-only="true" /> <tx:method name="load*" read-only="true" /> <tx:method name="list*" read-only="true" /> <!-- log方法会启动一个新事务 --> <tx:method name="log*" propagation="REQUIRES_NEW" isolation="READ_COMMITTED" /> <!-- 如果通过java代码来进行分库判断,这里exeNewTS方法需要启动一个新事务 ,切换数据源时使用--> <tx:method name="exeNewTS*" propagation="REQUIRES_NEW" isolation="READ_COMMITTED" /> <!-- <tx:method name="exeNewTS*"/> --> </tx:attributes> </tx:advice>
2 代码演练
2.1 类似顾问通知实现:(代码演练中没有用到顾问标签)
测试类:
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 /** * 1 这里问题的关键:在 ConcurrentOperationExecutor.java类中的try方法中 * 把正常的方法service.invoke() 和出现异常的方法service.invokeException() 进行对比 * * 2 从xml传值 <property name="maxRetries" value="3"/> */ public void testSave(){ InvokeService service = super.getbean("invokeService"); service.invoke(); System.out.println("==================================================================================================================="); service.invokeException(); } }
配置类:
<?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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd 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" > <!-- 扫描包 --> <context:component-scan base-package="com.imooc.aop.schema"></context:component-scan> <!-- 配置aop --> <aop:config> <aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor"> <!-- 注意:此处有小空格 -->
<aop:pointcut id="idempotentOperation"
expression="execution(* com.imooc.aop.schema.advisors.service.*.*(..)) " />
<aop:around pointcut-ref="idempotentOperation" method="doConcurrentOperation"/>
</aop:aspect> </aop:config> <!-- 配置bean类 ,当下类作为通知类存在--> <bean id="concurrentOperationExecutor" class="com.imooc.aop.schema.advisors.ConcurrentOperationExecutor">
<property name="maxRetries" value="3"/>
<property name="order" value="100"/> </bean> </beans>
实体类:
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("Invoke Service ...."); } public void invokeException(){ throw new PessimisticLockingFailureException(""); } }
通知类:
package com.imooc.aop.schema.advisors; import org.aspectj.lang.ProceedingJoinPoint; import org.springframework.core.Ordered; import org.springframework.dao.PessimisticLockingFailureException; public class ConcurrentOperationExecutor implements Ordered{ private static final int DEFAULT_MAX_RETRIES = 2; private int maxRetries = DEFAULT_MAX_RETRIES; private int order = 1; public int getMaxRetries() { return maxRetries; } public void setMaxRetries(int maxRetries) { this.maxRetries = maxRetries; } public int getOrder() { return order; } public void setOrder(int order) { this.order = order; } /** * 通知对应的方法 * @param pjp * @return * @throws Throwable */ public Object doConcurrentOperation(ProceedingJoinPoint pjp) throws Throwable{ int numAttempts = 0; //次数 PessimisticLockingFailureException lockFailureException; do { numAttempts++; System.out.println("Try Times : "+numAttempts); try { return pjp.proceed(); } catch (PessimisticLockingFailureException e) { lockFailureException = e; } } while (numAttempts<=this.maxRetries);//次数递增,当小于常量(xml传入的次数)时 System.out.println("Try error:"+numAttempts); return lockFailureException; } }
打印日志:
四月 20, 2019 3:01:36 下午 org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh 信息: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@45a5049a: startup date [Sat Apr 20 15:01:36 CST 2019]; root of context hierarchy 四月 20, 2019 3:01:36 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions 信息: Loading XML bean definitions from class path resource [spring-aop-schema-advisors.xml] 四月 20, 2019 3:01:36 下午 org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor <init> 信息: JSR-330 'javax.inject.Inject' annotation found and supported for autowiring Try Times : 1 Invoke Service .... =================================================================================================================== Try Times : 1 Try Times : 2 Try Times : 3 Try Times :4 Try error:4 四月 20, 2019 3:01:37 下午 org.springframework.context.support.ClassPathXmlApplicationContext doClose 信息: Closing org.springframework.context.support.ClassPathXmlApplicationContext@45a5049a: startup date [Sat Apr 20 15:01:36 CST 2019]; root of context hierarchy