首先,使用注解实现AOP是基于AspectJ方式的。
创建包含切点方法的类
package cn.ganlixin.test; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component public class Demo { @Pointcut("execution(* cn.ganlixin.test.Demo.demo1())") public void demo1() { System.out.println("Demo.demo1()"); } @Pointcut("execution(* cn.ganlixin.test.Demo.demo2())") public void demo2() { System.out.println("Demo.demo2()"); } }
使用@Component注解,相当于创建一个<bean />标签,id就是类名的首字母小写。
使用@Pointcut注解来声明切点方法。
创建通知类
package cn.ganlixin.advisor; 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.springframework.stereotype.Component; @Component @Aspect public class MyAdvisor { @Before("cn.ganlixin.test.Demo.demo1()") public void myBefore() { System.out.println("前置"); } @After("cn.ganlixin.test.Demo.demo1()") public void myAfter() { System.out.println("后置"); } @Around("cn.ganlixin.test.Demo.demo1()") public Object myAround(ProceedingJoinPoint p) throws Throwable { System.out.println("环绕前置"); Object result = p.proceed(); System.out.println("环绕后置"); return result; } @AfterThrowing("cn.ganlixin.test.Demo.demo2()") public void myThrow() { System.out.println("异常通知"); } @AfterReturning("cn.ganlixin.test.Demo.demo2()") public void myAfterReturning() { System.out.println("after Returning"); } }
首先需要使用@Component来创建<bean />
然后使用@Aspect注解来标记这是一个使用AspectJ方式的AOP通知类
分别使用@Before,@After,@Around,@AfterThrowing,@AfterReturning来标记该方法绑定AOP中的哪一个部分。
注意在通知类中方法上的注解,在指定方法名称(切点)时,一定要与切点方法类中声明的切点名称相同,否则会报错。
修改配置文件
<?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" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 指定哪些包下有注解 --> <context:component-scan base-package="cn.ganlixin.test,cn.ganlixin.advisor"> </context:component-scan> <!-- 开启cglib代理 --> <aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy> </beans>
需要注意的是:
1、基于注解的方式,需要使用xmlns:context命名空间以及xsd文件。
2、Spring不会主动去解析注解,因为他不知道哪些地方有注解,所以需要使用<context:component-scan base-package=" ">来指定哪些包下面有注解,Spring才会去指定的package中扫描注解。
3、还需要开启cglib代理,即设置<aop:aspectj-autoproxy proxy-target-class="true" />
测试
package cn.ganlixin.test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class Test { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("config/applicationContext.xml"); Demo d = ac.getBean("demo", Demo.class); d.demo1(); } }