spring aop理解,Spring中AOP主要用来做什么

  spring aop理解,Spring中AOP主要用来做什么

  00-1010前言Spring中AOP的功能和目标代理模式@AspectJ支持启用@AspectJ注释通过Java注释启用。支持:AspectJ注释是通过XML配置启用的。定义切割点。公共切割点匹配切割点的表达式。增强前后,异常增强。围绕增强型代理机制的代理工厂的使用得到了增强。Spring容器包含两个重要的特性:面向切割编程(AOP)和控制反转(IOC)。面向方面编程是面向对象编程(OOP)的补充。在面向对象的编程过程中,编程目标都是对象,而在面向方面的编程中,编程目标都是方面。扇区支持跨类型和跨对象的模块化(例如,事务的方面可以添加到任何地方)。

  

目录

AOP是Spring的关键特性之一。虽然Spring的IOC特性不依赖于AOP(意味着你只能使用Spring的IOC特性而不能使用AOP特性),但是两者的结合可以灵活实现很多中间件解决方案。比如我们经常使用的事务(@Transaction),就是通过AOP方案实现的。本文主要关注AOP编程中的一些术语。这些术语并不局限于Spring,而是适用于所有AOP编程。

 

  方面:面向方面编程可以跨类、跨对象的方面编程,一个方面就是一种横切关注点的模块化。连接点:程序执行过程中的一个点,如方法调用、字段访问、异常抛出等。建议:用于增强切面,包括正面增强、背面增强和环绕增强。大多数AOP框架拦截切入点,并在切入点处维护拦截器链。TargetObject:包含一个或多个方面的对象。AOPProxy:由Java动态代理或CGLib增强的代理对象。编织:将切面整合成一个完整的流程执行过程。

  

前言

Spring的AOP是用纯Java语言实现的(比如AspectJ,不是Java语言),没有任何额外的编译过程和对类加载器的修改。它适用于任何Servlet容器和应用服务。Spring的AOP只支持方法拦截,不支持字段拦截。如果用户需要使用字段拦截,可以考虑引入AspectJ等类似框架。

 

  Spring的Aop框架与其他框架有些不同。Spring的AOP框架不仅仅是为了提供一个AOP功能而设计的,它更重要的功能是结合Spring的IOC容器来提供一些企业应用服务的解决方案(比如事务等。).我们可以用和普通豆子一样的方式来定义它。Spring的AOP不支持非常细粒度的AOP,只支持容器中Bean的AOP。如果需要更细粒度的AOP,可以考虑使用AspectJ。Spring容器的一个优秀特性就是无入侵性,可以灵活选择自己的AOP方案,不一定非要用Spring方案。

  

Spring的AOP的功能和目标

Spring对接口方法默认使用Java动态代理实现AOP拦截,对非接口方法使用CGLIB字节码工具实现代理。

 

  

代理方式

@AspectJ注释可以将一个普通的Java类声明为切面。@AspectJ批注是AspectJ5引入的批注。尽管Spring可以读取AspectJ5注释来配置节元数据,但它仍然在运行时使用Spring AOP作为代理,而不是使用AspectJ编译器或编织逻辑。我们将在后面讨论如何在Spring中使用AspectJ编译器和编织逻辑。

 

  

@AspectJ的支持

Spring默认没有启用AspectJ。如果需要Spring支持相应方面的@AspectJ注释,可以通过向配置类添加注释或者使用XML (AspectJ的包是:aspectjweaver.jar)来启用配置。

 

  

启用@AspectJ

@ Configuration @ EnableAspectJAutoProxypublic类AppConfig {}

 

  

通过Java注解启用AspectJ注解支持:

AOP : AspectJ-autoproxy/

 

  00-1010启用AspectJ支持时,开发者定义的任何方面facet都会被自动检测,然后Spring AOP会截取该facet。下面两个例子展示了如何配置AspectJ方面。您可以通过添加@Component注释将facet Bean注册到Spring容器中。

  bean id=myAs

  pect" class="org.xyz.NotVeryUsefulAspect"> <!-- configure properties of the aspect here --></bean>

package org.xyz;import org.aspectj.lang.annotation.Aspect;@Aspectpublic class NotVeryUsefulAspect {}

 

  

声明一个切入点

切入点程序运行过程中我们感兴趣的一个点,Spring的AOP框架只支持发现对Spring Bean方法上的切入点,因此你可以简单的把切入点理解为SpringBean的方法。

 

  切入点确定感兴趣的连接点,从而使我们能够控制何时运行通知。springaop只支持springbean的方法执行连接点,因此可以将切入点看作与springbean上方法的执行相匹配。切入点声明由两部分组成:一部分是由名称和任何参数组成的签名,另一部分是确定我们感兴趣的方法执行的切入点表达式。在AOP的@AspectJ注释样式中,切入点签名由常规方法定义提供,切入点表达式由@pointcut注释指示(用作切入点签名的方法必须具有void返回类型)。切入点由两部分组成,一部分是用于区别不同切入点的标识(下面例子中的private void anyOldTransfer() {})),另外一部分是确定我们感兴趣的Bean方法的表达式(下面例子中的@Pointcut("execution(* transfer(..))")), 下面的例子展示了一个切入点的定义:

  

@Pointcut("execution(* transfer(..))") // the pointcut expressionprivate void anyOldTransfer() {} // the pointcut signature

Spring匹配切入点的语法使用了AspectJ5中的表达式语法,我们可以参考AspectJ文档相关的语法.

 

  

 

  

常见的切入点匹配表达

Spring支持下面常见的AspectJ切面定义语法:

 

  execution:用于匹配方法的连接点。

