`

Spring中的AOP 实现

阅读更多

一、AOP 概念
Joinpoint:它定义在哪里加入你的逻辑功能,对于Spring AOP,Jointpoint指的就是Method。

Advice:特定的Jointpoint处运行的代码,对于Spring AOP 来讲,有Before advice、AfterreturningAdvice、ThrowAdvice、AroundAdvice(MethodInteceptor)等。

Pointcut:一组Joinpoint,就是说一个Advice可能在多个地方织入,

Aspect:这个我一直迷惑,它实际是Advice和Pointcut的组合,但是Spring AOP 中的Advisor也是这样一个东西,但是Spring中为什么叫Advisor而不叫做Aspect。

Weaving:将Aspect加入到程序代码的过程,对于Spring AOP,由ProxyFactory或者ProxyFactoryBean负责织入动作。

Target:这个很容易理解,就是需要Aspect功能的对象。

Introduction:引入,就是向对象中加入新的属性或方法,一般是一个实例一个引用对象。当然如果不引入属性或者引入的属性做了线程安全性处理或者只读属性,则一个Class一个引用也是可以的(自己理解)。Per-class lifecycle or per-instance life cycle

二、AOP 种类
1、静态织入:指在编译时期就织入Aspect代码,AspectJ好像是这样做的。

2、动态织入:在运行时期织入,Spring AOP属于动态织入,动态织入又分静动两种,静则指织入过程只在第一次调用时执行;动则指根据代码动态运行的中间状态来决定如何操作,每次调用Target的时候都执行(性能较差)。

三、Spring AOP 代理原理
Spring AOP 是使用代理来完成的,Spring 会使用下面两种方式的其中一种来创建代理:
1、JDK动态代理,特点只能代理接口,性能相对较差,需要设定一组代理接口。
2、CGLIB 代理,可代理接口和类(final method除外),性能较高(生成字节码)。


四、Spring AOP 通知类型
1、BeforeAdvice:前置通知需实现MethodBeforeAdvice,但是该接口的Parent是BeforeAdvice,致于什么用处我想可能是扩展性需求的设计吧。或者Spring未来也并不局限于Method的JoinPoint(胡乱猜测)。BeforeAdvice可以修改目标的参数,也可以通过抛出异常来阻止目标运行。

2、AfterreturningAdvice:实现AfterreturningAdvice,我们无法修改方法的返回值,但是可以通过抛出异常阻止方法运行。

3、AroundAdvice:Spring 通过实现MethodInterceptor(aopalliance)来实现包围通知,最大特点是可以修改返回值,当然它在方法前后都加入了自己的逻辑代码,因此功能异常强大。通过MethodInvocation.proceed()来调用目标方法(甚至可以不调用)。

4、ThrowsAdvice:通过实现若干afterThrowing()来实现。

5、IntroductionInterceptor:Spring 的默认实现为DelegatingIntroductionInterceptor

五、Spring AOP Pointcut
以上只是Advice,如果不指定切入点,Spring 则使用所有可能的Jointpoint进行织入(当然如果你在Advice中进行方法检查除外)。因此切入点在AOP中扮演一个十分重要的角色。Spring 2.0 推荐使用AspectJ的Annocation的切入点表达式来定义切入点,或者使用<aop:xxx/>来定义AOP,这方面本篇不做考虑。

1、Pointcut:它是Spring AOP Pointcut的核心,定义了getClassFilter()和getMethodMatcher()两个方法。

2、ClassFilter:定义了matches(Class cls)一个方法。

3、MethodMatcher() 定义了matches(Method,Class),isRuntime(),matches(Mathod,Class,Object[])三个方法,如果isRuntime()返回true则表示为动态代理(实际是动态代理的动态代理),则调用第三个方法(每访问一次调用一次),否则调用第一个方法(并且只调用一次)

4、Spring AOP 静态切入点的几个实现。
ComposablePointcut 太复杂一个切入点无法表达就用这个,union MethodMatcher和ClassFilter或者intersection MethodMatcher、ClassFilter和Pointcut。为什么不实现union Pointcut? 而只能通过Pointcuts类对Pointcut进行union操作。

ControlFlowPointcut 想对程序的运行过程进行追踪就用这个

DynamicMatchMatcherPointcut 想用动态AOP 就用这个

JdkRegexpMethodPointcut 想使用正则表达式就用这个

Perl5RegexpMethodPointcut

NameMatchMethodPointcut 想用方法名字来匹配就用这个

StaticMethodMatcherPointcut 静态切入点就用这个
没有人反对你直接实现Pointcut:)。

六、Spring AOP 中的Advisor其实就是Aspect
1、 PointcutAdvisor
其实一般使用DefaultPointcutAdvisor就足够了,给它Advice和Pointcut。
当然如果想少写那么几行代码也可以使用NameMatchMethodPointcutAdvisor,RegexpMethodPointcutAdvisor等。
更多Advisor可以查看API文档。


2、 IntroductionAdvisor
默认实现为DefaultIntroductionAdvisor。

七、AOP ProxyFactory
使用代码实现AOP 可使用ProxyFactory
声明式AOP 可使用ProxyFactoryBean
ProxyFactoryBean 需要设定 target,interceptorNames(可以是Advice或者Advisor,注意顺序)
对接口代理需设置proxyInterfaces

八、自动代理
BeanNameAutoProxyCreator

Java代码 复制代码
  1. <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">   
  2.     <property name="beanNames"><value>jdk*,onlyJdk</value></property>   
  3.     <property name="interceptorNames">   
  4.         <list>   
  5.             <value>myInterceptor</value>   
  6.         </list>   
  7.     </property>   
  8. </bean>  
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
	<property name="beanNames"><value>jdk*,onlyJdk</value></property>
	<property name="interceptorNames">
		<list>
			<value>myInterceptor</value>
		</list>
	</property>
</bean>


DefaultAdvisorAutoProxyCreator

Java代码 复制代码
  1. <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>   
  2. <bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">   
  3.     <property name="transactionInterceptor" ref="transactionInterceptor"/>   
  4. </bean>   
  5. <bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>   
  6. <bean id="businessObject1" class="com.mycompany.BusinessObject1">   
  7.     <!-- Properties omitted -->   
  8. </bean>   
  9. <bean id="businessObject2" class="com.mycompany.BusinessObject2"/>  
<bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<bean class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
	<property name="transactionInterceptor" ref="transactionInterceptor"/>
</bean>
<bean id="customAdvisor" class="com.mycompany.MyAdvisor"/>
<bean id="businessObject1" class="com.mycompany.BusinessObject1">
	<!-- Properties omitted -->
</bean>
<bean id="businessObject2" class="com.mycompany.BusinessObject2"/>




九、Spring 2.0 AOP

Spring 2.0 的APO, 它引入了一种更加简单并且更强大的方式来定义切面。

首先建一个普通Java项目:com.longthsoft.learn.spring

把 spring.jar, commons-logging.jar, cglib-nodep-...jar, aspectjweaver.jar, aspectjrt.jar 放到 Build Path 下.

以止 lib 除了 spring 外, 其他的都可以在 spring 下载包的 lib 中找到

下面编码开始:

让我们先写两个简单的类:

Java代码 复制代码
  1. package com.longthsoft.learn.spring.models;   
  2.   
  3. public class A {   
  4.     public void sayHello() {   
  5.         System.out.println("Hello, I'm a");   
  6.     }   
  7. }   
Java代码 复制代码
  1. package com.longthsoft.learn.spring.models;   
  2.   
  3. public class B {   
  4.     public void sayHi() {   
  5.         System.out.println("Hi, I'm b");   
  6.     }   

 




没什么实际的东西, 只是小A和小B在打招呼

接下来把他们交给Spring吧(有点残忍)。

Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xsi:schemaLocation="   
  6.         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  7.         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">   
  8.        
  9.     <bean id="a" class="com.longthsoft.learn.spring.models.A" />   
  10.     <bean id="b" class="com.longthsoft.learn.spring.models.B" />   
  11. </beans> 

 


接下来写个Boot

Java代码 复制代码
  1. package com.longthsoft.learn.spring;   
  2.   
  3. import org.springframework.context.ApplicationContext;   
  4. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  5.   
  6. import com.longthsoft.learn.spring.models.A;   
  7. import com.longthsoft.learn.spring.models.B;   
  8.   
  9. public final class Boot {   
  10.   
  11.     public static void main(String[] args) {   
  12.         ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");   
  13.         A a = (A) ctx.getBean("a");   
  14.         a.sayHello();   
  15.            
  16.         B b = (B) ctx.getBean("b");   
  17.         b.sayHi();   
  18.     }   
  19.   
  20. }  
嘿, 这里的运行结果不帖了, 大家脑子里闪过即可。 

圣诞到了, 小A小B 介绍完自己之后,也应该说句 "Merry Christmas" 

Spring 说, 既然你们交给我, 这等 routine 就不用再麻烦了, 直接一并处理掉。 

于是:
Java代码 复制代码
  1. package com.longthsoft.learn.spring;   
  2.   
  3. import org.aspectj.lang.annotation.AfterReturning;   
  4. import org.aspectj.lang.annotation.Aspect;   
  5. import org.aspectj.lang.annotation.Pointcut;   
  6.   
  7. @Aspect  
  8. public class SimpleAspect {   
  9.   
  10.     @Pointcut("execution(* com.longthsoft.learn.spring.models.*.say*())")   
  11.     public void simplePointcut() { }   
  12.        
  13.     @AfterReturning(pointcut="simplePointcut()")   
  14.     public void simpleAdvice() {   
  15.         System.out.println("Merry Christmas");   
  16.     }   
然后修改一下配置文件
Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.     xmlns:aop="http://www.springframework.org/schema/aop"  
  5.     xsi:schemaLocation="   
  6.         http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd   
  7.         http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd">   
  8.        
  9.     <aop:aspectj-autoproxy />   
  10.        
  11.     <bean id="a" class="com.longthsoft.learn.spring.models.A" />   
  12.     <bean id="b" class="com.longthsoft.learn.spring.models.B" />   
  13.        
  14.     <bean id="simpleAspect" class="com.longthsoft.learn.spring.SimpleAspect" />   
  15. </beans>  

 


OK, 运行一下:

Hello, I'm a
Merry Christmas
Hi, I'm b
Merry Christmas

 

分享到:
评论

相关推荐

    Spring中AOP实现EHCache的整合(一)

    在本文中,我们将深入探讨如何在Spring框架中集成并使用AOP(面向切面编程)来实现对EHCache的高效管理。Spring是一个广泛使用的Java应用框架,它提供了强大的依赖注入和面向切面编程功能。而EHCache是一款流行、高...

    spring-aop-jar

    它被许多AOP框架使用,包括Spring,使得不同的AOP实现可以互相协作。它包含如`org.aopalliance.intercept.MethodInterceptor`和`org.aopalliance.aop.Advice`等核心接口。 2. spring-aop-4.1.6.RELEASE.jar:这是...

    基于注解实现SpringAop

    基于注解实现SpringAop基于注解实现SpringAop基于注解实现SpringAop

    研究下Spring中AOP的实现?

    在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点分离,将横切关注点(如日志、事务管理、...在实际项目中,可以利用Spring AOP进行事务管理、性能监控、权限控制等多种功能的实现。

    Spring AOP实现机制

    **Spring AOP 实现机制详解** Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许程序员在不修改源代码的情况下,通过“切面”来插入额外的业务逻辑,如日志、事务管理等。AOP的引入极大地提高了代码的...

    spring aop实现原理

    NULL 博文链接:https://zhang-yingjie-qq-com.iteye.com/blog/319927

    spring基于AOP实现事务

    总结一下,Spring基于AOP实现的事务管理通过TransactionProxyFactoryBean,结合声明式事务配置,能够提供一种高效且易于维护的事务解决方案。它允许我们在不修改业务逻辑的情况下,统一管理和控制事务,提升了代码的...

    spring的aop实现

    Spring AOP(面向切面编程)是Spring框架的核心特性之一,它允许开发者在不修改源代码的情况下,...在压缩包文件"springAop"中,可能包含了示例代码和配置文件,通过学习这些内容,你可以更好地理解和实践Spring AOP。

    spring-boot aop

    本示例是关于如何在Spring Boot项目中实现AOP功能的一个简单演示。 首先,我们需要了解AOP的基本概念。AOP的核心是切面(Aspect),它封装了跨越多个对象的行为或关注点,如日志记录。切点(Pointcut)定义了在何处...

    初探spring aop内部实现 java

    Spring AOP(面向切面编程)是Spring框架中的一个重要组件,它允许我们在不修改源代码的情况下,对程序的行为进行统一的管理和控制。本篇文章将深入探讨Spring AOP的内部实现,以及如何通过源代码理解其DataSource...

    Spring AOP的简单实现

    在这个场景中,我们将使用Spring AOP来实现一个日志记录的功能,以追踪系统中各个方法的调用情况,包括访问时间以及传递的参数。下面将详细阐述如何实现这一目标。 首先,我们需要了解AOP的基本概念。AOP的核心是切...

    反射实现 AOP 动态代理模式(Spring AOP 的实现原理)

    Spring框架中的AOP模块使用了动态代理来实现AOP概念。Spring AOP允许开发者定义切面,并在这些切面中指定拦截的方法。Spring AOP支持不同的代理策略,包括JDK动态代理和CGLIB代理。如果被代理的类没有实现接口,...

    Spring使用AOP的三个jar包

    在Java世界中,Spring框架以其强大的功能和灵活性深受开发者喜爱,尤其在面向切面编程(AOP)方面,Spring提供了非常全面的支持。AOP是一种编程范式,它允许程序员定义“切面”,这些切面可以封装关注点,如日志、...

    Spring的AOP实现的日志功能案例.zip

    Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志功能案例.zip Spring的AOP实现的日志功能案例....

    Spring 2.5 AOP 例子

    Spring 2.5 AOP(面向切面编程)是Java应用程序中的一个重要概念,它允许开发者在不修改原有代码的情况下插入新的行为或监控。这个例子旨在帮助我们理解和应用Spring框架的AOP特性。以下是对该主题的详细解释: 一...

    Spring实现AOP的4种方式

    在Spring框架中,AOP(面向切面编程)是一种强大的设计模式,它允许开发者将关注点从业务逻辑中分离出来,比如日志记录、事务管理、权限检查等。本篇文章将详细探讨Spring实现AOP的四种主要方法:基于代理的方式、...

    死磕Spring之AOP篇 - Spring AOP两种代理对象的拦截处理(csdn)————程序.pdf

    在 Spring 中,AOP 的实现主要依赖于代理模式,有两种代理方式:JDK 动态代理和 CGLIB 动态代理。 JDK 动态代理是基于接口的,它要求被代理的目标对象必须实现至少一个接口。Spring 使用 `java.lang.reflect.Proxy`...

    Spring Aop的简单实现

    在这个基于配置文件的实现中,我们首先需要在Spring配置文件(如applicationContext.xml)中定义一个切面。切面通常由一个或多个通知组成,我们可以使用`&lt;aop:config&gt;`标签来声明切面。例如: ```xml &lt;aop:config&gt; ...

    Spring AOP框架实现的结构分析

    在本文中,我们将从实现的角度来认识 SpringAOP 框架,从外部接口、内部实现、组成部分、执行过程四个方面来介绍 Spring AOP 框架的结构分析。 最后,本文的目标是从实现的角度来认识 SpringAOP 框架,观察的角度是...

    spring之AOP(动态代理)

    在Spring中,AOP主要通过两种动态代理技术实现:JDK动态代理和CGLIB动态代理。 首先,让我们详细了解一下JDK动态代理。JDK动态代理基于Java的接口实现,它适用于目标对象实现了至少一个接口的情况。在运行时,JDK...

Global site tag (gtag.js) - Google Analytics