Spring课程 Spring入门篇 5-7 advisors
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 :
Invoke Service ....
===================================================================================================================
Try Times :
Try Times : 2
Try Times :
Try Times :
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
Spring课程 Spring入门篇 5-7 advisors的更多相关文章
- Spring Boot -01- 快速入门篇(图文教程)
Spring Boot -01- 快速入门篇(图文教程) 今天开始不断整理 Spring Boot 2.0 版本学习笔记,大家可以在博客看到我的笔记,然后大家想看视频课程也可以到[慕课网]手机 app ...
- Spring实践系列-入门篇(一)
本文主要介绍了在本地搭建并运行一个Spring应用,演示了Spring依赖注入的特性 1 环境搭建 1.1 Maven依赖 目前只用到依赖注入的功能,故以下三个包已满足使用. <properti ...
- Spring课程 Spring入门篇 6-3 ProxyFactoryBean及相关内容(下)
1 解析 1.1 使用global advisors demo 1.2 jdk代理和cglib代理的选择 1.3 如何强制使用CGLIB实现AOP? 1.4 JDK动态代理和CGLIB字节码生成的区别 ...
- Spring课程 Spring入门篇 6-2 ProxyFactoryBean及相关内容(上)
1 解析 1.1 类的方式实现各种通知需要实现的接口 1.2 创建Spring aop代理的优点及方法 1.3 代理控制切入点和通知的顺序的代码实现(具体完全实现,见代码2.1) 1.4 代理方式选择 ...
- Spring课程 Spring入门篇 7-2 Advice定义及实例
1 解析 1.1 通知:after和afterreturning的区别 1.2 @RunWith 是什么? 2 代码演练 2.1 注解方式配置通知的两种方式 2.2 异常通知 2.3 非异常通知 1 ...
- Spring课程 Spring入门篇 5-2 配置切面aspect
本节主要讲了在xml中配置切面的demo 1 解析 1.1 配置切面xml 1.2 配置切面xml 1.3 问:什么是动态代理? 2 代码演练 2.1 配置切面xml 1 解析 1.1 配置切面xml ...
- Spring课程 Spring入门篇 4-9 Spring bean装配之对jsr支持的说明
1 解析 1.1 疑问:2.2去掉@resource注解,为什么不能赋值?不是有set方法了吗? 1.2 @resource注解版本支持 1.3 没有显式指定@resource的那么,默认名称从何获得 ...
- Spring课程 Spring入门篇 4-8 Spring bean装配之基于java的容器注解说明--基于泛型的自动装配
1 解析 1.1 什么是泛型? 1.2 泛型有什么作用? 1.3 泛型装配样式? 2 代码演练 2.1 泛型应用 1 解析 1.1 什么是泛型? Java泛型设计原则:只要在编译时期没有出现警告,那么 ...
- Spring课程 Spring入门篇 4-7 Spring bean装配之基于java的容器注解说明--@Scope 控制bean的单例和多例
1 解析 1.1 bean的单例和多例的应用场景 1.2 单例多例的验证方式 1.3 @Scope注解单例多例应用 2 代码演练 2.1 @Scope代码应用 1 解析 1.1 bean的单例和多例的 ...
随机推荐
- c:foreach 使用
<!--引入--> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" ...
- 实现反转的方法(reverse)
1.最简单的方法: public static String reverse1(String str) { return new StringBuffer(str).reverse().toStrin ...
- 大数据-hadoop HA集群搭建
一.安装hadoop.HA及配置journalnode 实现namenode HA 实现resourcemanager HA namenode节点之间通过journalnode同步元数据 首先下载需要 ...
- python的builtins模块
builtins模块详解 1.简介 builtins是python的内建模块,所谓内建模块就是你在使用时不需要import,在python启 动后,在没有执行程序员编写的任何代码前,python会加载 ...
- vue,下级页面刷新导致路由跳转带过来的数据消失的解决方法
if(typeof(this.$route.query.result)=='string'){ //刷新时走这 }else{ //正常路由跳转过来后就把数据塞到 localStorage let ob ...
- Vue项目中使用HighChart
记:初次在Vue项目中使用 HighChart 的时候要走的坑 感谢这位哥们的思路 传送门 Vue-cli项目使用 npm install highcharts --save 让我们看看 highch ...
- MVC返回数据流,ajax接受并保存文件
js代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...
- git特殊用法
git stash的使用 1.当前分支写了一半的代码,需要切到其他分支修复bug或者完成优先级较高的任务时 git stash 暂存分支进度 git stash list 查看草稿区 git stas ...
- vue 打印
vue 方法 第一种方法:通过npm 安装插件 1,安装 npm install vue-print-nb --save 2,引入 安装好以后在main.js文件中引入 import Print ...
- spark第十篇:Spark与Kafka整合
spark与kafka整合需要引入spark-streaming-kafka.jar,该jar根据kafka版本有2个分支,分别是spark-streaming-kafka-0-8和spark-str ...