最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

解析SpringBoot中使用LoadTimeWeaving技術(shù)實現(xiàn)AOP功能

 更新時間:2022年09月21日 09:18:39   作者:takumiCX  
這篇文章主要介紹了SpringBoot中使用LoadTimeWeaving技術(shù)實現(xiàn)AOP功能,AOP面向切面編程,通過為目標類織入切面的方式,實現(xiàn)對目標類功能的增強,本文給大家介紹的非常詳細,需要的朋友可以參考下

1.SpringBoot AOP功能

1.1 LTW與不同的切面織入時機

AOP——面向切面編程,通過為目標類織入切面的方式,實現(xiàn)對目標類功能的增強。按切面被織如到目標類中的時間劃分,主要有以下幾種:

  • 1.運行期織入

這是最常見的,比如在運行期通過為目標類生成動態(tài)代理的方式實現(xiàn)AOP就屬于運行期織入,這也是Spring AOP中的默認實現(xiàn),并且提供了兩種創(chuàng)建動態(tài)代理的方式:JDK自帶的針對接口的動態(tài)代理和使用CGLib動態(tài)創(chuàng)建子類的方式創(chuàng)建動態(tài)代理。

  • 2.編譯期織入

使用特殊的編譯器在編譯期將切面織入目標類,這種比較少見,因為需要特殊的編譯器的支持。

  • 3.類加載期織入

通過字節(jié)碼編輯技術(shù)在類加載期將切面織入目標類中,這是本篇介紹的重點。它的核心思想是:在目標類的class文件被JVM加載前,通過自定義類加載器或者類文件轉(zhuǎn)換器將橫切邏輯織入到目標類的class文件中,然后將修改后class文件交給JVM加載。這種織入方式可以簡稱為LTW(LoadTimeWeaving)。

1.2 JDK實現(xiàn)LTW的原理

可以使用JKD的代理功能讓代理器訪問到JVM的底層組件,借此向JVM注冊類文件轉(zhuǎn)換器,在類加載時對類文件的字節(jié)碼進行轉(zhuǎn)換。具體而言,java.lang.instrument包下定義了ClassFileTransformer接口,該接口的作用如下面的注釋所描述

* An agent provides an implementation of this interface in order
* to transform class files.
* The transformation occurs before the class is defined by the JVM.

可以通過實現(xiàn)該接口,并重寫如下抽象方法自定義類文件轉(zhuǎn)換規(guī)則

byte[]
transform(  ClassLoader         loader,
            String              className,
            Class<?>            classBeingRedefined,
            ProtectionDomain    protectionDomain,
            byte[]              classfileBuffer)
    throws IllegalClassFormatException;

classfileBuffer是原始類文件對應(yīng)的字節(jié)碼數(shù)組,返回的byte[]為轉(zhuǎn)化后的字節(jié)碼數(shù)組,如果返回null,則表示不進行字節(jié)碼處理。

而java.lang.instrument包下的Instrumentation接口則可以將我們自定義的ClassTransFormer向JVM內(nèi)部的組件進行注冊

void
addTransformer(ClassFileTransformer transformer);

在實際使用中,可以通過JVM的-javaagent代理參數(shù)在啟動時獲取JVM內(nèi)部組件的引用,將ClassFileTransformer實例注冊到JVM中,JVM在加載Class文件時,會先調(diào)用這個ClassTransformer的transform()方法對Class文件的字節(jié)碼進行轉(zhuǎn)換,比如織入切面中定義的橫切邏輯,實現(xiàn)AOP功能。整個過程可以入下所示

1.3 如何在Spring中實現(xiàn)LTW

Spring中默認通過運行期生成動態(tài)代理的方式實現(xiàn)切面的織入,實現(xiàn)AOP功能,但是Spring也可以使用LTW技術(shù)來實現(xiàn)AOP,并且提供了細粒度的控制,支持在單個ClassLoader范圍內(nèi)實施類文件轉(zhuǎn)換。

Spring中的org.springframework.instrument.classloading.LoadTimeWeaver接口定義了為類加載器添加ClassFileTransfomer的抽象

