Springboot学习笔记(4)——AOP
OOP是通过继承和实现接口达到复用的目的,但它使代码的耦合度增强。
AOP是通过另一种松耦合的方式实现了类共享功能的目的,是OOP的补充。
AOP分为两种方式:注解拦截式和方法规则拦截式。前者在方法上添加自定义注解,然后通过该注解找到相应的方法,后者则是通过类似正则匹配规则来找到相应的方法。然后进行相应的注入操作。
其实现步骤如下:
1、增加Spring AOP的jar包。
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.1.5.RELEASE</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjrt</artifactId> <version>1.9.2</version> </dependency> <dependency> <groupId>org.aspectj</groupId> <artifactId>aspectjweaver</artifactId> <version>1.9.2</version> </dependency>
2、编写拦截规则的注解(如果是方法规则拦截式则跳过此步骤)
package com.red.demo.aop; import java.lang.annotation.Documented; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) @Documented public @interface Action { String name(); }
3、编写被拦截类
package com.red.demo.aop; import org.springframework.stereotype.Service; @Service public class Screen { @Action(name="电影放映即将开始!") public void start(){ System.out.println("【FBI WARNING】"); } public void display(){ System.out.println( "我命由我不由天!"); } }
这里两种拦截方法,注解拦截式和方法规则拦截式都用了。
4、编写切面
package com.red.demo.aop; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.aspectj.lang.reflect.MethodSignature; import org.springframework.stereotype.Component; @Aspect @Component public class LogAspect { @Pointcut("@annotation(com.red.demo.aop.Action)") public void movieStart(){} @After("movieStart()") public void after(JoinPoint joinPoint){ MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); Action action = method.getAnnotation(Action.class); System.out.println("注解式拦截:"+action.name()+"()"); } @Before("execution(* com.red.demo.aop.Screen.*(..))")//注意第一个星号后面的空格 public void before(JoinPoint joinPoint){ MethodSignature signature = (MethodSignature) joinPoint.getSignature(); Method method = signature.getMethod(); System.out.println("方法规则拦截式:"+method.getName()+"()"); } }
5、编写配置类
package com.red.demo.aop; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @ComponentScan("com.red.demo.aop") @EnableAspectJAutoProxy public class AOPConfig { }
6、运行
package com.red.demo; import com.red.demo.aop.AOPConfig; import com.red.demo.aop.Screen; import org.springframework.context.annotation.AnnotationConfigApplicationContext; public class DemoApplication { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AOPConfig.class); Screen screen = context.getBean(Screen.class); screen.start(); screen.display(); context.close(); } }
运行结果:
16:55:44.284 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@175e721
16:55:44.300 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor'
16:55:44.409 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\IdeaProjects\demo\target\classes\com\red\demo\aop\LogAspect.class]
16:55:44.409 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:\IdeaProjects\demo\target\classes\com\red\demo\aop\Screen.class]
16:55:44.566 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor'
16:55:44.566 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory'
16:55:44.566 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor'
16:55:44.566 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor'
16:55:44.581 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator'
16:55:44.659 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'AOPConfig'
16:55:44.675 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void com.red.demo.aop.LogAspect.before(org.aspectj.lang.JoinPoint)
16:55:44.691 [main] DEBUG org.springframework.aop.aspectj.annotation.ReflectiveAspectJAdvisorFactory - Found AspectJ method: public void com.red.demo.aop.LogAspect.after(org.aspectj.lang.JoinPoint)
16:55:44.878 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'logAspect'
16:55:44.878 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'screen'
方法规则拦截式:start()
【FBI WARNING】
注解式拦截:电影放映即将开始!
方法规则拦截式:display()
我命由我不由天!
16:55:44.991 [main] DEBUG org.springframework.context.annotation.AnnotationConfigApplicationContext - Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@175e721, started on Sun Aug 11 16:55:44 CST 2019