国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

寧波網(wǎng)站建設(shè)免費(fèi)咨詢(xún)漯河網(wǎng)絡(luò)推廣哪家好

寧波網(wǎng)站建設(shè)免費(fèi)咨詢(xún),漯河網(wǎng)絡(luò)推廣哪家好,貴陽(yáng)做網(wǎng)站設(shè)計(jì),太倉(cāng)有做網(wǎng)站的地方嗎?作者簡(jiǎn)介:大家好,我是Leo,熱愛(ài)Java后端開(kāi)發(fā)者,一個(gè)想要與大家共同進(jìn)步的男人😉😉 🍎個(gè)人主頁(yè):Leo的博客 💞當(dāng)前專(zhuān)欄: Spring專(zhuān)欄 ?特色專(zhuān)欄: M…

Springgif.gif

?作者簡(jiǎn)介:大家好,我是Leo,熱愛(ài)Java后端開(kāi)發(fā)者,一個(gè)想要與大家共同進(jìn)步的男人😉😉
🍎個(gè)人主頁(yè):Leo的博客
💞當(dāng)前專(zhuān)欄: Spring專(zhuān)欄
?特色專(zhuān)欄: MySQL學(xué)習(xí)
🥭本文內(nèi)容:Spring5學(xué)習(xí)筆記—AOP編程
🖥?個(gè)人小站 :個(gè)人博客,歡迎大家訪問(wèn)
📚個(gè)人知識(shí)庫(kù): 知識(shí)庫(kù),歡迎大家訪問(wèn)

1. 靜態(tài)代理設(shè)計(jì)模式

1.1 為什么需要代理設(shè)計(jì)模式

  • 在JavaEE分層開(kāi)發(fā)開(kāi)發(fā)中,那個(gè)層次對(duì)于我們來(lái)講最重要

    DAO ---> Service --> Controller JavaEE分層開(kāi)發(fā)中,最為重要的是Service層
    
  • Service層中包含了哪些代碼?

    Service層中 = 核心功能(幾十行 上百代碼) + 額外功能(附加功能)
    1. 核心功能業(yè)務(wù)運(yùn)算DAO調(diào)用
    2. 額外功能(事務(wù)、日志、性能...)1. 不屬于業(yè)務(wù)2. 可有可無(wú)3. 代碼量很小 
    
  • 額外功能書(shū)寫(xiě)在Service層中好不好?

    Controller層(Service層的調(diào)用者)除了需要核心功能,還需要這些額外功能。

    但是從軟件設(shè)計(jì)者角度看:Service層最好不要寫(xiě)額外功能。

  • 現(xiàn)實(shí)生活中的解決方式

    image-20230815111510825

代理模式是一種比較好理解的設(shè)計(jì)模式。簡(jiǎn)單來(lái)說(shuō)就是 我們使用代理對(duì)象來(lái)代替對(duì)真實(shí)對(duì)象(real object)的訪問(wèn),這樣就可以在不修改原目標(biāo)對(duì)象的前提下,提供額外的功能操作,擴(kuò)展目標(biāo)對(duì)象的功能。

代理模式的主要作用是擴(kuò)展目標(biāo)對(duì)象的功能,比如說(shuō)在目標(biāo)對(duì)象的某個(gè)方法執(zhí)行前后你可以增加一些自定義的操作。

代理模式: 為一個(gè)對(duì)象提供一個(gè)替身,以控制對(duì)這個(gè)對(duì)象的訪問(wèn)。即通過(guò)代理對(duì)象訪問(wèn)目標(biāo)對(duì)象.這樣做的好處是:可以在目標(biāo)對(duì)象實(shí)現(xiàn)的基礎(chǔ)上,增強(qiáng)額外的功能操作,即擴(kuò)展目標(biāo)對(duì)象的功能。

被代理的對(duì)象可以是遠(yuǎn)程對(duì)象、創(chuàng)建開(kāi)銷(xiāo)大的對(duì)象或需要安全控制的對(duì)象

