spring 实现AOP的四种方式

Dear 丶 2022-09-26 03:53 262阅读 0赞

一、什么是AOP

  1. AOPAspect-OrientedProgramming,面向方面编程),可以说是OOPObject-Oriented Programing,面向对象编程)的补充和完善。OOP引入封装、继承和多态性等概念来建立一种对象层次结构,用以模拟公共行为的一个集合。当我们需要为分散的对象引入公共行为的时候,OOP则显得无能为力。也就是说,OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如日志功能。日志代码往往水平地散布在所有对象层次中,而与它所散布到的对象的核心功能毫无关系。对于其他类型的代码,如安全性、异常处理和透明的持续性也是如此。这种散布在各处的无关的代码被称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
  2. AOP技术则恰恰相反,它利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,即方面。所谓“方面”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。AOP代表的是一个横向的关系,如果说“对象”是一个空心的圆柱体,其中封装的是对象的属性和行为;那么面向方面编程的方法,就仿佛一把利刃,将这些空心圆柱体剖开,以获得其内部的消息。而剖开的切面,也就是所谓的“方面”了。然后它又以巧夺天功的妙手将这些剖开的切面复原,不留痕迹。
  3. 使用“横切”技术,AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”

#

  1. 实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。

二、AOP相关概念

方面(Aspect):一个关注点的模块化,这个关注点实现可能另外横切多个对象。事务管理是J2EE应用中一个很好的横切关注点例子。方面用Spring的 Advisor或拦截器实现。

连接点(Joinpoint):程序执行过程中明确的点,如方法的调用或特定的异常被抛出。

通知(Advice): 在特定的连接点,AOP框架执行的动作。各种类型的通知包括“around”、“before”和“throws”通知。通知类型将在下面讨论。许多AOP框架包括Spring都是以拦截器做通知模型,维护一个“围绕”连接点的拦截器链。Spring中定义了四个advice: BeforeAdvice, AfterAdvice, ThrowAdvice和DynamicIntroductionAdvice

切入点(Pointcut): 指定一个通知将被引发的一系列连接点的集合。AOP框架必须允许开发者指定切入点:例如,使用正则表达式。 Spring定义了Pointcut接口,用来组合MethodMatcher和ClassFilter,可以通过名字很清楚的理解, MethodMatcher是用来检查目标类的方法是否可以被应用此通知,而ClassFilter是用来检查Pointcut是否应该应用到目标类上

引入(Introduction):添加方法或字段到被通知的类。 Spring允许引入新的接口到任何被通知的对象。例如,你可以使用一个引入使任何对象实现 IsModified接口,来简化缓存。Spring中要使用Introduction, 可有通过DelegatingIntroductionInterceptor来实现通知,通过DefaultIntroductionAdvisor来配置Advice和代理类要实现的接口

目标对象(Target Object):包含连接点的对象。也被称作被通知或被代理对象。POJO

AOP代理(AOP Proxy):AOP框架创建的对象,包含通知。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。

织入(Weaving): 组装方面来创建一个被通知对象。这可以在编译时完成(例如使用AspectJ编译器),也可以在运行时完成。Spring和其他纯Java AOP框架一样,在运行时完成织入。

三、AOP相关概念理解

1.通知(Advice): 通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。
2.连接点(Joinpoint): 程序能够应用通知的一个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。

3.切入点(Pointcut) :通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,Spring中允许我们方便的用正则表达式来指定

4.切面(Aspect) :通知和切入点共同组成了切面:时间、地点和要发生的“故事”

5.引入(Introduction) :引入允许我们向现有的类添加新的方法和属性(Spring提供了一个方法注入的功能)

6.目标(Target) :即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做的事)

7.代理(proxy) :应用通知的对象,详细内容参见设计模式里面的代理模式

