AOP是Aspect-Oriented Programming(面向方面/切面编程)的简称。Aspect是一种新的模块化机制,用来描述分散在对象、类或函数中的横切关注点。分离关注点使解决特定领域问题的代码从业务逻辑中独立出来,业务逻辑的代码中不再含有针对特定领域问题代码的调用,业务逻辑同特定领域问题的关系通过切面来封装、维护,这样原来分散在整个应用程序中的变动就可以很好地管理起来。

Advice通知

Advice(通知)定义在连接点做什么,为切面增强提供织入接口。在Spring AOP中,它主要描述Spring AOP围绕方法调用而注入的切面行为。

Pointcut切点

Pointcut(切点)决定Advice通知应该作用于哪个连接点,也就是说通过Pointcut来定义需要增强的方法的集合,这些集合的选取可以按照一定的规则来完成。在这种情况下,Pointcut通常意味着标识方法,例如,这些需要增强的地方可以由某个正则表达式进行标识,或根据某个方法名进行匹配等。

Advisor通知器

完成对目标方法的切面增强设计(Advice)和关注点的设计(Pointcut)以后,需要一个对象把它们结合起来,完成这个作用的就是Advisor(通知器)。通过Advisor,可以定义应该使用哪个通知并在哪个关注点使用它,也就是说通过Advisor,把Advice和Pointcut结合起来,这个结合为使用IoC容器配置AOP应用,或者说即开即用地使用AOP基础设施,提供了便利。

AOP实例

项目中使用了logback来记录日志,需要生成线程流水号invokeNo来追踪线程执行过程,这里提供一种通过aop生成invokeNo的实现。

1.pom.xml中引入aop的jar包:

			<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.6.11</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.11</version>
</dependency>

2.Advice类:

public class InvokeNoAspect {

    /**
* logger
*/
private static final Logger LOGGER = LoggerFactory.getLogger(InvokeNoAspect.class); public Object process(ProceedingJoinPoint joinPoint) {
try {
MDC.put("invokeNo", UUID.randomUUID().toString().replaceAll("-", ""));
Object obj = joinPoint.proceed();
return obj;
} catch (Throwable throwable) {
LOGGER.error("MDC标识添加异常:", throwable);
throw new RuntimeException("TraceIDAspect.process,MDC标识invokeNo添加异常");
} finally {
MDC.clear();
}
}
}

3.Advisor配置:

        <context:component-scan base-package="com.xxx"/>
	<!-- kafka监听类添加线程流水号invokeNo -->
<bean id="logAspect" class="com.xxx.spring.InvokeNoAspect"/>
<aop:config>
<aop:pointcut id="pointcut" expression="execution(* com.xxx.biz..*.onMessage (..)) ||
execution(* com.xxx.web.task..*.doTask (..))"/>
<aop:aspect ref="logAspect">
<aop:around pointcut-ref="pointcut" method="process"/>
</aop:aspect>
</aop:config>

注:该配置必须放在bean注入配置后才起作用(如果是controller等类,需要在springmvc配置文件如dispatcher-servlet.xml中配置,如果是service类,需要在service bean注入的配置文件中配置)

以上是通过execution中引入方法表达式形式来描述切入点pointcut,execution的详细描述如下:

表达式 描述
public * *(..) 任何公共方法的执行
* cn.javass..IPointcutService.*() cn.javass包及所有子包下IPointcutService接口中的任何无参方法
* cn.javass..*.*(..) cn.javass包及所有子包下任何类的任何方法
* cn.javass..IPointcutService.*(*) cn.javass包及所有子包下IPointcutService接口的任何只有一个参数方法
* (!cn.javass..IPointcutService+).*(..) 非“cn.javass包及所有子包下IPointcutService接口及子类型”的任何方法
* cn.javass..IPointcutService+.*() cn.javass包及所有子包下IPointcutService接口及子类型的的任何无参方法
* cn.javass..IPointcut*.test*(java.util.Date)

cn.javass包及所有子包下IPointcut前缀类型的的以test开头的只有一个参数类型为java.util.Date的方法,注意该匹配是根据方法签名的参数类型进行匹配的,而不是根据执行时传入的参数类型决定的

* cn.javass..IPointcut*.test*(..)  throws

IllegalArgumentException, ArrayIndexOutOfBoundsException

cn.javass包及所有子包下IPointcut前缀类型的的任何方法,且抛出IllegalArgumentException和ArrayIndexOutOfBoundsException异常

* (cn.javass..IPointcutService+

&& java.io.Serializable+).*(..)

