spring aop的使用详解

569 阅读2分钟

spring aop 面向切面编程

spring aop有注解拦截和基于方法匹配拦截两种法师。其中注解式拦截很好的控制拦截的粒度和更丰富的信息,spirng本身在事务处理@Transcational 和数据缓存@Cacheable等上都使用此形式的拦截。

pom文件中添加依赖

 <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.0.4.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        
        <!--下面三个是使用aop需要添加-->
        <!--spring aop支持-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.0.4.RELEASE</version>
        </dependency>
        <!--aspectj支持-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.8.13</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
    </dependencies>

演示注解拦截方式(基于java配置的方式进行演示)

1、在配置java中开启spring对aspectJ代理的支持。

@Configuration
@ComponentScan("com.demo.springaop")
@EnableAspectJAutoProxy // 开启spring对aspectJ代理的支持
public class AopConfig{
}

2、自定义一个注解,

@Target(ElementType.METHOD)
@Retention(RetenttionPolicy.RUNTIME)
@Documented
public @interface Action {
    String name();
}

3、声明一个切面,@Aspect,使用@After、@Before、@Around定义建言(advice)。首先在切面中(加aspect注解的类)声明了一个切点,有这个自定义注解的就是切点。然后在切面中定义一个建言,可以使用上面的切点到建言的参数。例如@After("annotationPointCut()")。意思就是说,有这个aciton注解的方法,运行的时候就会先运行这个建言中的逻辑。

@Aspect // 声明一个切面
@Component // 让切面成为spirng容器管理的bean
public class MyAspect {
    @Pointcut("@annotation(com.netopstec.springaop.annotation.Action)")//声明切点,有这个注解的就是切点
    public void annotationPointCut(){}
    
    @After("annotationPointCut()") //声明一个建言,使用上面声明的切点
    public void after(JoinPoint joinPoint) {
        MethodSignature signature = (MethodSignature)joinPont.getSignature(); // 找到切点
        Method method = signature.getMethod();  // 根据那个切点获取到有aciton的方法
        Action action = method.getAnnotation(Action.class); // 获取到方法上的注解中的内容,输出。
        System.out.println("注解式拦截:" + action.name()); //模拟打印日志操作
    }
}

4、编写被拦截的类,使用Action注解。测试这个方法的时候,结果就是建言里面的逻辑把 “注解式拦截”打印出来了。

@Service
public class DemoAnnotationService{
    @Action(name="注解式拦截")
    public void add() {}
}