AOP
面向切面编程(是一种通过预编译和运行期动态代理的方式实现在不修改源代码的情况下给程序动态添加功能的技术)。
切入点(Pointcut): 在哪些类,哪些方法上切入(where)
通知(Advice): when:方法前/方法后/方法前后,what:增强的功能 。
切面(Aspect): 切面 = 切入点 + 通知,通俗点就是:在什么时机,什么地方,做什么增强!
织入(Weaving): 把切面加入到对象,并创建出代理对象的过程。(由 Spring 来完成)。
五种增强
AOP实现步骤
引入jar包
<!--pom.xml-->
<!--使用JoinPrint需要引入包 ,另外还需引入log4j包-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
引入xml头部
<!--spring-config.xml头部-->
xmlns:aop="http://www.springframework.org/schema/aop"
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
AOP配置标签
<!--spring-config.xml-->
<!-- 扫描包中注解标注的类 -->
<context:component-scan base-package="com.hz.service,com.hz.dao,com.hz.aop" />
<!--实例化Spring01Logger-->
<bean class="com.hz.aop.Spring01Logger" id="spring01Logger"></bean>
<!--AOP-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pointcutLog" expression="execution(* com.hz.service..*.*(..))"/>
<!--增强类绑定-->
<aop:aspect ref="spring01Logger">
<!--织入,连接点-->
<!--前置增强 method:Spring01Logger类的logger() pointcut-ref:切入点名-->
<aop:before method="beforeLogger" pointcut-ref="pointcutLog"></aop:before>
<!--后置增强-->
<aop:after-returning method="afterReturningLogger" pointcut-ref="pointcutLog" returning="ref"></aop:after-returning>
<aop:after method="afterLogger" pointcut-ref="pointcutLog" ></aop:after>
<aop:after-throwing method="afterThrowingLogger" pointcut-ref="pointcutLog" throwing="e"/>
</aop:aspect>
</aop:config>
增强处理类
public class Spring01Logger {
public void beforeLogger(){
System.out.println("这是日志文件!前置增强!");
}
public void afterReturningLogger(Object ref){
System.out.println("这是日志文件!后置增强!返回值---"+ref);
}
public void afterLogger(){
System.out.println("这是日志文件!最终增强!");
}
public void afterThrowingLogger(RuntimeException e){
System.out.println("这是日志文件!异常增强!异常---"+e);
}
}
AOP注解
开启注解
<!--开启AOP注解-->
<aop:aspectj-autoproxy/>
@Component
是一个通用的 Spring 注解,用于将一个类标记为 Spring 容器中的一个组件。Spring 会自动检测并注册这些组件,以便在应用程序中使用依赖注入等功能。
@Aspect
是 Spring AOP 中的一个注解,用于定义一个切面(Aspect)。切面是横切关注点的一个模块化单元,它允许你将跨越多个对象的功能(如日志记录、事务管理等)分离出来。
@Pointcut
它主要用于定义切入点(Pointcut),即指定哪些方法或连接点应该被AOP框架拦截和增强处理。
@Before("printCut()")
前置增强。
@AfterReturning(value = "printCut()",returning = "ref")
后置增强,returning:方法返回值。
@After("printCut()")
最终增强。
@AfterThrowing(value = "printCut()",throwing = "e")
异常增强,throwing:方法异常返回值。
使用注解:
//Spring01Logger
@Component //实现Bean组件的定义
@Aspect //定义切面
public class Spring01Logger {
@Pointcut("execution(* com.hz.service..*.*(..))")
public void printCut(){}//公共切入点
@Before("printCut()")
public void beforeLogger(JoinPoint jp){
System.out.println("这是日志文件!前置增强!");
System.out.println("调用 " + jp.getTarget() + " 的 " + jp.getSignature().getName()
+ " 方法。方法入参:" + Arrays.toString(jp.getArgs()));
}
@AfterReturning(value = "printCut()",returning = "ref")
public void afterReturningLogger(Object ref){
System.out.println("这是日志文件!后置增强!返回值---"+ref);
}
@After("printCut()")
public void afterLogger(){
System.out.println("这是日志文件!最终增强!");
}
@AfterThrowing(value = "printCut()",throwing = "e")
public void afterThrowingLogger(RuntimeException e){
System.out.println("这是日志文件!异常增强!异常---"+e);
}
}
spring-config.xml中的以下的代码就可以注释掉了
<!--实例化Spring01Logger-->
<bean class="com.hz.aop.Spring01Logger" id="spring01Logger"></bean>
<!--AOP-->
<aop:config>
<!--配置切入点-->
<aop:pointcut id="pointcutLog" expression="execution(* com.hz.service..*.*(..))"/>
<!--增强类绑定-->
<aop:aspect ref="spring01Logger">
<!--织入,连接点-->
<!--前置增强 method:Spring01Logger类的logger() pointcut-ref:切入点名-->
<aop:before method="beforeLogger" pointcut-ref="pointcutLog"></aop:before>
<!--后置增强-->
<aop:after-returning method="afterReturningLogger" pointcut-ref="pointcutLog" returning="ref"></aop:after-returning>
<aop:after method="afterLogger" pointcut-ref="pointcutLog" ></aop:after>
<aop:after-throwing method="afterThrowingLogger" pointcut-ref="pointcutLog" throwing="e"/>
</aop:aspect>
</aop:config>
我的spring-config.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:aop="http://www.springframework.org/schema/aop"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx.xsd">
<!-- 扫描包中注解标注的类 -->
<context:component-scan base-package="com.hz.service,com.hz.dao,com.hz.aop" />
<!--开启AOP注解-->
<aop:aspectj-autoproxy/>
</beans>