* Defines the contract for adding one or more
* {@link ClassFileTransformer ClassFileTransformers} to a {@link ClassLoader}.
*
public interface LoadTimeWeaver {

Spring的LTW支持AspectJ定義的切面,既可以是直接使用AspectJ語法定義的切面,也可以是使用@AspectJ注解,通過java類定義的切面。Spring LTW通過讀取classpath下META-INF/aop.xml文件,獲取切面類和要被切面織入的目標類的相關(guān)信息,通過LoadTimeWeaver在ClassLoader加載類文件時將切面織入目標類中,其工作原理如下所示

Spring中可以通過LoadTimeWeaver將Spring提供的ClassFileTransformer注冊到ClassLoader中。在類加載期,注冊的ClassFileTransformer讀取類路徑下META-INF/aop.xml文件中定義的切面類和目標類信息,在目標類的class文件真正被VM加載前織入切面信息,生成新的Class文件字節(jié)碼,然后交給VM加載。因而之后創(chuàng)建的目標類的實例,就已經(jīng)實現(xiàn)了AOP功能。

2. Springboot中使用LTW實現(xiàn)AOP的例子

實現(xiàn)一個簡單的AOP需求,在方法調(diào)用前后打印出開始和結(jié)束的日志信息。

相關(guān)的maven依賴和插件

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-aop</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <configuration>
                <argLine>
                    -javaagent:"${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar"
                    -javaagent:"${settings.localRepository}/org/springframework/spring-instrument/${spring.version}/spring-instrument-${spring.version}.jar"
                    <!-- -Dspring.profiles.active=test-->
                </argLine>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
            <configuration>
                <agent>
                    ${settings.localRepository}/org/aspectj/aspectjweaver/${aspectj.version}/aspectjweaver-${aspectj.version}.jar
                </agent>
                <agent>
                    ${settings.localRepository}/org/springframework/spring-instrument/${spring.version}/spring-instrument-${spring.version}.jar
                </agent>
            </configuration>
        </plugin>
    </plugins>

</build>

這里通過maven插件的方式為JVM設(shè)置代理,通過-javaagent參數(shù)指定織入器類包的路徑,這樣就可以在類加載期將切面織入,更多關(guān)于javaagent的知識可以參考javaagent

織入目標類

/**
 * @author: takumiCX
 * @create: 2018-12-19
 **/
@Component
public class LtwBean {
    public void test(){
        System.out.println("process.......");
    }
}

只有一個test()方法,通過@Componet注解向容器注冊。

切面類

/**
 * @author: takumiCX
 * @create: 2018-12-19
 **/
@Aspect
public class LogMethodInvokeAspect {

    @Pointcut("execution(public * com.takumiCX.ltw.*.*(..))")
    public void pointCut(){

    }
    @Around("pointCut()")
    public void advise(ProceedingJoinPoint pjp) throws Throwable {


        Signature signature = pjp.getSignature();
        System.out.println(signature+" start..... ");
        pjp.proceed();
        System.out.println(signature+" end......");
    }
}

@Aspect注解表示這是一個切面類

配置類

/**
 * @author: takumiCX
 * @create: 2018-12-19
 **/
@Configuration
@ComponentScan("com.takumiCX.ltw")
@EnableLoadTimeWeaving(aspectjWeaving=AUTODETECT)
public class CustomLtwConfig{
}

通過@@EnableLoadTimeWeaving開啟LTW功能,可以通過屬性aspectjWeaving指定LTW的開啟策略

  1. ENABLED

開啟LTW

  1. DISABLED

不開啟LTW

  • AUTODETECT

如果類路徑下能讀取到META-INF/aop.xml文件,則開啟LTW,否則關(guān)閉

  • 在META-INF文件夾下編寫aop.xml文件

aop.xml文件內(nèi)容

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE aspectj PUBLIC "-//AspectJ//DTD//EN" "http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>

    <!--要織入切面的目標類-->
    <weaver>
        <include within="com.takumiCX.ltw..*" />
    </weaver>
    <!--切面類-->
    <aspects>
        <aspect name="com.takumiCX.ltw.aspect.LogMethodInvokeAspect" />
    </aspects>
</aspectj>

這樣我們的Spring容器就能加載該文件讀取到描述目標類和切面類的相關(guān)信息,容器在加載目標類的class文件到j(luò)vm之前,會將切面類中定義的增強邏輯織入到class文件中,真正加載到j(luò)vm中的是織入切面后的class文件,因而通過該class文件創(chuàng)建出的目標類的實例,不需要經(jīng)過動態(tài)代理就能實現(xiàn)AOP相關(guān)功能。

測試類

/**
 * @author: takumiCX
 * @create: 2018-12-20
 **/
@RunWith(SpringRunner.class)
@SpringBootTest(classes ={CustomLtwConfig.class})
public class LTWTest {
    @Autowired
    private LtwBean ltwBean;
    @Test
    public void testLTW() throws InterruptedException {

        ltwBean.test();

    }
}

最后的結(jié)果如下

方法調(diào)用前后分別記錄的開始和結(jié)束的日志信息,說明我們的切面成功的織入到了目標類。但是這里可能有一個疑問,這真的是LTW(Load TimeWeaving)通過在類加載期織入切面起到的作用嗎?有沒有可能是LTW沒起作用,是Spring AOP默認通過運行期生成動態(tài)代理的方式實現(xiàn)的AOP。
我們的LogMethodInvokeAspect切面類上并沒有加@Component注解向容器注冊,并且配置類CustomLtwConfig上也沒有加@EnableAspectJAutoProxy注解開啟Aspectj的運行時動態(tài)代理,所以這里基于動態(tài)代理的AOP并不會生效。

為了驗證我們的想法,將aop.xml文件刪除

重新運行測試代碼

AOP沒起到作用,說明剛才的AOP功能確實是通過LTW技術(shù)實現(xiàn)的。

當我們給切面類加上@Component注解,給配置類加上@EnableAspectJAutoProxy

/**
 * @author: takumiCX
 * @create: 2018-12-19
 **/
@Aspect
@Component
public class LogMethodInvokeAspect {
/**
 * @author: takumiCX
 * @create: 2018-12-19
 **/
@Configuration
@ComponentScan("com.takumiCX.ltw")
@EnableAspectJAutoProxy
@EnableLoadTimeWeaving(aspectjWeaving=AUTODETECT)
public class CustomLtwConfig{
}

再次運行測試類時,發(fā)現(xiàn)AOP又生效了,這時候類路徑下并沒有aop.xml,所以這時候AOP是Spring在運行期通過動態(tài)代理的方式實現(xiàn)的。

3. 參考資料

《精通Spring4.x企業(yè)應(yīng)用開發(fā)實戰(zhàn)》
《spring揭秘》
https://sexycoding.iteye.com/blog/1062372

到此這篇關(guān)于SpringBoot中使用LoadTimeWeaving技術(shù)實現(xiàn)AOP功能的文章就介紹到這了,更多相關(guān)SpringBoot AOP功能內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • springcloud-feign調(diào)用報錯問題