任何实现了cn.javass包及所有子包下IPointcutService接口和java.io.Serializable接口的类型的任何方法
@java.lang.Deprecated * *(..) 任何持有@java.lang.Deprecated注解的方法
@java.lang.Deprecated @cn.javass..Secure  * *(..) 任何持有@java.lang.Deprecated和@cn.javass..Secure注解的方法
(@cn.javass..Secure  *)  *(..) 任何返回值类型持有@cn.javass..Secure的方法
*  (@cn.javass..Secure *).*(..) 任何定义方法的类型持有@cn.javass..Secure的方法
* *(@cn.javass..Secure (*) , @cn.javass..Secure (*))

任何签名带有两个参数的方法,且这个两个参数都被@ Secure标记了,

如public void test(@Secure String str1, @Secure String str1);

* *((@ cn.javass..Secure *))或

* *(@ cn.javass..Secure *)

任何带有一个参数的方法,且该参数类型持有@ cn.javass..Secure;

如public void test(Model model);且Model类上持有@Secure注解

* *(

@cn.javass..Secure (@cn.javass..Secure *) ,

@ cn.javass..Secure (@cn.javass..Secure *))

任何带有两个参数的方法,且这两个参数都被@ cn.javass..Secure标记了;且这两个参数的类型上都持有@ cn.javass..Secure;

* *(

java.util.Map<cn.javass..Model, cn.javass..Model>

, ..)

任何带有一个java.util.Map参数的方法,且该参数类型是以< cn.javass..Model, cn.javass..Model >为泛型参数;注意只匹配第一个参数为java.util.Map,不包括子类型;

如public void test(HashMap<Model, Model> map, String str);将不匹配,必须使用“* *(

java.util.HashMap<cn.javass..Model,cn.javass..Model>

, ..)”进行匹配;

而public void test(Map map, int i);也将不匹配,因为泛型参数不匹配

* *(java.util.Collection<@cn.javass..Secure *>)

任何带有一个参数(类型为java.util.Collection)的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass..Secure注解;

如public void test(Collection<Model> collection);Model类型上持有@cn.javass..Secure

* *(java.util.Set<? extends HashMap>)

任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型继承自HashMap;

Spring AOP目前测试不能正常工作

* *(java.util.List<? super HashMap>)

任何带有一个参数的方法,且传入的参数类型是有一个泛型参数,该泛型参数类型是HashMap的基类型;如public voi test(Map map);

Spring AOP目前测试不能正常工作

* *(*<@cn.javass..Secure *>)

任何带有一个参数的方法,且该参数类型是有一个泛型参数,该泛型参数类型上持有@cn.javass..Secure注解;

Spring AOP目前测试不能正常工作

execution描述参考文章:https://blog.csdn.net/qq_23167527/article/details/78623639

另外,Advisor的配置也可以通过对目标类添加注解的方式进行拦截:

    <!-- 事务框架 -->
<bean id="myServiceInterceptor" class="com.xxx.template.ServiceInterceptor">
<property name="transactionTemplate" ref="myTransactionTemplate" />
</bean> <!-- 事务拦截器拦截以Service注解的bean -->
<aop:config>
<aop:pointcut id="transactionProfilePointcut" expression="@within(org.springframework.stereotype.Service)" />
<aop:advisor advice-ref="myServiceInterceptor"
pointcut-ref="transactionProfilePointcut" order="300" />
</aop:config>

也可以类似这样:

    <!-- 秒级监控日志 -->
<bean id="monitorAdviceExtends" class="com.xxx.template.MonitorAdviceExtends">
<property name="preFix" value="${monitor.preFix}"/>
</bean> <!-- 对beanName中以Biz结尾的类进行拦截 -->
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="interceptorNames">
<list>
<value>monitorAdviceExtends</value>
</list>
</property>
<property name="beanNames">
<value>*Biz</value>
</property>
</bean>

