aop实现原理-动态代理CGLib代理
生活随笔
收集整理的這篇文章主要介紹了
aop实现原理-动态代理CGLib代理
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
那接下來的話,那咱們Spring當中,這個AOP,咱們先說概念,咱們先不寫具體代碼,咱們就是聊,聊Spring的AOP,Spring能幫我們干啥呢,我告訴你,Spring他作為對象的容器,Spring作為對象的容器,說白了,他是能夠幫我們,進行對容器中的對象,進行生成代理對象的一個功能,Spring能夠對容器中管理的對象,能夠生成動態代理對象的,能理解啥意思不,你們以前學過動態代理技術,以前咱們寫動態代理對象,咱們得自己寫代碼,剛才我給你寫的代碼Proxy.newProxyInstance,然后里面傳xx參數,以前是咱們自己要調這個方法,以前我們要使用動態代理,我們需要自己調用,下面這個方法,然后呢來生成代理對象,而有了Spring之后,Spring非常體貼,Spring能幫我們生成代理對象,生成這個代理對象,不需要調用這個方法了,只需要拿配置文件配就可以,或者拿注解配就可以,他就自動產生代理對象,知道啥意思不,那他為什么叫AOP,他生成代理對象為什么叫AOP,那道理很簡單,那就是因為我左邊這個圖,你想,那這樣Spring能夠幫我們生成動態代理,那能不能讓Spring幫我Service實現動態代理,然后我告訴Spring,你在生成動態代理的時候,你這個動態代理,給我每一個Service,添加管理事務的代碼,Spring一聽,弄個代理對象,弄出來之后,這樣的話,咱們只需要寫一遍事務代碼,相當于給所有的Service都加上了,這樣的話,AOP思想都體現出來了,所以,AOP這種東西思想,是咱們使用之后,其實你要說SpringAOP的本質,他就是幫我們生成動態代理,能明白啥意思不,所以為什么要使用AOP呢,這個問題太抽象了,明白啥意思不,所以這個Spring,其實SpringAOP就是啥啊,它能夠幫我們生成動態代理對象而已,重點就是這一點,咱們學SpringAOP,學的就是這玩意,讓Spring指揮我們代理對象,而不是,像以前一樣,自己手寫動態代理對象,這就是學習SpringAOP,學習的要點,而你學習會了能讓Spring幫我們代理對象了,是不是你就能夠完成AOP思想來開發了,是不是這么一個關系,所以這就是學習SpringAOP
這就是學習SpringAOP,他這個詞叫的太大了,具體就是Spring能夠動態幫我們創建代理對象,下面就是Spring實現AOP的原理,實現AOP的原理,其實提到了一個,實際上是什么技術呢,動態代理技術,然后呢除了這個以外,還有一個技術,叫做cglib代理技術,這兩種代理技術,分別介紹一下,為什么要選擇兩種代理技術,來幫我們產生代理對象,動態代理你們學過,你們知道,動態代理他在使用的時候有一個局限性,就是必須要有接口,說一下,被代理對象,必須要實現接口,才能產生代理對象,因為剛才這個方法寫出來也看到了,咱們傳的話,第二個參數,是不是接口的數據,這個是不是要你傳被代理對象,要實現的接口,在動態代理的地方當中,如果沒有接口,將不能使用動態代理,那這樣的話你想,如果Spring在給我們生成產生代理的時候,他只封裝了動態代理的技術,那如果我們想要生成代理的對象,沒有接口,是不是做不到啊,于是為了能夠保證每一個對象,都能夠實現動態代理對象,所以又融入了一個第三方代理的技術,cglib代理,這個代理技術,它是可以對任何類生成代理,因為它代理的原理是什么,因為他對目標對象進行繼承代理,比如我要給UserService生成一個動態代理對象,那實際上你生成代理對象,是UserService這個對象的子類,它會把被代理對象進行一個繼承,對他進行一個繼承,那我們還記得hibernate,當中有一個細節不知道你們記不記得,就是hibernate實體有一個要求,就是咱們的實體要求最好使用包裝類型,是類不能被final修飾,其實hibernate在產生代理對象的時候,先不查,先產生代理對象,那個時候就是cglib代理,那你現在理解hibernate,他對要求在類上不能使用final了,明白啥意思不,這不是出來不了嗎,cglib代理,他的代理原理是對目標繼承代理,那如果這個被代理對象,如果他是被final修飾,那就無法被繼承,這樣的話就生成不了代理了,如果目標對象被final修飾,該類無法被cglib代理,那這樣的話,Spring同時整合了兩個代理技術,那有人說Spring到底是使用哪一種代理對象呢,混合的,沒錯,啥叫混合式,他如果有接口,優先使用,如果發現要你代理的這個對象,沒有接口,他就會使用cglib代理,所以這塊的話,Spring他支持了這兩種,然后接下來這樣
使用動態代理和cglib代理,分別完成對類的代理功能,而我們要手動來完成這兩種方式來做代理,咱們做一下準備工作,c_proxy,service包,給后面兩節課做一個例子鋪墊,UserService是咱們的interface,delete,update,然后find,聲明一個UserService接口,接下來再創建一個實現類,UserServiceImpl,實現咱們的UserService接口,然后實現這個四個方法
package com.learn.service;public interface UserService {void save();void delete();void update();void find();
}
這個四個方法的實現全都是非常簡單的實現,咱們寫了UserService的一個實現類了,里面的四個方法,然后接下來呢,要寫的代碼,這里是Service的方法,咱們要對這些方法進行事務管理,如果真正是項目代碼的話,我就打開事務,保存完用戶之后,提交事務,是這個意思不,那我用了四個方法,是不是每個方法都要寫,我用動態代理技術,分別對我們這個實現類進行代理,然后來增強這四個方法,把事務管理代碼,插入到這四塊當中,明白啥意思不,這個就是咱們要寫動態代碼的目的,手動來完成代理,接下里再新建一個包
package com.learn.service;public class UserServiceImpl implements UserService {@Overridepublic void save() {System.out.println("保存用戶!");}@Overridepublic void delete() {System.out.println("刪除用戶!");}@Overridepublic void update() {System.out.println("更新用戶!");}@Overridepublic void find() {System.out.println("查找用戶");}}
就叫proxy,第一個UserServiceProxyFactory,UserService的代理工廠,那這個動態代理的工廠當中,有一個工廠方法,然后返回UserService對象,getUserServiceProxy,然后在這個方法里面,你去調這個方法,返回一個UserService的一個代理對象,然后在這里面生成動態代理返回,那生成動態代理的話,調用Proxy.newInstance,第一個叫類加載器,類加載器學過吧,隨便給個數都可以,第二個參數把接口給他,接口的話就是被代理對象,UserServiceImpl,是不是他,被代理對象,點class點getInterfaces,獲得被代理對象的實現類接口,傳給第二個參數,第三個參數是啥玩意呢,第三個參數很關鍵,第三個參數是咱們指定,代理到底要怎么增強,增強的內容,要求你傳入的接口,InvocationHandler,那這個接口的話,我打算這樣,讓本身這個Factory去實現這個接口,Factory去實現這個,讓本身去實現的話那就好寫了,我本身去實現這個接口的話,是不是用InvocationHandler,這里是不是接收一下,這里是不是就是咱們的UserService,咱們叫usProxy對象,然后強轉成UserService對象,return usProxy,這樣getUserProxy方法就講完了,主要把這個接口實現就完事了,這里面三個參數,分別會把當前的代理對象傳進來,會把當前調用的方法傳進來,方法執行的方法參數傳進來,那以前的方法該調還得調,這是代表你現在執行的業務方法,這個方法你該調還得調,所以這里調用一下invoke方法,這里把方法值傳進去,但是這里知道,咱們的invoke方法,是不是需要方法所在對象的,也來一個實例,這個實例他哪里來呢,這塊的話,產生代理的話,得需要你給我傳進來啊,哪個類執行這個方法,就執行代理,所以你得把這個類給我傳進來,所以我在這里使用構造方法,要他必須把這個us給我傳進來,那咱們就把us作為咱們運行所在的類,這個結果的話,return出去,這個就是業務方法的執行了,是不是在執行之前,咱們不是說要打開事務嗎,然后業務方法執行之后,是不是要提交事務,這樣看我們這個接口實現類就寫完了,這兩行就是咱們要生成的代碼,這一行是原有方法的調用,接下來咱們試一下,咱們動態代理方法的寫完,寫一個Demo測試一下,看他是不是增強了,public void fun1()
這是被代理對象的,創建咱們的factory,factory等于,new一個UserServiceProxyFactory,然后傳進去以后,咱們只需要調用getUserServiceFactory方法,咱們的代理對象叫usProxy,調用usProxy的如何增加方法
package com.learn.c_proxy;import org.junit.Test;import com.learn.service.UserService;
import com.learn.service.UserServiceImpl;public class Demo {@Testpublic void fun1() {UserService us = new UserServiceImpl();UserServiceProxyFactory factory = new UserServiceProxyFactory(us);UserService usProxy = factory.getUserServiceProxy();usProxy.save();}}
打開事務
保存用戶!
提交事務
是不是這個效果,保存用戶之前,之后,你看動態代理是不是這樣演示的,也是這樣演示吧,差不多吧,你要學會怎么去配,不會讓你自己手寫的,這是使用動態代理手動來完成代理對象,來增強咱們的目標方法
?
總結
以上是生活随笔為你收集整理的aop实现原理-动态代理CGLib代理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: aop思想介绍
- 下一篇: 手动使用cglib代理(了解)