Spring AOP的原理及应用


 AOP(Aspect-Oriented Programming,面向切面编程),可以说是OOP的补充和完善。它是通过预编译方式和运行期动态代理实现程序功能的统一维护。


 开发人员在编写应用程序时,通常包含两种代码:一种是和业务系统有关系的代码,一种是和业务系统关系不大的代码,例如日志,事务处理,权限处理等等。


 以前的程序中,这两种代码是写在一起的。这样一来,程序中到处充满着相同或类似的代码,不利于维护。而Aop的目标就是使这两种代码分离解耦,这样程序员就能专心于业务的处理,而且达到维护和重用的目的。

拿日志记录这个例子来看。每个方法都需要进行日志记录,不使用Aop的时候,每个方法中都要包含日志记录的代码,这样就会产生重复,而且日志记录和业务代码紧紧耦合,不利于维护。使用AOP的思想,可以把日志看成是一个切面,所有需要日志记录的方法都要经过这个切面。这样就可以把日志记录的代码封装,当方法经过切面的时候执行,这样就实现了代码重用。

AOP和OOP的区别:


 OOP(面向对象编程)针对业务处理过程的实体及其属性和行为进行抽象封装,以获得更加清晰高效的逻辑单元划分。

 AOP则是针对业务处理过程中的切面进行提取,它所面对的是处理过程中的某个步骤或阶段,以获得逻辑过程中各部分之间低耦合性的隔离效果。


 一个程序分为核心关注点和横切关注点,OOP关注核心,AOP关注横切。

AOP中常用术语:

  • Joinpoint:连接点,程序执行的具体位置。Spring中连接点指的是方法。
  • Pointcut:切点,具体选择哪个方法作为连接点即为切点。
  • Advice:通知/增强,是指在特定的连接点,AOP框架执行的动作。
  • Target:目标对象,添加连接织入的目标类,也就是被代理对象。
  • Weaving:织入,是指增强代码植入到目标类具体连接点上的过程。
  • Proxy:代理,对目对象进行增强,生成代理对象。

重点说一下:


 joinpoint:一般是一个类或一个方法具有边界性质的特定点,如方法执行之前、方法执行之后,方法抛出异常之后等。Spring只支持方法类型的连接点,所以spring中连接点指方法。连接点包括两个信息:哪个方法和方位(在方法执行的什么位置),在spring中,用切点表示执行点,用增强表示方位。


 Weaving:AOP有三种织入方式:


 
 1)编译器织入 (如使用AspectJ编译器)


 
 2)类装载期织入


 
 3)运行期织入 (采用动态代理)

Spring AOP:


 Spring AOP 是基于AOP思想实现的一个项目。Spring 1.2 开始支持AOP,Spring AOP使用纯Java实现,不需要专门的编译过程和类加载器,在运行期通过代理方式向目标类织入增强代码,实现对代理对象中原有业务逻辑进行增强。

 Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(Auditing)和事务(Transaction)管理)进行内聚性的开发。

Spring AOP实现过程:


 1、配置XML <aop:aspectj-autoproxy>或@EnableAspectJAutoProxy注解来开启AOP自动代理对象。spring IOC容器在启动时会将配置的目标对象bean、切面及相关通知信息,解析成Advisor对象对应的BeanDefintion,并把代理对象的配置信息保存在ProxyConfig对象中。


 2、解析切面配置信息。通过Spring 对advisor信息进行处理,判断是否需要使用动态代理,使用哪种动态代理方式。


 3、使用JDK或者CGLIB代理,如果没有设置指定代理目标类,AOP自动识别进行动态代理,目标对象是接口类则使用JDK代理,否则就使用CGLIB代理。

图解Spring aop原理:

《Spring AOP的原理及应用》