舉個(gè)例子:當(dāng)我們工作之后需要出去租房子,房東張貼廣告帶我看房子,最后簽合同,但是房東只想坐著簽合同并不想到處跑著看房子,于是就找了一個(gè)中介專(zhuān)門(mén)來(lái)宣傳廣告并且?guī)ё鈶?hù)看房子,而房東只負(fù)責(zé)簽合同收錢(qián)!中介在這里就可以看作是代理你的代理對(duì)象代理的行為(方法)是帶租戶(hù)看房子。

img

1.2 代理設(shè)計(jì)模式分析

2.1 概念

通過(guò)代理類(lèi),為原始類(lèi)(目標(biāo))增加額外的功能 好處:利于原始類(lèi)(目標(biāo))的維護(hù)

2.2 名詞解釋

1. 目標(biāo)類(lèi) 原始類(lèi) 指的是 業(yè)務(wù)類(lèi) (核心功能 --> 業(yè)務(wù)運(yùn)算 DAO調(diào)用)
2. 目標(biāo)方法,原始方法目標(biāo)類(lèi)(原始類(lèi))中的方法 就是目標(biāo)方法(原始方法)
3. 額外功能 (附加功能)日志,事務(wù),性能

2.3 代理開(kāi)發(fā)的核心要素

代理類(lèi) = 實(shí)現(xiàn)和目標(biāo)類(lèi)相同的接口 + 在同名方法中添加額外功能 + 調(diào)用原始類(lèi)同名方法房東 ---> public interface UserService{m1m2}UserServiceImpl implements UserService{m1 ---> 業(yè)務(wù)運(yùn)算 DAO調(diào)用m2 }UserServiceProxy implements UserServicem1m2

2.4 編碼

靜態(tài)代理:為每一個(gè)原始類(lèi),手動(dòng)編寫(xiě)一個(gè)代理類(lèi) (.java .class)

image-20230815112248257

2.5 靜態(tài)代理存在的問(wèn)題

1. 靜態(tài)類(lèi)文件數(shù)量過(guò)多,不利于項(xiàng)目管理UserServiceImpl  UserServiceProxyOrderServiceImpl OrderServiceProxy
2. 額外功能維護(hù)性差代理類(lèi)中 額外功能修改復(fù)雜(麻煩)

2. Spring的動(dòng)態(tài)代理開(kāi)發(fā)

2.1 Spring動(dòng)態(tài)代理的概念

概念:通過(guò)代理類(lèi)為原始類(lèi)(目標(biāo)類(lèi))增加額外功能,代理類(lèi)由Spring動(dòng)態(tài)生成。
好處:利于原始類(lèi)(目標(biāo)類(lèi))的維護(hù)

2.2 搭建開(kāi)發(fā)環(huán)境

<dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.1.14.RELEASE</version>
</dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjrt</artifactId><version>1.8.8</version>
</dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.8.3</version>
</dependency>

2.3 Spring動(dòng)態(tài)代理的開(kāi)發(fā)步驟

1. 創(chuàng)建原始對(duì)象(目標(biāo)對(duì)象)

public class UserServiceImpl implements UserService{@Overridepublic void register(User user) {System.out.println("UserServiceImpl.register");}@Overridepublic boolean login(String name, String password) {System.out.println("UserServiceImpl.login");return true;}
}
<bean id="userServiceImpl" class="com.Leo.dynamic.service.impl.UserServiceImpl"/>

2. 定義額外功能

實(shí)現(xiàn)MethodBeforeAdvice接口

public class Before implements MethodBeforeAdvice {//作用:給原始方法添加額外功能//注意:會(huì)在原始方法運(yùn)行之前運(yùn)行此方法@Overridepublic void before(Method method, Object[] args, Object target) throws Throwable {System.out.println("-----method before advice log------");}
}
<bean id="before" class="com.Leo.dynamic.service.Before"/>

3. 定義切入點(diǎn)

1. 切入點(diǎn):額外功能加入的位置2. 目的:由程序員根據(jù)自己的需要,決定額外功能加入給那個(gè)原始方法
register()
login()簡(jiǎn)單的測(cè)試:所有方法都做為切入點(diǎn),都加入額外的功能。
<aop:config><aop:pointcut id="pc" expression="execution(* *(..))"/>
</aop:config>

