Spring AOP 的三种配置方式
方式1:使用Spring自带的AOP
public class LogAdvice implements MethodBeforeAdvice, AfterReturningAdvice,MethodInterceptor {
@Override
public void before(Method method, Object[] objects, Object target) throws Throwable {
//前置通知
}
@Override
public void afterReturning(Object result, Method method, Object[] objects, Object target) throws Throwable {
//后置通知
}
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
//环绕通知
//目标方法之前执行
methodInvocation.proceed(); //目标方法
//目标方法之后执行
return resultVal;
}
}
创建被代理对象
<bean id="orderServiceBean" class="com.apesource.service.impl.OrderServiceImpl"/>
<bean id="userServiceBean" class="com.apesource.service.impl.UserServiceImpl"/>
通知(Advice)
<bean id="logAdviceBean" class="com.apesource.log.LogAdvice"/>
<bean id="performanceAdviceBean" class="com.apesource.log.PerformanceAdvice"/>
切入点(Pointcut):通过正则表达式描述指定切入点(某些 指定方法)
<bean id="createMethodPointcutBean" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
<!--注入正则表达式:描述那些方法为切入点-->
<property name="pattern" value=".*creat.*"/>
</bean>
Advisor(高级通知) = Advice(通知) + Pointcut(切入点)
<bean id="performanceAdvisorBean" class="org.springframework.aop.support.DefaultPointcutAdvisor">
<!--注入切入点-->
<property name="pointcut" ref="createMethodPointcutBean"/>
<!--注入通知-->
<property name="advice" ref="performanceAdviceBean"/>
</bean>
创建自动代理
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<!--Bean名称规则(数组):指定那些bean创建自动代理-->
<property name="beanNames">
<list>
<value>*ServiceBean</value>
<value>*TaskBean</value>
</list>
</property>
<!--通知列表:需要执行那些通知-->
<property name="interceptorNames">
<list>
<value>logAdviceBean</value>
<value>performanceAdvisorBean</value>
</list>
</property>
</bean>
方式2:使用Aspectj实现切面(普通POJO的实现方式)
导入Aspectj相关依赖
<!--aop依赖1:aspectjrt -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
<version>1.9.5</version>
</dependency>
<!--aop依赖2: aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.5</version>
</dependency>
通知方法名随便起,没有限制
public class LogAspectj {
//前置通知
public void beforeAdvice(JoinPoint joinPoint){
System.out.println("========== 【Aspectj前置通知】 ==========");
}
//后置通知:方法正常执行后,有返回值,执行该后置通知:如果该方法执行出现异常,则不执行该后置通知
public void afterReturningAdvice(JoinPoint joinPoint,Object returnVal){
System.out.println("========== 【Aspectj后置通知】 ==========");
}
public void afterAdvice(JoinPoint joinPoint){
System.out.println("========== 【Aspectj后置通知】 ==========");
}
//环绕通知
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("##########【环绕通知中的前置通知】##########");
Object returnVale = joinPoint.proceed();
System.out.println("##########【环绕通知中的后置通知】##########");
return returnVale;
}
/**
* 异常通知:方法出现异常时,执行该通知
*/
public void throwAdvice(JoinPoint joinPoint, Exception ex){
System.out.println("出现异常:" + ex.getMessage());
}
}
使用Aspectj实现切面,使用Spring AOP进行配置
<!--业务组件bean-->
<bean id="userServiceBean" class="com.apesource.service.impl.UserServiceImpl"/>
<!--日志Aspect切面-->
<bean id="logAspectjBean" class="com.apesource.log.LogAspectj"/>
<!--使用Aspectj实现切面,使用Spring AOP进行配置-->
<aop:config>
<!--配置切面-->
<!--注入切面bean-->
<aop:aspect ref="logAspectjBean">
<!--定义Pointcut:通过expression表达式,来查找 特定的方法(pointcut)-->
<aop:pointcut id="pointcut"
expression="execution(* com.apesource.service.impl.*.create*(..))"/>
<!--配置"前置通知"-->
<!--在pointcut切入点(serviceMethodPointcut)查找到 的方法执行"前",
来执行当前logAspectBean的doBefore-->
<aop:before method="beforeAdvice" pointcut-ref="pointcut"/>
<!--配置“后置通知”-->
<!--returning属性:配置当前方法中用来接收返回值的参数名-->
<aop:after-returning returning="returnVal"
method="afterReturningAdvice" pointcut-ref="pointcut"/>
<aop:after method="afterAdvice" pointcut-ref="pointcut"/>
<!--配置"环绕通知"-->
<aop:around method="aroundAdvice" pointcut-ref="pointcut"/>
<!--配置“异常通知”-->
<!--throwing属性:配置当前方法中用来接收当前异常的参数名-->
<aop:after-throwing throwing="ex" method="throwAdvice" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
方式3:使用Aspectj实现切面(基于注解的实现方式)
//声明当前类为Aspect切面,并交给Spring容器管理
@Component
@Aspect
public class LogAnnotationAspectj {
private final static String EXPRESSION =
"execution(* com.apesource.service.impl.*.create*(..))";
//前置通知
@Before(EXPRESSION)
public void beforeAdvice(JoinPoint joinPoint){
System.out.println("========== 【Aspectj前置通知】 ==========");
}
//后置通知:方法正常执行后,有返回值,执行该后置通知:如果该方法执行出现异常,则不执行该后置通知
@AfterReturning(value = EXPRESSION,returning = "returnVal")
public void afterReturningAdvice(JoinPoint joinPoint,Object returnVal){
System.out.println("========== 【Aspectj后置通知】 ==========");
}
//后置通知
@After(EXPRESSION)
public void afterAdvice(JoinPoint joinPoint){
System.out.println("========== 【Aspectj后置通知】 ==========");
}
//环绕通知
@Around(EXPRESSION)
public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
System.out.println("##########【环绕通知中的前置通知】##########");
Object returnVale = joinPoint.proceed();
System.out.println("##########【环绕通知中的后置通知】##########");
return returnVale;
}
// 异常通知:方法出现异常时,执行该通知
@AfterThrowing(value = EXPRESSION,throwing = "ex")
public void throwAdvice(JoinPoint joinPoint, Exception ex){
System.out.println("********** 【Aspectj异常通知】执行开始 **********");
System.out.println("出现异常:" + ex.getMessage());
System.out.println("********** 【Aspectj异常通知】执行结束 **********");
}
}
<!-- 自动扫描器 -->
<context:component-scan base-package="com.apesource"/>
<!--配置Aspectj的自动代理-->
<aop:aspectj-autoproxy/>