课程链接:

1    简析

1.1  advisor简析

2    代码演练

2.1  类似顾问通知实现:(代码演练中没有用到顾问标签)

 

 

 

1    简析

顾问:在通知的基础之上,在细化我们的aop切面!

通知和顾问都是切面的实现方式!
通知是顾问的一个属性!

顾问会通过我们的设置,将不同的通知,在不通过的时间点,把切面
织入到不同的切入点!

PointCutAdvisor接口!
比较常用的两个实现类:
NameMatchMethodPointcutAdvisor :根据切入点(主业务方法)名称织入切面!
RegexpMethodPointcutAdvisor :根据自定义的正则表达式织入切面!

正则表达式中常用的三个运算符
.   任意单个字符
+   表示字符出现一次或者多次
*   表示字符出现0次或者多次

1.1  advisor简析(更加灵活的配置切面,详细的可以参见2.1)

Advisor是Pointcut和Advice的配置器,它包括PointcutAdvice,是将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的更多相关文章

  1. Spring Boot -01- 快速入门篇(图文教程)

    Spring Boot -01- 快速入门篇(图文教程) 今天开始不断整理 Spring Boot 2.0 版本学习笔记,大家可以在博客看到我的笔记,然后大家想看视频课程也可以到[慕课网]手机 app ...

  2. Spring实践系列-入门篇(一)

    本文主要介绍了在本地搭建并运行一个Spring应用,演示了Spring依赖注入的特性 1 环境搭建 1.1 Maven依赖 目前只用到依赖注入的功能,故以下三个包已满足使用. <properti ...

  3. Spring课程 Spring入门篇 6-3 ProxyFactoryBean及相关内容(下)

    1 解析 1.1 使用global advisors demo 1.2 jdk代理和cglib代理的选择 1.3 如何强制使用CGLIB实现AOP? 1.4 JDK动态代理和CGLIB字节码生成的区别 ...

  4. Spring课程 Spring入门篇 6-2 ProxyFactoryBean及相关内容(上)

    1 解析 1.1 类的方式实现各种通知需要实现的接口 1.2 创建Spring aop代理的优点及方法 1.3 代理控制切入点和通知的顺序的代码实现(具体完全实现,见代码2.1) 1.4 代理方式选择 ...

  5. Spring课程 Spring入门篇 7-2 Advice定义及实例

    1 解析 1.1 通知:after和afterreturning的区别 1.2 @RunWith 是什么? 2 代码演练 2.1 注解方式配置通知的两种方式 2.2 异常通知 2.3 非异常通知 1 ...

  6. Spring课程 Spring入门篇 5-2 配置切面aspect

    本节主要讲了在xml中配置切面的demo 1 解析 1.1 配置切面xml 1.2 配置切面xml 1.3 问:什么是动态代理? 2 代码演练 2.1 配置切面xml 1 解析 1.1 配置切面xml ...

  7. Spring课程 Spring入门篇 4-9 Spring bean装配之对jsr支持的说明

    1 解析 1.1 疑问:2.2去掉@resource注解,为什么不能赋值?不是有set方法了吗? 1.2 @resource注解版本支持 1.3 没有显式指定@resource的那么,默认名称从何获得 ...

  8. Spring课程 Spring入门篇 4-8 Spring bean装配之基于java的容器注解说明--基于泛型的自动装配

    1 解析 1.1 什么是泛型? 1.2 泛型有什么作用? 1.3 泛型装配样式? 2 代码演练 2.1 泛型应用 1 解析 1.1 什么是泛型? Java泛型设计原则:只要在编译时期没有出现警告,那么 ...

  9. 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的单例和多例的 ...

随机推荐

  1. c:foreach 使用

    <!--引入--> <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" ...

  2. 实现反转的方法(reverse)

    1.最简单的方法: public static String reverse1(String str) { return new StringBuffer(str).reverse().toStrin ...

  3. 大数据-hadoop HA集群搭建

    一.安装hadoop.HA及配置journalnode 实现namenode HA 实现resourcemanager HA namenode节点之间通过journalnode同步元数据 首先下载需要 ...

  4. python的builtins模块

    builtins模块详解 1.简介 builtins是python的内建模块,所谓内建模块就是你在使用时不需要import,在python启 动后,在没有执行程序员编写的任何代码前,python会加载 ...

  5. vue,下级页面刷新导致路由跳转带过来的数据消失的解决方法

    if(typeof(this.$route.query.result)=='string'){ //刷新时走这 }else{ //正常路由跳转过来后就把数据塞到 localStorage let ob ...

  6. Vue项目中使用HighChart

    记:初次在Vue项目中使用 HighChart 的时候要走的坑 感谢这位哥们的思路 传送门 Vue-cli项目使用 npm install highcharts --save 让我们看看 highch ...

  7. MVC返回数据流,ajax接受并保存文件

    js代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <ti ...

  8. git特殊用法

    git stash的使用 1.当前分支写了一半的代码,需要切到其他分支修复bug或者完成优先级较高的任务时 git stash 暂存分支进度 git stash list 查看草稿区 git stas ...

  9. vue 打印

    vue 方法 第一种方法:通过npm 安装插件 1,安装  npm install vue-print-nb --save 2,引入  安装好以后在main.js文件中引入  import Print ...

  10. spark第十篇:Spark与Kafka整合

    spark与kafka整合需要引入spark-streaming-kafka.jar,该jar根据kafka版本有2个分支,分别是spark-streaming-kafka-0-8和spark-str ...