4. 組裝

<!-- 組裝切入點(diǎn)與額外功能 -->
<aop:advisor advice-ref="before" pointcut-ref="pc"/>

5. 測(cè)試調(diào)用

目的:獲得Spring工廠創(chuàng)建的動(dòng)態(tài)代理對(duì)象,并進(jìn)行調(diào)用
ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
注意:1. Spring的工廠通過(guò)	原始對(duì)象的id值獲得的是代理對(duì)象2. 獲得代理對(duì)象后,可以通過(guò)聲明接口類(lèi)型,進(jìn)行對(duì)象的存儲(chǔ)UserService userService=(UserService)ctx.getBean("userServiceImpl");userService.login("","");
userService.register(new User());

控制臺(tái)打印: 可以發(fā)現(xiàn)在日志之前輸入了

image-20230815114453445

2.4 動(dòng)態(tài)代理細(xì)節(jié)分析

4.1 Spring創(chuàng)建的動(dòng)態(tài)代理類(lèi)在哪里?

Spring框架在運(yùn)行時(shí),通過(guò)動(dòng)態(tài)字節(jié)碼技術(shù),在JVM創(chuàng)建的,運(yùn)行在JVM內(nèi)部,等程序結(jié)束后就消失了。

什么叫動(dòng)態(tài)字節(jié)碼技術(shù):通過(guò)第三方動(dòng)態(tài)字節(jié)碼框架,在JVM中創(chuàng)建對(duì)應(yīng)類(lèi)的字節(jié)碼,進(jìn)而創(chuàng)建對(duì)象,當(dāng)虛擬機(jī)結(jié)束,動(dòng)態(tài)字節(jié)碼跟著消失。

結(jié)論:動(dòng)態(tài)代理不需要定義類(lèi)文件,都是JVM運(yùn)行過(guò)程中動(dòng)態(tài)創(chuàng)建的,所以不會(huì)造成靜態(tài)代理,類(lèi)文件數(shù)量過(guò)多,影響項(xiàng)目管理的問(wèn)題。

image-20200423165547079

4.2 動(dòng)態(tài)代理編程簡(jiǎn)化代理的開(kāi)發(fā)

在額外功能不改變的前提下,創(chuàng)建其他目標(biāo)類(lèi)(原始類(lèi))的代理對(duì)象時(shí),只需要指定原始(目標(biāo))對(duì)象即可。

3. Spring動(dòng)態(tài)代理詳解

3.1 額外功能的詳解

  • MethodBeforeAdvice分析

    作用:原始方法執(zhí)行之前,運(yùn)行額外功能。

    public class Before implements MethodBeforeAdvice {/*** 作用:給原始方法添加額外功能* 注意:會(huì)在原始方法運(yùn)行之前運(yùn)行此方法* @param method 原始方法 login() register() ...* @param objects 原始方法的參數(shù)列表 name password ...* @param o 原始對(duì)象 UserServiceImpl OrderServiceImpl* @throws Throwable 拋出的異常*/@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("---- MethodBeforeAdvice  log... ----");}
    }
    

實(shí)戰(zhàn):需要時(shí)才用,可能都會(huì)用到,也有可能都不用。

  • MethodInterceptor(方法攔截器)

    MethodInterceptor接口:額外功能可定義在原始方法執(zhí)行 前、后、前和后。

    public class Around implements MethodInterceptor {/*** @param invocation 封裝了原始方法 invocation.proceed()表示原始方法的運(yùn)行* @return 原始方法的返回值* @throws Throwable 可能拋出的異常*/@Overridepublic Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("------ 額外功能 log -----");//原始方法的執(zhí)行Object ret = invocation.proceed();//返回原始方法的返回值return ret;}
    }
    

額外功能運(yùn)行在原始方法執(zhí)行之后

  public Object invoke(MethodInvocation invocation) throws Throwable {Object ret = invocation.proceed();System.out.println("-----額外功能運(yùn)行在原始方法執(zhí)行之后----");return ret;}

