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:IdeaProjectsdemo	argetclassescom
eddemoaopLogAspect.class]
16:55:44.409 [main] DEBUG org.springframework.context.annotation.ClassPathBeanDefinitionScanner - Identified candidate component class: file [D:IdeaProjectsdemo	argetclassescom
eddemoaopScreen.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