Spring技术内幕总结 - AOP概述的更多相关文章

  1. Spring技术内幕:设计理念和整体架构概述(转)

    程序员都很崇拜技术大神,很大一部分是因为他们发现和解决问题的能力,特别是线上出现紧急问题时,总是能够快速定位和解决. 一方面,他们有深厚的技术基础,对应用的技术知其所以然,另一方面,在采坑的过程中不断 ...

  2. 《spring技术内幕》读书笔记(1)——什么是POJO模式

    今天在看<spring技术内幕>,第一章中多次提到了使用POJO来完成开发,就百度了一下,在此保留 1.     什么是POJO POJO的名称有多种,pure old java obje ...

  3. Spring技术内幕:SpringIOC原理学习总结

    前一段时候我把Spring技术内幕的关于IOC原理一章看完,感觉代码太多,不好掌握,我特意又各方搜集了一些关于IOC原理的资料,特加深一下印象,以便真正掌握IOC的原理. IOC的思想是:Spring ...

  4. Spring技术内幕:Spring AOP的实现原理(二)

    **二.AOP的设计与实现 1.JVM的动态代理特性** 在Spring AOP实现中, 使用的核心技术时动态代理.而这样的动态代理实际上是JDK的一个特性.通过JDK的动态代理特性,能够为随意Jav ...

  5. Spring技术内幕:Spring AOP的实现原理(一)

    一.SpringAOP的概述 1.AOP概念 AOP是Aspect-Oriented Programming(面向切面编程)的简称.维基百科的解释例如以下: Aspect是一种新的模块化机制,用来描写 ...

  6. 深入探索spring技术内幕(一): spring概述

    一.Spring是什么? Spring是一个开源的控制反转 ( IoC ) 和面向切面 ( AOP ) 的容器框架, 它的主要目的是简化企业开发. 二.控制反转(IoC) 控制反转: 所谓的控制反转就 ...

  7. Spring技术内幕:Spring AOP的实现原理(三)

    生成SingleTon代理对象在getSingleTonInstance方法中完毕,这种方法时ProxyFactoryBean生成AopProxy对象的入口.代理对象会封装对target目标对象的调用 ...

  8. Spring技术内幕:Spring AOP的实现原理(五)

    7.Advice通知的实现 AopProxy代理对象生成时,其拦截器也一并生成.以下我们来分析下Aop是怎样对目标对象进行增强的.在为AopProxy配置拦截器的实现中,有一个取得拦截器配置过程,这个 ...

  9. Spring技术内幕——深入解析Spring架构与设计原理(一)IOC实现原理

    IOC的基础 下面我们从IOC/AOP开始,它们是Spring平台实现的核心部分:虽然,我们一开始大多只是在这个层面上,做一些配置和外部特性的使用工作,但对这两个核心模块工作原理和运作机制的理解,对深 ...

随机推荐

  1. day 34 进程线程排序 抢票 初级生产者消费者

    # 实现的内容 模拟购票 20个人买,就有一张购票查,的时候大家都看到,但是购买只能一人购买成功#利用互斥锁# from multiprocessing import Process,Lock# im ...

  2. mysql关系型和非关系型区别

    关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织优点:1.易于维护:都是使用表结构,格式一致:2.使用方便:SQL语言通用,可用于复杂查询:3.复杂操作:支持SQL,可用于 ...

  3. 使用scrapy ImagesPipeline爬取图片资源

    这是一个使用scrapy的ImagesPipeline爬取下载图片的示例,生成的图片保存在爬虫的full文件夹里. scrapy startproject DoubanImgs cd DoubanIm ...

  4. 【webdriver自动化】使用数据驱动的方式实现登录多个163账号

    练习1:使用数据驱动的方式,登录多个邮箱账号 login_info.txt: youxiang_99@163.com,XXXX youxiang_100@163.com,XXXX main.py: f ...

  5. 用optional取代null

    Java8引入了java.util.Optional<T>,它是一个封装的Optional值的类.变量存在时,Optional类只是对类简单封装.变量不存在时,缺失的值会被建模成一个空的O ...

  6. windows环境下安装Anaconda(Python)

    参考网址:http://www.jianshu.com/p/169403f7e40chttp://blog.csdn.net/qq_26898461/article/details/51488326 ...

  7. 防盗链技术终极解决方案(squid+cookie)

    防盗链技术现状:1.通过识别Referer确认请求来源页面2.Apache,squid等都能对Referer进行识别3.通过ActiveX显示的内容不向服务器提供Referer Header(例如,F ...

  8. 自定义bootbox:dialog方法

    <script src="static/ace/js/bootbox.js"></script>bootbox.dialog({ message: '< ...

  9. 软工实践第二次作业—Wordcount

    Git仓库地址:https://github.com/cwabc/PersonProject-C 一.问题描述 输入一个txt文件名,以命令行参数传入,程序能够统计txt文件中的以下几个指标: 统计文 ...

  10. lnmp架构、mysql的安装、php的安装、nginx相关

    1.lnmp架构 2.mysql的安装: mysql5.6自动安装脚本: yum install perl-Data-Dumper.x86_64 libaio.x86_64 libaio-devel. ...