額外功能運(yùn)行在原始方法執(zhí)行之前和之后(實(shí)戰(zhàn):事務(wù)需要在之前和之后都運(yùn)行)

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("-----額外功能運(yùn)行在原始方法執(zhí)行之前----");Object ret = invocation.proceed();System.out.println("-----額外功能運(yùn)行在原始方法執(zhí)行之后----");return ret;
}

額外功能運(yùn)行在原始方法拋出異常時(shí)

  @Override
public Object invoke(MethodInvocation invocation) throws Throwable {Object ret = null;try {ret = invocation.proceed();} catch (Throwable throwable) {System.out.println("-----原始方法拋出異常 執(zhí)行的額外功能 ---- ");throwable.printStackTrace();}return ret;}

MethodInterceptor可以影響原始方法的返回值

@Override
public Object invoke(MethodInvocation invocation) throws Throwable {System.out.println("------log-----");Object ret = invocation.proceed();//拿到原始方法的返回值后進(jìn)行一些操作就會(huì)影響,直接返回就不影響return false;
}

3.2 切入點(diǎn)詳解

切入點(diǎn)決定了額外功能加入的位置。

<aop:pointcut id="pc" expression="execution(* *(..))"/>
exection(* *(..)) ---> 匹配了所有方法    a  b  c 1. execution()  切入點(diǎn)函數(shù)
2. * *(..)      切入點(diǎn)表達(dá)式 

1. 切入點(diǎn)表達(dá)式

  • 方法切入點(diǎn)表達(dá)式:

    image-20200425105040237

    *  *(..)  --> 所有方法* ---> 修飾符 返回值
    * ---> 方法名
    ()---> 參數(shù)表
    ..---> 對(duì)于參數(shù)沒(méi)有要求 (0個(gè)或多個(gè))
    

舉例:

  # 定義login方法作為切入點(diǎn)* login(..)# 定義register作為切入點(diǎn)* register(..)# 定義名字為login且有兩個(gè)字符串類(lèi)型參數(shù)的方法 作為切入點(diǎn)* login(String,String)# 注意:非java.lang包中的類(lèi)型,必須要寫(xiě)全限定名* register(com.Leo.proxy.User)# ..可以和具體的參數(shù)類(lèi)型連用(至少有一個(gè)參數(shù)是String類(lèi)型)* login(String,..)# 精準(zhǔn)方法切入點(diǎn)限定# 修飾符 返回值    包.類(lèi).方法(參數(shù))*             com.yuziayn.proxy.UserServiceImpl.login(..)*             com.Leo.proxy.UserServiceImpl.login(String,String)
  • 類(lèi)切入點(diǎn)表達(dá)式:

    指定特定的類(lèi)作為切入點(diǎn),即這個(gè)類(lèi)中所有的方法都會(huì)加上額外功能。

    舉例:

    # 類(lèi)中的所有方法都加入額外功能 
    * com.Leo.proxy.UserServiceImpl.*(..)# 忽略包
    # 1. 類(lèi)只在一級(jí)包下  com.UserServiceImpl
    * *.UserServiceImpl.*(..)# 2. 類(lèi)可在多級(jí)包下  com.Leo.proxy.UserServiceImpl
    * *..UserServiceImpl.*(..)
    
  • 包切入點(diǎn)表達(dá)式:

    指定包作為切入點(diǎn),即這個(gè)包中的所有類(lèi)及其方法都會(huì)加入額外的功能。

    舉例:

    # proxy包作為切入點(diǎn),即proxy包下所有類(lèi)中的所有方法都會(huì)加入額外功能,但是不包括其子包中的類(lèi)!
    * com.Leo.proxy.*.*(..)# 當(dāng)前包及其子包都生效
    * com.Leo.proxy..*.*(..) 
    

2 切入點(diǎn)函數(shù)

