文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

Spring中AOP的概念是什么

2023-07-02 08:57

关注

这篇文章主要介绍“Spring中AOP的概念是什么”,在日常操作中,相信很多人在Spring中AOP的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Spring中AOP的概念是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

Spring容器包含两个重要的特性:面向切面编程(AOP)和控制反转(IOC)。面向切面编程是面向对象(OOP)的一种补充,在面向对象编程的过程中编程针对的目标是一个个对象,而面向切面编程中编程针对的目标是一个个切面。切面支持跨类型跨对象(如事务的切面可以加在任何地方)进行模块化。

前言

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

Spring中AOP的概念是什么

Spring的AOP的功能和目标

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

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

代理方式

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

@AspectJ的支持

@AspectJ注解可以把一个普通的Java类声明为切面。@AspectJ注解是AspectJ5引入的注解,Spring虽然可以读取AspectJ5的注解用于切面元数据的配置,但是在运行的时候使用的仍然是Spring AOP进行代理,而没有使用AspectJ的编译器或者织入逻辑。我们会在后续讨论如何在Spring中使用AspectJ的编译器和织入逻辑。

启用@AspectJ

Spring默认没有启用AspectJ,如果你需要Spring支持@AspectJ注解对应的切面,可以通过在配置类上添加注解或者使用XML启用配置(AspectJ所在的包是:aspectjweaver.jar)。

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

@Configuration@EnableAspectJAutoProxypublic class AppConfig {}

通过XML配置启用AspectJ注解

<aop:aspectj-autoproxy/>

定义一个切面

当启用AspectJ支持之后,开发者定义的任何Aspect切面会自动地被检测到,然后Spring AOP会对切面进行拦截。下面两个例子展示了如何配置AspectJ切面,你可以通过添加@Component注解把切面Bean注册到Spring容器中。

<bean id="myAspect" 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切面定义语法:

@Pointcut("execution(public * *(..))")private void anyPublicOperation() {}
@Pointcut("within(com.xyz.myapp.trading..*)")private void inTrading() {}
@target(org.springframework.transaction.annotation.Transactional)
//    当前AOP对象实现了 IPointcutService接口的任何方法@Pointcut("target(cn.javass.spring.chapter6.service.IPointcutService)")private void anyPublicOperation() {}
args(java.io.Serializable)
@target(org.springframework.transaction.annotation.Transactional)
@args(com.xyz.security.Classified)
@within(org.springframework.transaction.annotation.Transactional)
@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的概念是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注编程网网站,小编会继续努力为大家带来更多实用的文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