1. AOP概念  

AOP(Aspect-Oriented Programming,面向切面编程),简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或业务封装起来,再把封装功能整合到业务中。好处:便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。

AOP的核心思想就是“将应用程序中的业务逻辑同对其提供支持的通用服务进行分离"

例如:将日志记录,性能统计,安全控制,事务处理,异常处理等代码从业务逻辑代码中划分出来,通过对这些行为的分离,我们希望可以将它们独立到非指导业务逻辑的方法中,进而改变这些行为的时候不影响业务逻辑的代码。

2.AOP实现准备

(1),首先在IOC的基础上添加依赖

<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <spring.version>5.3.12</spring.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.4</version>
        </dependency>
    </dependencies>

(2),编写服务接口和服务类

服务接口:

public interface UserService {
    /**
     * 模拟添加
     */
    void add();
    /**
     * 模拟删除
     */
    void delete();
    /**
     * 模拟更新
     */
    void update();
    /**
     * 模拟查询
     */
    void query();
}

服务类:

public class UserServiceImpl implements UserService {

    @Override
    public void add() {

        System.out.println("模拟添加");
    }

    @Override
    public void delete() {

        System.out.println("模拟删除");
    }

    @Override
    public void update() {

        System.out.println("模拟更新");
    }

    @Override
    public void query() {

        System.out.println("模拟查询");
    }
}

3.AOP的实现

(1),方式一:使用原生spring API接口

编写增强类

public class MethodLog implements MethodBeforeAdvice {
    //method:要执行目标对象方法
    //objects:参数
    //o:目标对象
    @Override
    public void before(Method method, Object[] objects, Object o) throws Throwable {
        System.out.println(o.getClass().getName()+"的"+method.getName()+"被执行了");
    }
}

在配置文件spring-aop.xml中配置:

<!--注册bean-->
    <bean id="userService" class="com.li.service.impl.UserServiceImpl"/>
    <bean id="methodLog" class="com.li.log.MethodLog"/>
    
    <!--方式一:使用原生spring API接口-->
    <!--配置aop:需要导入aop的约束-->
    <aop:config>

        <!--切入点:expression:表达式,expression(要执行的位置)-->
        <aop:pointcut id="pointcut" expression="execution(* com.li.service.impl.UserServiceImpl.add*(..))"/>

        <!--执行环绕-->
        <aop:advisor advice-ref="methodLog" pointcut-ref="pointcut"/>
    </aop:config>

编写测试类:

public class AOPTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
        //动态代理代理的是接口
        UserService userService = (UserService) context.getBean("userService");
        userService.delete();
        userService.update();
        userService.add();
        userService.query();
    }

}

测试结果:

spring aop实现原理详解 spring aop的实现方式_spring

 (2),方式二:自定义类

编写增强类:

public class DivPointCut {
    public void befor(){
        System.out.println("============方法执行前============");
    }

    public void after(){
        System.out.println("============方法执行后============");
    }
}

在配置文件spring-aop.xml中配置:

<!--注册bean-->
    <bean id="userService" class="com.li.service.impl.UserServiceImpl"/>

    <!--方式二:自定义-->
    <bean id="div" class="com.li.div.DivPointCut"/>
    <aop:config>
        <aop:aspect ref="div">
            <!--切入点-->
            <aop:pointcut id="point" expression="execution(* com.li.service.impl.UserServiceImpl.add*(..))"/>
            <!--通知-->
            <aop:before method="befor" pointcut-ref="point"/>
            <aop:after method="after" pointcut-ref="point"/>
        </aop:aspect>
    </aop:config>

编写测试类:(测试类不变)

public class AOPTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
        //动态代理代理的是接口
        UserService userService = (UserService) context.getBean("userService");
        userService.delete();
        userService.update();
        userService.add();
        userService.query();
    }

}

测试结果:

spring aop实现原理详解 spring aop的实现方式_spring aop实现原理详解_02

 (3),方式三:采用注解

编写增强类:

@Aspect //生成代理对象
@Component
public class Log {
    //后置通知
    @AfterReturning(pointcut = "execution(* com.li.service.impl.UserServiceImpl.add(..))")
    public void add(){
        System.out.println("==========模拟日志添加==========");
    }

    //前置通知
    @Before("execution(* com.li.service.impl.UserServiceImpl.delete(..))")
    public void before(){
        System.out.println("==========模拟日志删除==========");
    }
}

在配置文件spring-aop.xml中配置:

<!--开启注解扫描-->
    <context:component-scan base-package="com.li"/>
    <!--开启Aspect生成代理对象-->
    <aop:aspectj-autoproxy proxy-target-class="true"/>

注意:要在业务类上加上一个@Component注解,否则会有可能扫描不到

spring aop实现原理详解 spring aop的实现方式_spring aop实现原理详解_03

 编写测试类:

public class AOPTest {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("spring-aop.xml");
        
        //动态代理代理的是接口扫描userServiceImpl
        UserService userService = (UserService) context.getBean("userServiceImpl");
        userService.delete();
        userService.update();
        userService.add();
        userService.query();
    }

}

测试结果:

spring aop实现原理详解 spring aop的实现方式_java_04