spring中AOP代理由spring的IOC容器負責生成,管理,其依賴管理也由IOC容器負責管理,因此,AOP代理可以直接使用容器總的其他bean實例作爲目標,這種管理可由IOC容器的依賴注入提供。spring默認使用java動態代理來創建AOP 代理,這樣就可以爲任何接口實例創建代理了。
spring也可以使用cglib的動態代理,關於jdk動態代理和cglib動態代理之間的區別和聯繫,請看小編《細說java動態代理和cglib動態代理》,當我們配置了cglib之後,在需要代理類而不是代理某個接口的時候,spring框架會自動切換爲cglib。但是默認上使用jdk的動態代理,如果需要我們可以通過配置文件,強制使用cglib代理。
通過上篇博客《Spring的AOP-AspectJ 的靜態實現》,我們不難發現,要實現AOP,程序員主要需要下面的操作:
* 定義普通的業務組件
* 定義切入點,一個切入點可能橫切多個業務組件
* 定義增強處理,增強處理就是在AOP框架爲普通業務組件織入的處理動作;
重點操作在於後兩步,所以AOP的代理工作可以整合爲下列的公式:
AOP代理的方法 = 增強處理 + 目標對象的方法
spring實現AOP主要有兩種方式:
1. 基於註解的“零配置”方式
這裏的註解主要是指@Before……,@aspect ;具體操作請繼續看:
✎ 啓動對AspectJ的支持
<span style="font-family:SimSun;font-size:18px;"><aop:aspectj-autoproxy/></span>
✎ 定義切面bean
當啓動了AspectJ的支持後,我們只需要在spring容器中配置一個帶@Aspect註解的Bean,spring將會自動識別該Bean,並將該Bean作爲切面處理:
<span style="font-family:SimSun;font-size:18px;">package com.ysc.spring; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; @Aspect public class SecurityHandler { // 這裏是該類中的內容 }</span>
使用@aspect註解標註一個java類,該java類將會作爲切面bean。而負責自動增強的後處理Bean將會略過該bean,不會對該bean進行任何增強處理;當spring容器檢測到某個bean類使用了@aspect註解的修飾之後,spring容器不會對該bean進行增強,所以無需擔心該bean類會被增強處理;
✎ Before的增強處理
PS:增強處理有多種方式,這裏以Before的增強處理爲例:
<span style="font-family:SimSun;font-size:18px;">@Before("adAddMethod()") //@After("adAddMethod()") private void checkSecurity(){ System.out.println("-----------checkSecurity----------"); }</span>
我們對checkSecurity()方法進行Before的增強處理,而被增強的java方法是adAddMethod,這就意味着該add方法將被進行 執行前 檢查安全性的增強處理,我們編寫一個client.java 的類,執行對UserManager的方法的調用,查看 當前的Add方法被添加增強處理之後的效果:
public class Client { /** * @param args */ public static void main(String[] args) { BeanFactory factory = new ClassPathXmlApplicationContext("applicationContext.xml"); UserManager userManager = (UserManager)factory.getBean("userManager"); userManager.findUserById(1); userManager.modifyUser(1, "lisi", "123"); userManager.addUser("張三", "123"); } }
查看執行結果如下:
-------------userManager.findUserById()---------
-------------userManager.modifyUser()---------
-----------checkSecurity----------
-------------userManager.add()---------
發現只有被添加增強處理的add方法被執行了安全性檢查的方法,且在add方法執行之前執行的安全檢查,所以使用Before增強處理只能在目標方法執行之前織入增強,而after同理,只能在目標方法執行之後織入增強;
2.基於xml配置文件的管理方式
✎ 配置切面
<span style="font-family:SimSun;font-size:18px;"><aop:config> <aop:aspect id="" ref=""> …… </aop:aspect> </aop:config></span>
✎ 配置增強處理
<span style="font-family:SimSun;font-size:18px;">package com.ysc.spring; import org.aspectj.lang.JoinPoint; public class SecurityHandler { private void checkSecurity(JoinPoint joinpoint){ for(int i =0;i<joinpoint.getArgs().length;i++){ System.out.println(joinpoint.getArgs()[i]); } System.out.println(joinpoint.getSignature().getName()); System.out.println("-----------checkSecurity----------"); } }</span>
✎ 配置切入點
<span style="font-family:SimSun;font-size:18px;"><aop:pointcut expression="execution(* add*(..))" id="addAddMethod"/></span>
這時, 編譯Client.java 類,依舊可以實現零配置方式的效果,所以不管是零配置的方式還是基於xml的方式,都可以在spring框架的基礎上實現AOP。
當我們理解並清晰了Spring的AOP實現原理之後,發現它其實並不神祕,希望能幫到你更好的理解AOP這個“神祕”的切面編程理念!!