前面介绍了下Spring中的切面技术,现在说下采用注解的方式进行切面
首先肯定和之前的一样,需要一个自动代理的注解类 AnnotationAwareAspectJAutoProxyCreator
配置文件中的代码:
<?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:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd">
<bean id="person" class="cn.aop.aspectj2.Person"></bean>
<!-- 自动代理注解 <span style="font-family: Arial, Helvetica, sans-serif;">自动去查找带有注解的类和方法,和之前的那个自动代理类差不多,原理大概是遍历所有的带注解的类,然后进行一一解析。。</span>
<bean class="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"></bean>
-->
<!-- 注解自动标签,自动去查找带有注解的类和方法 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 注解的切面 需要自己写的切面了===切点+ 通知 在该类中相对之前,比较简单些-->
<bean class="cn.aop.aspectj2.MyAdvisor"></bean>
</beans>
在配置文件中,我们不难发现,最基本都是 一个被代理的对象,自动代理类,切面(可以是自己写的类,这个注解就是自己写的,当然在之前的那个就是用aop里面的)。我们需要写一个自己的切面类
切面类
package cn.aop.aspectj2;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
@Aspect
public class MyAdvisor {
private final String CUT="execution(* cn.aop.aspectj2.*.*(..))";
/*
* 在核心代码之前执行
*/
@Before(CUT)
public void advice(){
System.out.println("单独之前拦拦");
}
/*
* 在核心代码之后执行,正常退出或者异常都会调用这个
*/
@After(CUT)
public void advice2(){
System.out.println("单独之后拦拦");
}
/*
* around通知最好不用(可以用before+after来代替),因为参数依赖---但也有好处,
* 就是获得被拦截对象和相应方法的信息
*/
@Around(CUT)
public void around(ProceedingJoinPoint p) throws Throwable{
System.out.println("这是环绕前 "+p.getKind()+","+p.getTarget());
p.proceed();
System.out.println("环绕后");
}
/*
* 是针对某一个函数
* 在前面函数执行完成之后,这个才会执行,
* 但是方法中当出现异常之后,这个就不会执行的,正常退出才会执行
*/
@AfterReturning(CUT)
public void afterR(JoinPoint jp ){
System.out.println("所有之后"+jp.getKind());
}
@AfterReturning(CUT)
public void after2(){
System.out.println("所有之后222");
}
/*
* 这个在出现异常之后调用,前提是==------前面的代码没有抓住这个异常,
* 前面抓异常之后,这里是不会调用的,一般在日志里面用的比较多。
*
*/
@AfterThrowing(CUT)
public void throwex() throws Exception{
System.out.println("出异常了");
}
}
package cn.aop.aspectj2;
public class Person {
public void say(){
// Integer.parseInt("aa");//测试是否出异常
System.out.println("...这是say..");
}
public void run(){
System.out.println("这是person中的 run方法");
}
}
测试类
public class Demo2 {
@Test
public void test(){//同样的从容器中拿到配置文件,取出对象
ApplicationContext app = new ClassPathXmlApplicationContext("cn/aop/aspectj2/aspectj2.xml");
Person p=app.getBean(Person.class);
p.run();
p.say();
}
}