目录
1、利用注解实现AOP的基本流程java
1.一、建立一个注解,用来注解切点(pointcut)spring
1.二、建立一个service,使用上面定义的注解来指定切点测试
1.三、建立Aspect,增长业务逻辑this
1.四、建立Spring配置类spa
1.五、测试code
2、获取自定义注解的参数blog
2.一、建立带属性的自定义注解接口
2.二、建立service使用带属性的自定义注解ip
2.三、建立Aspect的错误示例get
2.四、建立Aspect的正确作法
2.五、测试
3、总结
1、利用注解实现AOP的基本流程
若是特别熟悉自定义注解实现AOP,能够直接转到第二部分:跳转。
Spring中,能够经过自定义注解的方式来实现AOP,比较简单,流程以下:
1.一、建立一个注解,用来注解切点(pointcut)
package cn.ganlixin.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface DemoAnnotation { //注意这里没有定义属性 }
1.二、建立一个service,使用上面定义的注解来指定切点
这里为了节约篇幅,就不建立service接口,再建立serviceImpl来实现接口了,直接写在service中:
package cn.ganlixin.service; import cn.ganlixin.annotation.DemoAnnotation; import org.springframework.stereotype.Service; @Service public class DemoService { @DemoAnnotation // 使用自定义的注解,声明该方法为切点方法 public void demo() { System.out.println("this is DemoService.demo()"); } }
1.三、建立Aspect,增长业务逻辑
package cn.ganlixin.aspect; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Component @Aspect public class DemoAspect { @Before("@annotation(cn.ganlixin.annotation.DemoAnnotation)") public void demoBefore() { System.out.println("this is before output message"); } }
1.四、建立Spring配置类
主要作的是:指定包扫描路径
package cn.ganlixin; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @ComponentScan("cn.ganlixin") @EnableAspectJAutoProxy public class AppConfig { }
1.五、测试
package cn.ganlixin; import cn.ganlixin.service.DemoService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class AppTest { @Test public void testAOP1() { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); DemoService demoService = context.getBean(DemoService.class); demoService.demo(); } }
输出:
this is before output message this is DemoService.demo()
2、获取自定义注解的参数
2.一、建立带属性的自定义注解
要获取自定义注解参数,就须要在自定义注解中增长几个属性,下面自定义的TestAnnotation中有两个属性:value和description。
package cn.ganlixin.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface TestAnnotation { String value(); String description() default "default description"; }
2.二、建立service使用带属性的自定义注解
service中有两个方法,分别使用了自定义注解:
package cn.ganlixin.service; import cn.ganlixin.annotation.TestAnnotation; import org.springframework.stereotype.Service; @Service public class TestService { @TestAnnotation("this is value") public void test1() { System.out.println("this is TestService.test1()"); } @TestAnnotation(value = "this is another value", description = "this is description") public void test2() { System.out.println("this is TestService.test2()"); } }
2.三、建立Aspect的错误示例
在写博客以前,我也搜过相关的博客,可是发现不少博客中写的都是利用@Around来实现获取注解信息,可是我若是须要在@Before中,@After中获取又怎么办呢?虽然能够经过如下骚操做,经过@Around来模拟@Before和@After,可是仍是感受很差。
下面仍是使用@Before来实现的。
package cn.ganlixin.aspect; import cn.ganlixin.annotation.TestAnnotation; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Component @Aspect public class TestAspect { @Before("@annotation(cn.ganlixin.annotation.TestAnnotation)") public void one(TestAnnotation testAnonotation) { System.out.println(testAnonotation.value()); System.out.println(testAnonotation.description()); } }
上面的代码看似没有问题,one()方法中接收一个TestAnnotation的参数,觉得可以获取到切点方法的注解信息,可是,IDE会告诉你以下错误:
2.四、建立Aspect的正确作法
package cn.ganlixin.aspect; import cn.ganlixin.annotation.TestAnnotation; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Component @Aspect public class TestAspect { // 先建立一个方法,方法名随意,可是须要制定@annotation为刚刚自定义的注解 @Pointcut("@annotation(cn.ganlixin.annotation.TestAnnotation)") public void test() {} // 使用@Before,须要先引入上面@Pointcut注解的方法名,在加上@annotation, // @annotation中的值,须要和action方法中的参数名称相同(必须相同,可是名称任意) @Before("test() && @annotation(testAnnotation)") public void action(TestAnnotation testAnnotation) { System.out.println("Annotation value : " + testAnnotation.value()); System.out.println("Annotation description : " + testAnnotation.description()); System.out.println("this is TestAspect.action()"); } }
划重点:
// 第2个示例,强调@annotation中的值,须要和方法参数名相同 @Before("test() && @annotation(abcdef)") public void action2(TestAnnotation abcdef) { System.out.println("Annotation value : " + abcdef.value()); System.out.println("Annotation description : " + abcdef.description()); System.out.println("this is TestAspect.action()"); }
2.五、测试
Spring的配置类不用更改,测试代码以下:
package cn.ganlixin; import cn.ganlixin.service.TestService; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class AppTest { @Test public void testAOP2() { ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class); TestService testService = context.getBean(TestService.class); testService.test1(); System.out.println("----------------------------"); testService.test2(); } }
输出:
Annotation value : this is value Annotation description : default description this is TestAspect.action() this is TestService.test1() ---------------------------- Annotation value : this is another value Annotation description : this is description this is TestAspect.action() this is TestService.test2()
3、总结
要想是获取AOP中自定义注解的参数值,主要就一点: