使springAOP生效不一定要加@EnableAspectJAutoProxy註解

在上篇文章《springAOP和AspectJ有關係嗎?如何使用springAOP面向切面編程》中遺留了一個問題,那就是在springboot中使用springAOP需要加@EnableAspectJAutoProxy註解嗎,網上很多都說需要加這個註解,但是有些情況卻是不需要加,就比如我下面的例子,這是爲什麼,難道網上都說錯了嗎?

一、效果演示

以下面的例子演示,

業務類,

UserService.java

package com.my.template.service;

import com.my.template.entity.User;
import org.springframework.stereotype.Service;

/**
 * @date 2022/8/9 15:28
 */
@Service
public class UserService implements Us{
    @Override
    public void saveUser(User user){
        System.out.println("保存user對象到數據庫:"+user);
    }
}

切面類,

LogAspect.java

package com.my.template.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

/**
 * @date 2022/8/11 14:12
 */
@Component
@Aspect
public class LogAspect {
    @Pointcut("execution(* com.my.template.service.UserService.*(..))")
    public void pointCut(){

    }
    @Before(value = "pointCut()")
    public void before(JoinPoint joinPoint){
        System.out.println("方法執行前-20220816");
    }

    @AfterReturning(value = "pointCut()")
    public void after(JoinPoint joinPoint){
        System.out.println("方法執行後-20220816");
    }
}

測試的controller

UserController.java

package com.my.template.controller;

import com.my.template.entity.User;
import com.my.template.service.Us;
import com.my.template.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @date 2022/8/9 15:35
 */
@RestController
public class UserController {
    @Autowired
    private Us us;
    @RequestMapping("/saveUser")
    public String saveUser(){

        User user=new User();
        user.setId("1");
        user.setName("張三");
        us.saveUser(user);
        return "success";
    }
}

sprinboot的啓動類,

BootServer.java

package com.my.template;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.context.annotation.ImportResource;

/**
 * 啓動類
 * @date 2022/6/3 21:32
 */
@SpringBootApplication()
public class BootServer {
    public static void main(String[] args) {
        try {
            SpringApplication.run(BootServer.class);
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

測試結果如下,

2022-08-16 22:30:44.082  INFO 25716 --- [nio-9099-exec-1] o.s.web.servlet.DispatcherServlet        : Completed initialization in 6 ms
方法執行前-20220816
保存user對象到數據庫:User{name='張三', id='1'}
方法執行後-20220816

從上面的測試結果來看,沒有加@EnableAspectJAutoProxy註解,但是AOP生效了,這是爲什麼?

二、爲什麼不加@EnableAspectJAutoProxy切面生效

關於這個問題我排查了很久,最後在依賴中找到了原因,看下pom文件

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>springTemplate</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
    </properties>
    <dependencies>
        <!--spring-boot的web依賴-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>2.3.3.RELEASE</version>
        </dependency>
        <!--自定義的starter-->
        <dependency>
            <groupId>org.example</groupId>
            <artifactId>customer-spring-boot-starter</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <!--使用springAOP需要引入該依賴-->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.8.13</version>
        </dependency>
    </dependencies>
    
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

在依賴中有spring-boot-starter-web的依賴,該依賴有下面的依賴,

會引入spring-boot-autoconfigure的依賴,這是自動裝配的依賴,也就是會讀取其下的spring.factories文件,在該文件中有下面的配置,

沒錯就是因爲AopAutoConfiguration類的問題。下面看具體原因。

三、原因分析

要看具體原因,我們就要打開AopAutoConfiguration這個類看下,

先看註釋吧,註釋中說AopAutoConfiguration等同於@EnableAspectJAutoProxy註解,也就是該類起的作用和@EnableAspectJAutoProxy是一樣的,再看該類上的註解,重點看@ConditionalOProperty註解中的內容,意思是如果在配置文件中有”spring.aop.auto“的配置,如果不配置爲true,否則可以配置爲false,現在我的配置文件中是沒有該配置項的,

server.port=9099
spring.datasource.type=com.mysql.cj.jdbc.MysqlDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource..driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=yh_dev
spring.datasource..password=DvpJe2x
spring.datasource.url=jdbc:mysql://10.0.0.37:3306/channel_center
#?????
my.customer.name=hello
my.customer.code=autoconfiguration

那麼我現在增加該配置,並設置爲false,

server.port=9099
spring.datasource.type=com.mysql.cj.jdbc.MysqlDataSource
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource..driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.username=yh_dev
spring.datasource..password=DvpJe2x
spring.datasource.url=jdbc:mysql://10.0.0.37:3306/channel_center
#?????
my.customer.name=hello
my.customer.code=autoconfiguration
spring.aop.auto=false

重啓服務之後,看測試結果,

從測試結果可以看到springAOP沒有起作用,現在在啓動類上加上@EnableAspectJAutoProxy註解,看下測試結果,

從上面的測試結果可以看到,添加了@EnableAspectJAutoProxy註解springAOP生效了。

綜上,在springboot環境下,由於存在spring-boot-autoconfigure依賴,默認會注入AopAutoConfiguration配置類,該類的作用等同於@EnableAspectJAutoProxy註解,所以在這種情況下可以不加@EnableAspectJAutoProxy註解,AopAutoConfiguration可以通過spring.aop.auto屬性控制;

四、總結

本文主要分析了在springboot環境下,不加@EnableAspectJAutoProxy註解springAOP仍然生效的問題。爲了保險期間請一律加上@EnableAspetJAutoProxy註解。

  1. AopAutoConfiguration類等同於@EnableAspectJAutoProxy註解;
  2. spring.aop.auto=ture/false屬性可以控制AopAutoConfiguration類是否生效;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章