AOP
AOP中涉及很多术语,常用术语的简单介绍如下:
连接点(Joinpoint):连接点是指代码中一些具有边界性质的特定位置,AOP框架可以针对连接点配置切面。连接点的类型有很多,如类初始化前、类初始化后、类的某个方法调用前、调用后、方法异常抛出时等,Spring框架的AOP功能只支持针对方法的连接点。
增强(Advice):添加特定连接点上的一段程序代码。
切入点(Poincut):指被增强的连接点。
目标对象(Target):需要添加增强的目标类。
引入(Introduction):一种特殊的增强,可以为目标类添加一些属性和方法。
织入(Weaving):将增强添加到目标类具体连接点的过程。AOP框架负责将目标类、增强连接在一起。
代理(Proxy):目标类被AOP框架织入增强后会产生一个结果类,其融合了目标类和增强逻辑,即为目标类的代理类。
切面(Aspect):切面由切入点和增强组成。
从源代码到最终运行,会经历编写源代码、编译生成字节码、加载字节码、运行程序几个阶段,在各个阶段都可以以特定的方式织入增强以实现AOP功能。
Spring AOP
Spring框架通过Java SE动态代理和cglib实现李AOP功能:当明确指定目标类实现的业务接口时,Spring使用动态代理,也可强制使用cglib;没有指定目标类的接口时,Spring使用cglib进行字节码增强。
Spring提供多种增强类型:
前置增强:是指在某个连接点方法之前执行的增强。如果这个增强不抛出异常,那么该连接点一定会被执行。
后置增强:是指连接点方法无论在任何情况下退出时所执行的增强,即无论连接点方法是正常退出还是抛出异常都会执行此增强。
返回后增强:是指连接点方法正常(没有抛出异常)执行后所执行的增强。
抛出异常后增强:是指在连接点方法抛出异常后执行的代码。
环绕增强:是指包围连接点方法的增强,环绕增强可以替代前述任何一种增强。
引介增强:引介增强是一种特殊的增强,能够使目标类实现某个指定的接口。
使用XML配置Spring AOP
<aop:config>:配置AOP功能的根元素
<aop:point>:配置AOP切入点
<aop:advisor>:配置AOP增强
<aop:aspect>:配置AOP切面
<aop:declare-parents>:配置引入增强
<aop:before>:配置前置增强
<aop:after>:配置后置增强
<aop:after-returning>:配置返回后增强
<aop:after-throwing>:配置抛出异常后增强
<aop:around>:配置环绕增强
配置示例
GoodService.java
package com.lxj.springAop;
import org.springframework.transaction.annotation.Transactional;
public class GoodsService {
private static int ORDER_NO = 10000; //用于生成订单编号
public int buyGoods(String user, String productName) {
ORDER_NO++;
System.out.println("【数据库插入订单】购买者:"+user+",商品名称:"+productName+",订单编号:"+ORDER_NO);
return ORDER_NO;
}
public void returnGoods(int orderNo) {
System.out.println("【数据库修改订单状态】订单编号:"+orderNo);
}
}
TransactionManager.java
package com.lxj.springAop;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
public class TransactionManager {
public void beginTransaction(){
System.out.println("【事务管理器】开始事务");
}
public void commitTransaction(){
System.out.println("【事务管理器】提交事务");
}
public void rollback(){
System.out.println("【事务管理器】回滚事务" );
}
}
ApplicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 业务类 -->
<bean id="service" class="com.lxj.springAop.GoodsService"></bean>
<!-- 切面类 -->
<bean id="transactionManager" class="com.lxj.springAop.TransactionManager"></bean>
<!-- 切入点 -->
<aop:config>
<aop:pointcut expression="execution( * com.lxj.springAop.*Service.*(..))"
id="transactionPointcut"/>
<aop:aspect id="transactionAspect" ref="transactionManager">
<aop:before method="beginTransaction"
pointcut-ref="transactionPointcut"/>
<aop:after-returning method="commitTransaction"
pointcut-ref="transactionPointcut"/>
<aop:after-throwing method="rollback"
pointcut-ref="transactionPointcut"/>
</aop:aspect>
</aop:config>
</beans>
测试类TestSpring.java:
package com.lxj.springAop;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class TestSpringAop {
public static void main(String[] args) {
ClassPathXmlApplicationContext context =
new ClassPathXmlApplicationContext("applicationContext.xml");
GoodsService service = (GoodsService) context.getBean("service");
service.buyGoods("张三", "劳力士");
service.returnGoods(10008);
context.close();
}
}
执行结果:
使用注解配置Spring AOP
applicationContext.java
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.3.xsd">
<!-- 业务类 -->
<bean id="service" class="com.lxj.springAop.GoodsService"></bean>
<!-- 切面类 -->
<bean id="transactionManager" class="com.lxj.springAop.TransactionManager"></bean>
<!-- 使用注解配置Aop -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>
TransactionManager.java
package com.lxj.springAop;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
@Aspect
public class TransactionManager {
@Before("execution( * com.lxj.springAop.*Service.*(..))")
public void beginTransaction(){
System.out.println("【事务管理器】开始事务");
}
@AfterReturning("execution( * com.lxj.springAop.*Service.*(..))")
public void commitTransaction(){
System.out.println("【事务管理器】提交事务");
}
@AfterThrowing("execution( * com.lxj.springAop.*Service.*(..))")
public void rollback(){
System.out.println("【事务管理器】回滚事务" );
}
}
运行结果一样。
源码和更多Spring基础学习,请点击
https://github.com/lxj786442592/Spring