@Pointcut("execution(public * *(..))")private void anyPublicOperation() {}

within:用于匹配类型内的方法。

@Pointcut("within(com.xyz.myapp.trading..*)")private void inTrading() {}

this:匹配当前AOP代理对象的执行方法

@target(org.springframework.transaction.annotation.Transactional)

target:target匹配目标对象的类型,即被代理对象的类型,例如A继承了B接口,则使用target("B"),target("A")均可以匹配到A

// 当前AOP对象实现了 IPointcutService接口的任何方法@Pointcut("target(cn.javass.spring.chapter6.service.IPointcutService)")private void anyPublicOperation() {}

args:用于限定切点方法的参数类型。

args(java.io.Serializable)

@target:被代理对象应该包含指定的注解。

@target(org.springframework.transaction.annotation.Transactional)

@args: 被代理对象的参数包含指定的注解。

@args(com.xyz.security.Classified)

@within: 被代理的对象应包含指定注解

@within(org.springframework.transaction.annotation.Transactional)

@annotation:切入点包含指定的注解。

@annotation(org.springframework.transaction.annotation.Transactional)

我们可以通过&&和对多个条件进行组合,AspectJ还有很多其它的表达式,但是Spring不支持除上述表达式以外的其它表达式。AspectJ其它表达式包含: call, get, set, preinitialization, staticinitialization, initialization, handler, adviceexecution, withincode, cflow, cflowbelow, if, @this, @withincode等。

 

  我们在使用Spring的代理方法之前,应该知道其代理原理。Java动态代理只能拦截public接口方法上的调用,CGLib只能拦截public、protected和defult方法。如果你需要更深层次的拦截,可以考虑使用底层的Aspectj。

  

 

  

切面的增强

我们在上面的步骤定义好了一个切入点,我们现在就可以对这个切入点进行额外操作,这些额外操作被称为增强,Spring支持四种增强方式:前增强、后增强、异常增强和环绕增强。Spring支持在增强方法的定义上直接定义切入点。

 

  

 

  

前增强BeforeAdvice

import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;@Aspectpublic class BeforeExample { @Before("com.xyz.myapp.CommonPointcuts.dataAccessOperation()") public void doAccessCheck() { // ... }}
import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;@Aspectpublic class BeforeExample { @Before("execution(* com.xyz.myapp.dao.*.*(..))") public void doAccessCheck() { // ... }}

 

  

后增强

import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.AfterReturning;@Aspectpublic class AfterReturningExample { @AfterReturning( pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()", returning="retVal") public void doAccessCheck(Object retVal) { // ... }}

 

  

异常增强

import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.AfterThrowing;@Aspectpublic class AfterThrowingExample { @AfterThrowing( pointcut="com.xyz.myapp.CommonPointcuts.dataAccessOperation()", throwing="ex") public void doRecoveryActions(DataAccessException ex) { // ... }}

 

  

环绕增强

import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.ProceedingJoinPoint;@Aspectpublic class AroundExample { @Around("com.xyz.myapp.CommonPointcuts.businessService()") public Object doBasicProfiling(ProceedingJoinPoint pjp) throws Throwable { // start stopwatch Object retVal = pjp.proceed(); // stop stopwatch return retVal; }}

 

  

代理机制

我们前面说过,Spring AOP通过动态代理和CGLIB实现AOP对象的代理。我们可以通过如下配置设置动态代理全部走CGLIB。

 

  

<aop:config proxy-target-class="true"> <!-- other beans defined here... --></aop:config>

 

  

代理工厂的使用

Spring AOP实现代理的核心类是AspectJProxyFactory,我们可以使用这个类编程式生成代理对象:

 

  

// create a factory that can generate a proxy for the given target objectAspectJProxyFactory factory = new AspectJProxyFactory(targetObject);// add an aspect, the class must be an @AspectJ aspect// you can call this as many times as you need with different aspectsfactory.addAspect(SecurityManager.class);// you can also add existing aspect instances, the type of the object supplied must be an @AspectJ aspectfactory.addAspect(usageTracker);// now get the proxy object...MyInterfaceType proxy = factory.getProxy()

到此这篇关于Spring基础之AOP的概念介绍的文章就介绍到这了,更多相关spring aop概念内容请搜索盛行IT以前的文章或继续浏览下面的相关文章希望大家以后多多支持盛行IT!

 

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

相关文章阅读

  • spring编程式事务处理,spring编程事务
  • spring编程式事务处理,spring编程事务,详解Spring学习之编程式事务管理
  • spring的核心功能模块有几个,列举一些重要的spring模块
  • spring的核心功能模块有几个,列举一些重要的spring模块,七个Spring核心模块详解
  • spring注解和springmvc的注解,SpringMVC常用注解
  • spring注解和springmvc的注解,SpringMVC常用注解,详解springmvc常用5种注解
  • spring实现ioc的四种方法,spring的ioc的三种实现方式
  • spring实现ioc的四种方法,spring的ioc的三种实现方式,简单实现Spring的IOC原理详解
  • spring事务失效问题分析及解决方案怎么做,spring 事务失效情况
  • spring事务失效问题分析及解决方案怎么做,spring 事务失效情况,Spring事务失效问题分析及解决方案
  • spring5.0新特性,spring4新特性
  • spring5.0新特性,spring4新特性,spring5新特性全面介绍
  • spring ioc以及aop原理,springmvc aop原理
  • spring ioc以及aop原理,springmvc aop原理,深入浅析Spring 的aop实现原理
  • Spring cloud网关,spring cloud zuul作用
  • 留言与评论(共有 条评论)
       
    验证码: