使用注解实现AOP
1.导入jar包:
与用接口实现 的jar包相同
2.配置:
a.将业务类和通知类纳入SpringIoc容器;
b.在容器中开启注解对Aop的支持:
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
c.将类使用注解方式(@Component)放入IOC容器中时,要将该类所在的包添加到扫描器中;
3.编写
通知类:
1.加入注解 @Aspect,不用再实现接口;但是要开启注解对Aop的支持,该注解不需要扫描器。
如:
//通知类(使用注释方式)
@Aspect //声明该类 是一个通知类
public class LogBefore_Annotation {
}
//在IOC容器中(即applicationContext.xml中)
<!--开启注解对Aop的支持-->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
2.在通知类中使用注解定义通知类型:
前置通知:
@Before("execution(切入点)") //或 @Before(pointcut ="execution(切入点)")
如:
@Before("execution(public void org.service.impl.StudentServiceImpl.addStudent(org.entity.Student))")
public void myBefore(){
System.out.println("<<注解形式--前置通知>>");
}
后置通知:
a.不需要使用方法(切点)的返回值:
@AfterReturning("execution(切入点)")//或 @AfterReturning(pointcut ="execution(切入点)")
b.需要使用方法(切点)的返回值:
@AfterReturning(pointcut ="execution(切入点)", )
如:
@AfterReturning("execution(public void org.service.impl.StudentServiceImpl.addStudent(org.entity.Student))")
public void myAfter(){
System.out.println("<<注解形式--后置通知>>");
}
环绕通知:
@Around("execution(切入点)")//或 @Around(pointcut ="execution(切入点)")
如:
/**
* 环绕通知
* 方法参数为:ProceedingJoinPoint类型
*/
@Around("execution(public void org.service.impl.StudentServiceImpl.addStudent(org.entity.Student))")
public void myAround(ProceedingJoinPoint jp){
try{
//方法执行:前置通知
System.out.println("<<注解形式[环绕通知]--前置通知>>");
//方法执行时
jp.proceed();//执行方法
//方法执行之后:后置通知
System.out.println("<<注解形式[环绕通知]--后置通知>>");
}catch(Throwable e ){
//发生异常时:异常通知
System.out.println("<<注解形式[环绕通知]--异常通知>>");
}finally {
//最终通知
System.out.println("<<注解形式[环绕通知]--最终通知>>");
}
}
最终通知:
@After("execution(切入点)")//或 @After(pointcut ="execution(切入点)")
如:
/**
* 最终通知
*/
@After("execution(public void org.service.impl.StudentServiceImpl.addStudent(org.entity.Student))")
public void myAfter(){
System.out.println("<<注解形式--最终通知>>");
}
异常通知:
@AfterThrowing("execution(切入点)")//或 @After(pointcut ="execution(切入点)")
如:
public void myException(){
System.out.println("<<注解形式--异常通知>>");
}
特定异常通知(如捕获空指针的异常通知):
@AfterThrowing(pointcut = "execution(切入点)", throwing = "e")
如:
/**
* 异常通知
* 如果只捕获特定类型的异常,需要第二个参数来实现:e
* 如:该异常通知只捕获空指针异常 则使用:NullPointerException类型
*
* **测试该类时,需要将上述环绕通知注释掉,否则该类无法捕获异常**
*/
@AfterThrowing(pointcut = "execution(public void org.service.impl.StudentServiceImpl.addStudent(org.entity.Student))",
throwing = "e")
public void myException(JoinPoint jp, NullPointerException e){
System.out.println("<<注解形式[特定异常]--异常通知>>:e:"+e.getMessage());
}
3.获取目标对象的一些参数:
通过注解形式实现的Aop,如果想获取 目标对象的一些参数,则需要使用一个对象:JointPoint
后置通知中获取参数:
目标对象: jp.getTarget()
调用的方法名:jp.getSignature().getName()
方法的参数个数:jp.getArgs().length
方法得到返回值:returningValue
注:
注解形式返回值问题:
a.注解属性中声明返回值的参数名returning
/**
*后置通知
* @AfterReturning 中pointcut是定义的切点、 returning是切点方法返回值类型
*/
@AfterReturning(pointcut = "execution(public void org.service.impl.StudentServiceImpl.addStudent(org.entity.Student))",
returning = "returningValue")
public void myAfter(JoinPoint jp, Object returningValue){
System.out.println("<<注解形式--后置通知>>");
System.out.println("*[注解]*目标对象:"+jp.getTarget()+
",\n*[注解]*调用的方法名:"+jp.getSignature().getName()+
",\n*[注解]*方法的参数个数:"+jp.getArgs().length+
",\n*[注解]*方法得到返回值:"+returningValue);
}
b.注解形式实现aop时,通知方法中的参数不能自定义。
业务类:
StudentServiceImpl中的addStudent()方法
将通知类和业务类放入IOC容器中:
1.直接在IOC中添加<bean></bean>;
2.使用注解时,要注意将该类所在包添加到扫描器中;
使用注解:
@Component("id值")