作用:用于執(zhí)行切入點(diǎn)表達(dá)式。

  1. execution()

    最為重要的切入點(diǎn)函數(shù),功能最全!
    用于執(zhí)行:方法切入點(diǎn)表達(dá)式、類(lèi)切入點(diǎn)表達(dá)式、包切入點(diǎn)表達(dá)式 弊端:execution執(zhí)行切入點(diǎn)表達(dá)式 ,書(shū)寫(xiě)麻煩execution(* com.Leo.proxy..*.*(..))注意:其他的切入點(diǎn)函數(shù) 只是簡(jiǎn)化execution書(shū)寫(xiě)復(fù)雜度,功能上完全一致
    
  2. args()

    # 作用:用于函數(shù)(方法)參數(shù)的匹配# 舉例:方法參數(shù)必須得是2個(gè)字符串類(lèi)型的參數(shù)execution(* *(String,String))等價(jià)于:args(String,String)
    
  3. within()

    # 作用:用于進(jìn)行類(lèi)、包切入點(diǎn)表達(dá)式的匹配
    # 舉例:
    # UserServiceImpl類(lèi)作為切入點(diǎn):execution(* *..UserServiceImpl.*(..))within(*..UserServiceImpl)
    # proxy包作為切入點(diǎn):execution(* com.Leo.proxy..*.*(..))within(com.yuziayan.proxy..*)
    
  4. @annotation()

    <!-- 作用:為具有特殊注解的方法加入額外功能 --><aop:pointcut id="" expression="@annotation(com.baizhiedu.Log)"/>
    
  5. 切入點(diǎn)函數(shù)間的邏輯運(yùn)算:

    目的:整合多個(gè)切入點(diǎn)函數(shù)一起配合工作,進(jìn)而完成更為復(fù)雜的需求。

    • and 與操作(同時(shí)滿(mǎn)足)

      # 案例:方法名為login,同時(shí)有2個(gè)字符串類(lèi)型的參數(shù):execution(* login(String,String))execution(* login(..)) and args(String,String)# 注意:與操作不能用于同種類(lèi)型的切入點(diǎn)函數(shù) 
      # 錯(cuò)誤案例:register方法 和 login方法作為切入點(diǎn)(不能用and,而用or!)execution(* login(..)) and execution(* register(..))
      # 上面的語(yǔ)句會(huì)發(fā)生錯(cuò)誤,因?yàn)槠鋵?shí)際表達(dá)的含義是方法名為login同時(shí)方法名為register,顯然有悖邏輯,此時(shí)應(yīng)該用到的是 or
      
  • or 或操作(滿(mǎn)足一種即可)

       # 案例:register方法 和 login方法作為切入點(diǎn) execution(* login(..)) or  execution(* register(..))
    

4. AOP編程

4.1 AOP概念

# AOP (Aspect Oriented Programing)   面向切面編程 = Spring動(dòng)態(tài)代理開(kāi)發(fā)
# 以切面為基本單位的程序開(kāi)發(fā),通過(guò)切面間的彼此協(xié)同,相互調(diào)用,完成程序的構(gòu)建
# 切面 = 切入點(diǎn) + 額外功能# OOP (Object Oriented Programing)   面向?qū)ο缶幊?Java
# 以對(duì)象為基本單位的程序開(kāi)發(fā),通過(guò)對(duì)象間的彼此協(xié)同,相互調(diào)用,完成程序的構(gòu)建# POP (Procedure Oriented Programing) 面向過(guò)程(方法、函數(shù))編程 C 
# 以過(guò)程為基本單位的程序開(kāi)發(fā),通過(guò)過(guò)程間的彼此協(xié)同,相互調(diào)用,完成程序的構(gòu)建# AOP的概念:本質(zhì)就是Spring的動(dòng)態(tài)代理開(kāi)發(fā),通過(guò)代理類(lèi)為原始類(lèi)增加額外功能。好處:利于原始類(lèi)的維護(hù)
# 注意:AOP編程不可能取代OOP,而是OOP編程的補(bǔ)充。

4.2 AOP編程的開(kāi)發(fā)步驟

  1. 原始對(duì)象
  2. 額外功能 (MethodInterceptor)
  3. 切入點(diǎn)
  4. 組裝切面 (額外功能+切入點(diǎn))

4.3 切面的名詞解釋

切面 = 切入點(diǎn) + 額外功能 幾何學(xué)面 = 點(diǎn) + 相同的性質(zhì)

image-20230529150312064

5. AOP的底層實(shí)現(xiàn)原理

