Spring AOP-基于@AspectJ风格

关于Spring AOP,可以去看看官方文档

 https://docs.spring.io/spring-framework/docs/current/spring-framework-reference/core.html#aop

  • Aspect: A modularization of a concern that cuts across multiple classes. Transaction management is a good example of a crosscutting concern in enterprise Java applications. In Spring AOP, aspects are implemented by using regular classes (the schema-based approach) or regular classes annotated with the @Aspect annotation (the @AspectJ style).

  • Join point: A point during the execution of a program, such as the execution of a method or the handling of an exception. In Spring AOP, a join point always represents a method execution.

  • Advice: Action taken by an aspect at a particular join point. Different types of advice include “around”, “before” and “after” advice. (Advice types are discussed later.) Many AOP frameworks, including Spring, model an advice as an interceptor and maintain a chain of interceptors around the join point.

  • Pointcut: A predicate that matches join points. Advice is associated with a pointcut expression and runs at any join point matched by the pointcut (for example, the execution of a method with a certain name). The concept of join points as matched by pointcut expressions is central to AOP, and Spring uses the AspectJ pointcut expression language by default.

  • Introduction: Declaring additional methods or fields on behalf of a type. Spring AOP lets you introduce new interfaces (and a corresponding implementation) to any advised object. For example, you could use an introduction to make a bean implement an IsModified interface, to simplify caching. (An introduction is known as an inter-type declaration in the AspectJ community.)

  • Target object: An object being advised by one or more aspects. Also referred to as the “advised object”. Since Spring AOP is implemented by using runtime proxies, this object is always a proxied object.

  • AOP proxy: An object created by the AOP framework in order to implement the aspect contracts (advise method executions and so on). In the Spring Framework, an AOP proxy is a JDK dynamic proxy or a CGLIB proxy.

  • Weaving: linking aspects with other application types or objects to create an advised object. This can be done at compile time (using the AspectJ compiler, for example), load time, or at runtime. Spring AOP, like other pure Java AOP frameworks, performs weaving at runtime.

官方文档对aop一些概念的定义:

join point:在spring aop中就是指方法(你要横切的方法)。

Pointcut:join point的集合。

target Object:目标对象。

AOP proxy:代理对象。

advice:增强的逻辑以及时机(before,after等等)。

aspect:pointcut+advice,在@AspectJ风格语法中,就是一个类。下面会示例。

Introduction:spring4后提出来的概念,这里就不说了。

demo示例:

导入依赖:

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.5</version>
</dependency>

AppConfig类,加上@EnableAspectJAutoproxy注解

@EnableAspectJAutoProxy
@ComponentScan("com.sunsas.aspectjdemo")
public class AppConfig {

}

新建一个接口:

package com.sunsas.aspectjdemo.service;

public interface ProxyInterface {
void functionA();
void functionB();
}

新建一个类ProxyClassA实现接口:

package com.sunsas.aspectjdemo.service.impl;

import com.sunsas.aspectjdemo.service.ProxyInterface;
import org.springframework.stereotype.Component;

@Component
public class ProxyClassA implements ProxyInterface {
@Override
public void functionA() {
System.out.println("ProxyClassA functionA");
}

@Override
public void functionB() {
System.out.println("ProxyClassA functionB");
}
}

在别的包下新建一个类ProxyClassB实现接口:

package com.sunsas.other;

import com.sunsas.aspectjdemo.service.ProxyInterface;
import org.springframework.stereotype.Component;

@Component
public class ProxyClassB implements ProxyInterface {
    @Override
    public void functionA() {
        System.out.println("ProxyClassB functionA");
    }

    @Override
    public void functionB() {
        System.out.println("ProxyClassB functionB");
    }
}

声明一个切面:

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.springframework.stereotype.Component;

@Component
@Aspect
public class MyAspect {
    @Pointcut("execution(* com.sunsas.aspectjdemo.service.impl.*.*(..))")
    public void cutA(){
    }
//    @Pointcut("execution(* functionA*(..))")
//    public void cutFunctionA(){
//    }

    @Before("cutA()")
    public void proxyFunctionA(){
        System.out.println("++++++++++++++++++++++++begin");
        System.out.println("before function");
    }
//    @After("cutFunctionA()")
//    public void proxyFunctionB(){
//        System.out.println("after function");
//        System.out.println("--------------------------end");
//    }
}

具体的语法可以去官方文档查看,这里使用:

 表示这个service包下的所有方法都会被横切。

新建测试类Test

package com.sunsas.aspectjdemo;

import com.sunsas.aspectjdemo.service.impl.ProxyClassA;
import com.sunsas.other.ProxyClassB;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext =
                new AnnotationConfigApplicationContext(AppConfig.class);
        ProxyClassA proxyClassA = (ProxyClassA) annotationConfigApplicationContext.getBean("proxyClassA");
        System.out.println(proxyClassA);
        ProxyClassB proxyClassB = annotationConfigApplicationContext.getBean(ProxyClassB.class);
        System.out.println(proxyClassB);
        proxyClassA.functionA();
        proxyClassA.functionB();
        proxyClassB.functionA();
        proxyClassB.functionB();
    }
}

项目结构如图:

 运行结果为:

com.sunsas.aspectjdemo.service.impl.ProxyClassA@6c4980d3
com.sunsas.other.ProxyClassB@38b27cdc
++++++++++++++++++++++++begin
before function
ProxyClassA functionA
++++++++++++++++++++++++begin
before function
ProxyClassA functionB
ProxyClassB functionA
ProxyClassB functionB

可见ProxyClassB的方法没有被代理,因为它不在com.sunsas.aspectjdemo.service.impl下。

但如果把这个@PointCut的impl去掉:

 打印结果:

com.sunsas.aspectjdemo.service.impl.ProxyClassA@1984b1f
com.sunsas.other.ProxyClassB@6d167f58
++++++++++++++++++++++++begin
before function
ProxyClassA functionA
++++++++++++++++++++++++begin
before function
ProxyClassA functionB
++++++++++++++++++++++++begin
before function
ProxyClassB functionA
++++++++++++++++++++++++begin
before function
ProxyClassB functionB

可以看到ProxyClassB的方法也被代理了。

可能是这时候接口也在此包下,所以实现了此接口的类都会被横切。

上面的MyAspect类就是一个切面,里面包括了Point cut(join point)和advice(before,after,around等等)。

原文地址:https://www.cnblogs.com/SunSAS/p/12326088.html