Xml配置AspectJ
配置的前提是关于AspectJ的包导入好,切面类(就是操作的前后要执行的方法所在的类)编写好了,并且切入点找好。
<?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:contest="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--全自动aop
1.在bean中配置aop约束
2.配置aop:config内容,把切入点和通知结合
-->
<bean id="studentService" class="Spring.AOP.AddStudent"/>
<!--已有的切面类-->
<bean id="myAspect" class="Spring.AOP.MyAspect"/>
<aop:config>
<!--引用已有的切面类-->
<aop:aspect ref="myAspect">
<!--配置这个切入点-->
<aop:pointcut id="myPointcut" expression="execution(* Spring.AOP.AddStudent.*(..))"/>
<!--配置前置通知-->
<aop:before method="before" pointcut-ref="myPointcut"/>
<!--配置环绕通知-->
<aop:around method="myAround" pointcut-ref="myPointcut"/>
<!--配置异常通知-->
<aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointcut" throwing="throwable"/>
<!--最终通知-->
<aop:after-returning method="myAfter" pointcut-ref="myPointcut" returning="retValue"/>
</aop:aspect>
</aop:config>
</beans>
这个执行顺序就不多介绍了,在xml配置时对应的标签要对应切面类里相应的方法就好了。在切面类里要注意环绕通知和最终通知,以及异常通知。
/*
环绕通知
*/
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知");
System.out.println(pjp.getSignature().getName());
System.out.println("开启事务");
//这个方法是放行
Object retObj = pjp.proceed();
System.out.println("关闭事务");
return retObj;
}
如果执行环绕通知的话,还是要注意放行方法以及返回值。
最终通知和异常通知就不说了,和上边的方法比较类似。但是一旦有异常发生时,最终通知总能执行到。
注解配置
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:contest="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd">
<!--//扫描注解的位置-->
<contest:component-scan base-package="Spring"/>
<!--配置aop注解生效-->
<aop:aspectj-autoproxy/>
</beans>
这样在切面类里就可以用注解了
package Spring.AOP;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
/*
*
* #date: 2019/12/9
* #description 切面类增强了代码和切入点的结合
*/
@Component
@Aspect
public class MyAspect {
//声明一个公共的切入点
@Pointcut("execution(* Spring.AOP.AddStudent.*(..))")
public void myPointcut(){
}
@Before("myPointcut()")
public void before(){
System.out.println("开启事务切面类");
}
@After("execution(* Spring.AOP.AddStudent.*(..))")
public void after(){
System.out.println("提交事务切面类");
}
@Around("execution(* Spring.AOP.AddStudent.*(..))")
public Object myAround(ProceedingJoinPoint pjp) throws Throwable {
System.out.println("环绕通知");
System.out.println(pjp.getSignature().getName());
System.out.println("开启事务");
//这个方法是放行
Object retObj = pjp.proceed();
System.out.println("关闭事务");
return retObj;
}
@AfterThrowing(pointcut = "myPointcut()",throwing = "throwable")
public void myAfterThrowing(JoinPoint joinPoint,Throwable throwable){
System.out.println("异常通知" + joinPoint.getSignature().getName()+"==="+throwable.getMessage());
}
//最终通知
@AfterReturning(pointcut = "execution(* Spring.AOP.AddStudent.*(..))",returning = "retValue")
public void myAfter(JoinPoint joinPoint,Object retValue){
System.out.println("最终通知");
System.out.println("返回值"+retValue);
}
}
这里要注意 @Pointcut(“execution(* Spring.AOP.AddStudent.*(…))”)这个注解,要是用这个注解很简单,就在一个空方法上添加这样的注解并设置执行的范围就好。这样就可以使用一个公共的切入点使得下面的切面不用每次都写执行的范围了。上图中部分使用的公共切面类,部分没有