原理讲解:


 AbstractAutoProxyCreator继承了ProxyConfig,且实现了SmartInstantiationAwareBeanPostProcessor , BeanFactoryAware接口,当IOC容器启动时,会创建AbstractAutoProxyCreator对象。实现BeanFactoryAware意味着,在AbstractAutoProxyCreator实例初始化阶段,BeanFactory自动注入DefaultListableBeanFactory工厂给AbstractAutoProxyCreator实例使用,有BeanFactory对象则可以通过getBean方法来访问容器中所有的通知对象Advisor相关信息.每当调用BeanFactory取得bean对象时,利用实现了SmartInstantiationAwareBeanPostProcessor的后置处理器功能,BeanFactory会在多个阶段自动调用AbstractAutoProxyCreator这个后置处理器的实现方法,这些实现方法用来判断该Bean是否需要代理,判断Bean是否需要的代理的依据是根据该bean对象是否在IOC容器中存在匹配的一个或多个通知Advisor对象,存在则需要代理,否则,就放过。


 根据bean对象的信息,从工厂中查询匹配的一个或多个通知Advisor对象,工厂通过Advisor.class类型查询到所有的Advisor类型,然后使用bean的class类型与Advisor对应的目标类型匹配,匹配成功的就取得该通知对象形成集合,并包装成Advisor接口对象集合。


 AdvisedSupport从用户定义的信息中取得包含了所有关于目标对象的信息和设置,还包括通知器拦截器等,这个对象是生成AOP代理方法的输入参数。代理工厂ProxyFactory继承了AdvisedSupport拥有了代理需要的配置,调用getProxy方法来得到代理对象Object。getProxy方法实现是根据bean的信息不同进行不同的代理方式:JDK代理或CGLIB代理。

Spring AOP在项目中实现:

 Spring AOP在项目中时通过AspectJ的语法来实现的,在Spring中实现AOP需要加入以下的Jar包,通过对切面进行配置来来实现。

spring aop所要依赖的Jar包:


 aopalliance-1.0.jar –AOP联盟标准包


 aspectjweaver-1.8.5.jar –AspectJ框架的jar包


 spring-aop-4.3.2.RELEASE.jar –Spring Aop的包

 spring-aspects-4.3.2.RELEASE.jar –Spring对AspectJ整合的jar包
Spring Aop常使用于声明式事务,用来对项目中的事务进行管理。
 Spring的声明式事务顾名思义就是采用声明的方式来处理事务,就是指在配置文件中声明。用在Spring配置文件中声明式的处理事务来代替代码式的处理事务。
 事务管理不侵入开发的组件。具体来说,业务逻辑对象就不会意识到正在事务管理之中。
 易于维护。如果要改变事务的管理策略,只需要对配置文件进行修改。
 粒度只能作用到方法级别,不能像编程式事务一样可以作用到代码块。
配置方式:

<bean id="transactionManager"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>
<tx:advice id="transactionService" transaction-manager="transactionManager">
	<tx:attributes>
		<tx:method name="add*" propagation="REQUIRED" />
		<tx:method name="insert*" propagation="REQUIRED" />
		<tx:method name="delete*" propagation="REQUIRED" />
		<tx:method name="remove*" propagation="REQUIRED" />
		<tx:method name="update*" propagation="REQUIRED" />
		<tx:method name="save*" propagation="REQUIRED" />
		<tx:method name="select*" propagation="SUPPORTS" />
		<tx:method name="find*" propagation="SUPPORTS" />
		<tx:method name="get*" propagation="SUPPORTS" />
	</tx:attributes>
</tx:advice>
<aop:config>
	<aop:pointcut id="transactionPointcut"
		expression="execution(* com.cat.arain.manager.impl.*.*(..))" />
	<aop:advisor pointcut-ref="transactionPointcut"
		advice-ref="transactionService" />
</aop:config>

因为事务是由事务管理器控制的,所以必须对事务管理器进行配置。

Spring AOP 默认使用JDK的动态代理方式。如果要使用CGLIB的代理方式的话,需要修改配置文件。

<aop:config proxy-target-class=“true”> 默认为false

下图为不同代理结果,第一张是cglib,第二张为jdk代理:

《Spring AOP的原理及应用》

《Spring AOP的原理及应用》

    原文作者:AOP
    原文地址: https://blog.csdn.net/lpy1239064101/article/details/79187492
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