    springcloud-feign調(diào)用報錯問題

    這篇文章主要介紹了springcloud-feign調(diào)用報錯問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-08-08
  • SpringBoot使用異步線程池實現(xiàn)生產(chǎn)環(huán)境批量數(shù)據(jù)推送

    SpringBoot使用異步線程池實現(xiàn)生產(chǎn)環(huán)境批量數(shù)據(jù)推送

    本文主要介紹了SpringBoot使用異步線程池實現(xiàn)生產(chǎn)環(huán)境批量數(shù)據(jù)推送,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-02-02
  • 基于Java類的加載方式

    基于Java類的加載方式

    這篇文章主要介紹了基于Java類的加載方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • ScrollView中嵌入ListView只顯示一條的解決辦法

    ScrollView中嵌入ListView只顯示一條的解決辦法

    在ScrollView添加一個ListView會導(dǎo)致listview控件顯示不全,通常只會顯示一條,究竟是什么原因呢?下面腳本之家小編給大家介紹ScrollView中嵌入ListView只顯示一條的解決辦法,感興趣的朋友一起學(xué)習(xí)吧
    2016-05-05
  • Mybatis分頁查詢主從表的實現(xiàn)示例

    Mybatis分頁查詢主從表的實現(xiàn)示例

    本文主要介紹了Mybatis分頁查詢主從表的實現(xiàn)示例,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-09-09
  • Java字符串逆序方法詳情

    Java字符串逆序方法詳情

    這篇文章主要介紹了Java字符逆序,字符逆序主要原理就是將一個字符串str的內(nèi)容顛倒過來,并輸出,下文操作分享需要的小伙伴可以參考一下
    2022-03-03
  • idea配置多環(huán)境啟動方式dev、test、prod

    idea配置多環(huán)境啟動方式dev、test、prod

    這篇文章主要介紹了idea配置多環(huán)境啟動方式dev、test、prod,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • SpringBoot詳細講解yaml配置文件的用法

    SpringBoot詳細講解yaml配置文件的用法

    這篇文章主要介紹了SpringBoot中的yaml配置文件問題,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-06-06
  • 使用ResponseEntity處理API返回問題

    使用ResponseEntity處理API返回問題

    這篇文章主要介紹了使用ResponseEntity處理API返回問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • Java獲取月份的三種方法總結(jié)

    Java獲取月份的三種方法總結(jié)

    這篇文章主要給大家介紹了關(guān)于Java獲取月份的三種方法,文中分別介紹了使用java.util.Date、java.util.Calendar和java.time包中的LocalDate類,推薦使用java.time包中的LocalDate,因為它提供了更為簡潔和強大的功能,需要的朋友可以參考下
    2024-12-12

最新評論

广汉市| 苏尼特左旗| 建水县| 大渡口区| 抚州市| 山西省| 鄂伦春自治旗| 峨眉山市| 佛坪县| 五华县| 凤冈县| 溧水县| 宕昌县| 濉溪县| 池州市| 柏乡县| 塘沽区| 丰县| 景泰县| 元阳县| 清水县| 郧西县| 团风县| 漠河县| 大竹县| 苍溪县| 隆尧县| 隆子县| 瓮安县| 丹巴县| 门源| 北安市| 綦江县| 集安市| 双城市| 静海县| 昂仁县| 从化市| 长子县| 开化县| 克拉玛依市|