5.1 核心問(wèn)題

  • AOP如何創(chuàng)建動(dòng)態(tài)代理類(lèi)?(動(dòng)態(tài)字節(jié)碼技術(shù))
  • Spring工廠如何加工創(chuàng)建代理對(duì)象?通過(guò)原始對(duì)象的id值,獲得的是代理對(duì)象。

5.2 動(dòng)態(tài)代理類(lèi)的創(chuàng)建

1. JDK的動(dòng)態(tài)代理

  • Proxy.newProxyInstance()方法參數(shù)詳解:

    image-20200428175248912

image-20200428175316276

  • 編碼:

    public class TestJDKProxy {public static void main(String[] args) {//1.創(chuàng)建原始對(duì)象//注意:由于后面匿名子類(lèi)的方法中用到了userService,所以應(yīng)該用final修飾//     而JDK1.8以后默認(rèn)加了final,不需要手動(dòng)加UserService userService = new UserServiceImpl();//2.JDK創(chuàng)建代理對(duì)象InvocationHandler handler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("----------- JDKProxy log -----------");\//目標(biāo)方法運(yùn)行:Object ret = method.invoke(userService, args);return ret;}};UserService userServiceProxy = (UserService) Proxy.newProxyInstance(userService.getClass().getClassLoader(), userService.getClass().getInterfaces(),handler);userServiceProxy.login("Leo", "123456");userServiceProxy.register(new User());}
    }
    

2. CGlib的動(dòng)態(tài)代理

  • 原理:通過(guò)父子繼承關(guān)系創(chuàng)建代理對(duì)象。原始類(lèi)作為父類(lèi),代理類(lèi)作為子類(lèi),這樣既可以保證2者方法一致,同時(shí)在代理類(lèi)中提供新的實(shí)現(xiàn)(額外功能+原始方法)

image-20200429111709226

  • CGlib編碼:

    package com.Leo.cglib;import org.springframework.cglib.proxy.Enhancer;
    import org.springframework.cglib.proxy.MethodInterceptor;
    import org.springframework.cglib.proxy.MethodProxy;import java.lang.reflect.Method;public class TestCGlibProxy {public static void main(String[] args) {//1.創(chuàng)建原始對(duì)象UserServiceImpl userService = new UserServiceImpl();//2.通過(guò)CGlib創(chuàng)建代理對(duì)象//  2.1 創(chuàng)建EnhancerEnhancer enhancer = new Enhancer();//  2.2 設(shè)置借用類(lèi)加載器enhancer.setClassLoader(TestCGlibProxy.class.getClassLoader());//  2.3 設(shè)置父類(lèi)(目標(biāo)類(lèi))enhancer.setSuperclass(userService.getClass());//  2.4 設(shè)置回調(diào),額外功能寫(xiě)在里面enhancer.setCallback(new MethodInterceptor() {//相當(dāng)于 InvocationHandler --> invoke()@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {//額外功能:System.out.println("========= CGlibProxy log ========");//目標(biāo)方法執(zhí)行:Object ret = method.invoke(userService, objects);return ret;}});//  2.5 通過(guò)Enhancer對(duì)象創(chuàng)建代理UserServiceImpl service = (UserServiceImpl) enhancer.create();//測(cè)試:service.register();service.login();}
    }
    

3. 總結(jié)

1. JDK動(dòng)態(tài)代理   Proxy.newProxyInstance()  
# 通過(guò)目標(biāo)類(lèi)實(shí)現(xiàn)的接口創(chuàng)建代理類(lèi) 
2. Cglib動(dòng)態(tài)代理 Enhancer                  
# 通過(guò)繼承目標(biāo)類(lèi)創(chuàng)建代理類(lèi) 

5.3 Spring工廠如何返回代理對(duì)象

  • 思路分析:

image-20200430113353205

  • 編碼模擬:

    public class ProxyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return bean;}@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {InvocationHandler invocation = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("----------- 模擬Spring返回代理對(duì)象的方式 log -----------");Object ret = method.invoke(bean, args);return ret;}};return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), invocation);}
    }
    
      <!-- 1.配置原始對(duì)象 --><bean id="userService" class="com.Leo.factory.UserServiceImpl"></bean><!-- 2.配置自己模擬的ProxyBeanPostProcessor --><bean id="proxyBeanPostProcessor" class="com.Leo.factory.ProxyBeanPostProcessor"/>
    