8.织入(Weaving) :把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:

  1. (1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器
  2. (2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码
  3. (3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

四、spring AOP四种实现方式

配置可以通过xml文件来进行,大概有四种方式:

  1. 配置ProxyFactoryBean,显式地设置advisors, advice, target等(基于代理的AOP )

  2. 配置AutoProxyCreator,这种方式下,还是如以前一样使用定义的bean,但是从容器中获得的其实已经是代理对象

  3. 通过来配置(纯POJO切面)

  4. 通过来配置,使用AspectJ的注解来标识通知及切入点

五、spring具体实现

1. 经典的基于代理的AOP

Spring支持五种类型的通知:
Before(前) org.apringframework.aop.MethodBeforeAdvice
After-returning(返回后) org.springframework.aop.AfterReturningAdvice

  1. **After-throwing(抛出后)** org.springframework.aop.ThrowsAdvice
  2. **Arround(周围)** org.aopaliance.intercept.MethodInterceptor
  3. **Introduction(引入)** org.springframework.aop.IntroductionInterceptor

步骤:
1、创建通知:实现这几个接口,把其中的方法实现了
2、定义切点和通知者:在Spring配制文件中配置这些信息

  1. 3、使用ProxyFactoryBean来生成代理

具体做法:

  1. 1. 创建通知:

" class="reference-link">Center

Center 1

Center 2

在spring配置文件里添加:

Center 3

2、定义切点和通知者:

定义切点的常用的两种方式:1)使用正则表达式 2)使用AspectJ表达式,这里用正则表达式

在spring配置文件里添加:

Center 4

切入点和通知都配置完成,接下来该调用ProxyFactoryBean产生代理对象

在spring配置文件里添加:

Center 5

3、使用ProxyFactoryBean来生成代理

  1. ProxyFactoryBean是一个代理,我们可以把它转换为proxyInterfaces中指定的实现该interface的代理对象

Center 6

运行结果:

Center 7

2、配置AutoProxyCreator方式

  1. 上面这个过程貌似有点复杂,尤其是配置切点跟通知,Spring提供了一种自动代理的功能,能让切点跟通知自动进行匹配,修改配置文件如下:

Xml代码

  1. <bean id=”sleepHelper” class=”test.spring.aop.bean.SleepHelper”>
  2. <bean id=”sleepAdvisor” class=”org.springframework.aop.support.RegexpMethodPointcutAdvisor”>
  3. <property name=”advice” ref=”sleepHelper”/>
  4. <property name=”pattern” value=”.*sleep”/>
  5. <bean id=”human” class=”test.spring.aop.bean.Human”>
  6. <bean class=”org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator”/>

执行程序:

Java代码

  1. public class Test {
  2. public static void main(String[] args){
  3. ApplicationContext appCtx = new ClassPathXmlApplicationContext(“applicationContext.xml”);
  4. Sleepable sleeper = (Sleepable)appCtx.getBean(“human”);
  5. sleeper.sleep();
  6. }
  7. }

成功输出结果跟前面一样!
只要我们声明了org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator(我勒个去的,名太长了)就能为方法匹配的bean自动创建代理!

3、使用AspectJ的注解

用@Aspect的注解来标识切面,注意不要把它漏了,否则Spring创建代理的时候会找不到它,@Pointcut注解指定了切点,@Before和 @AfterReturning指定了运行时的通知,注意的是要在注解中传入切点的名称

Center 8

Spring配置文件:

Center 9

测试代码:

Center 10

4、通过来配置(纯POJO切面)

前面我们用到了标签,Spring在aop的命名空间里面还提供了其他的配置元素:

定义一个AOP通知者

后通知

返回后通知

抛出后通知

周围通知

定义一个切面

前通知

顶级配置元素,类似于这种东西

定义一个切点

主要的类的代码变化不大:

Center 11

Center 12

Spring的配置文件:

Center 13

测试代码:

Center 14

http://blog.csdn.net/wangpeng047/article/details/8560694 Spring Aop实例 (注解、来配置方式实现)

http://blog.csdn.net/a352193394/article/details/7345860 使用Spring的注解方式实现AOP

发表评论

表情:
评论列表 (有 0 条评论,262人围观)

还没有评论,来说两句吧...

相关阅读