6. 基于注解的AOP編程

6.1 開(kāi)發(fā)步驟:

  1. 原始對(duì)象

  2. 額外功能

  3. 切入點(diǎn)

  4. 組裝切面

    /*** 聲明切面類(lèi)     @Aspect* 定義額外功能   @Around* 定義切入點(diǎn)     @Around("execution(* login(..))")**/
    @Aspect
    public class MyAspect {@Around("execution(* login(..))")//組裝了切入點(diǎn)和額外功能public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//額外功能:System.out.println("--------- 基于注解的AOP編程 log --------");//原始方法執(zhí)行:Object ret = joinPoint.proceed();return ret;}
    }
    
       <!-- 原始對(duì)象 --><bean id="userService" class="com.Leo.aspect.UserServiceImpl"></bean><!-- 切面 --><bean id="myAspect" class="com.Leo.aspect.MyAspect"/><!-- 開(kāi)啟基于注解的AOP編程 --><aop:aspectj-autoproxy/>
    

6.2 細(xì)節(jié)分析:

  • 切入點(diǎn)復(fù)用:

    @Aspect
    public class MyAspect {/*** 切入點(diǎn)復(fù)用:定義一個(gè)函數(shù),加上@Pointcut注解,通過(guò)該注解的value定義切入點(diǎn)表達(dá)式,以后可以復(fù)用。*/@Pointcut("execution(* login(..))")public void myPointcut(){}@Around("myPointcut()")//組裝了切入點(diǎn)和額外功能public Object around(ProceedingJoinPoint joinPoint) throws Throwable {//額外功能:System.out.println("--------- 基于注解的AOP編程 log --------");//原始方法執(zhí)行:Object ret = joinPoint.proceed();return ret;}@Around("myPointcut()")public Object around1(ProceedingJoinPoint joinPoint) throws Throwable {//額外功能:System.out.println("--------- 基于注解的AOP編程 tx --------");//原始方法執(zhí)行:Object ret = joinPoint.proceed();return ret;}}
    
  • 動(dòng)態(tài)代理的創(chuàng)建方式:

    AOP底層實(shí)現(xiàn)  2種代理創(chuàng)建方式1.  JDK   通過(guò)實(shí)現(xiàn)接口,創(chuàng)建代理對(duì)象2.  Cglib 通過(guò)繼承目標(biāo)類(lèi),創(chuàng)建代理對(duì)象默認(rèn)情況 AOP編程 底層應(yīng)用JDK動(dòng)態(tài)代理創(chuàng)建方式 如果要切換Cglib1. 基于注解AOP開(kāi)發(fā)<aop:aspectj-autoproxy proxy-target-class="true" />2. 傳統(tǒng)的AOP開(kāi)發(fā)<aop:config proxy-target-class="true"></aop>
    

7. AOP開(kāi)發(fā)中的一個(gè)坑

坑:在同一個(gè)業(yè)務(wù)類(lèi)中,業(yè)務(wù)方法間相互調(diào)用時(shí),只有最外層的方法,加入了額外功能(內(nèi)部的方法,通過(guò)普通的方式調(diào)用,運(yùn)行的都是原始方法)。如果想讓內(nèi)層的方法也調(diào)用代理對(duì)象的方法,就要實(shí)現(xiàn)AppicationContextAware獲得工廠,進(jìn)而獲得代理對(duì)象。

public class UserServiceImpl implements UserService, ApplicationContextAware {private ApplicationContext ctx;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.ctx = applicationContext;}@Log@Overridepublic void register(User user) {System.out.println("UserServiceImpl.register 業(yè)務(wù)運(yùn)算 + DAO ");//throw new RuntimeException("測(cè)試異常");//調(diào)用的是原始對(duì)象的login方法 ---> 核心功能/*設(shè)計(jì)目的:代理對(duì)象的login方法 --->  額外功能+核心功能ApplicationContext ctx = new ClassPathXmlApplicationContext("/applicationContext2.xml");UserService userService = (UserService) ctx.getBean("userService");userService.login();Spring工廠重量級(jí)資源 一個(gè)應(yīng)用中 應(yīng)該只創(chuàng)建一個(gè)工廠*/UserService userService = (UserService) ctx.getBean("userService");userService.login("Leo", "123456");}@Overridepublic boolean login(String name, String password) {System.out.println("UserServiceImpl.login");return true;}
}

8. AOP階段知識(shí)總結(jié)

AOP 總結(jié)

http://m.aloenet.com.cn/news/1179.html

相關(guān)文章:

  • 微信微網(wǎng)站平臺(tái)seo優(yōu)化流程
  • j昆明網(wǎng)站制作公司關(guān)鍵詞搜索指數(shù)
  • 怎么靠做網(wǎng)站賺錢(qián)嗎企業(yè)宣傳方式有哪些
  • python 做網(wǎng)站開(kāi)發(fā)嗎app拉新怎么做
  • 銅山區(qū)建設(shè)局局網(wǎng)站周保春安卓?jī)?yōu)化大師舊版
  • 網(wǎng)站搜索不到公司網(wǎng)站如何建造一個(gè)網(wǎng)站
  • 網(wǎng)址你知道我的意思的免費(fèi)何鵬seo
  • 做網(wǎng)站的服務(wù)商最新軍事新聞今日最新消息
  • 誰(shuí)可以做網(wǎng)站優(yōu)化排名推廣百度管理員聯(lián)系方式
  • 讓其他公司做網(wǎng)站應(yīng)注意什么問(wèn)題網(wǎng)站搜索引擎優(yōu)化主要方法
  • 溫州網(wǎng)站推廣哪家好國(guó)家免費(fèi)技能培訓(xùn)
  • 東莞南城網(wǎng)站建設(shè)價(jià)格站內(nèi)關(guān)鍵詞自然排名優(yōu)化
  • 湖南做網(wǎng)站磐石網(wǎng)絡(luò)案例哈爾濱百度關(guān)鍵詞優(yōu)化
  • 400電話網(wǎng)站源碼百度集團(tuán)總部在哪里
  • 做電影網(wǎng)站還是國(guó)外服務(wù)器如何做一個(gè)營(yíng)銷(xiāo)方案
  • 珠海營(yíng)銷(xiāo)型網(wǎng)站建設(shè)公司長(zhǎng)沙網(wǎng)站優(yōu)化推廣方案
  • 澄邁網(wǎng)站新聞建設(shè)百度空間登錄
  • 制作網(wǎng)站公司 可以要求后續(xù)修改嗎查詢(xún)網(wǎng)站注冊(cè)信息
  • 直裝模板源碼搜索引擎優(yōu)化自然排名的優(yōu)點(diǎn)
  • 成都建設(shè)銀行社會(huì)招聘網(wǎng)站今日熱點(diǎn)新聞大事件
  • 用dw制作個(gè)介紹家鄉(xiāng)網(wǎng)站煙臺(tái)網(wǎng)站建設(shè)
  • 做網(wǎng)站賺錢(qián)嗎?pageadmin建站系統(tǒng)
  • 免費(fèi)建站網(wǎng)站網(wǎng)站開(kāi)發(fā)需要的技術(shù)
  • 制作百度移動(dòng)網(wǎng)站每日一則新聞?wù)?/a>
  • 慈利做網(wǎng)站在哪里sem和seo有什么區(qū)別
  • 微信手機(jī)網(wǎng)站開(kāi)發(fā)外貿(mào)網(wǎng)站外鏈平臺(tái)
  • 蘋(píng)果電腦做網(wǎng)站的步驟seo課程培訓(xùn)中心
  • 手機(jī)移動(dòng)網(wǎng)絡(luò)限制網(wǎng)站武漢電腦培訓(xùn)學(xué)校有哪些
  • 鄉(xiāng)鎮(zhèn)網(wǎng)站建設(shè)工作計(jì)劃國(guó)際新聞最新消息
  • wordpress mysql 配置關(guān)鍵詞優(yōu)化難度查詢(xún)