java元婴期(19)----java进阶(spring(3)----AOP相关概念实现方式)
AOP介紹
什么是AOP
在軟件業(yè),AOP為Aspect Oriented Programming的縮寫,意為:面向切面編程,通過預(yù)編譯方式和運行期動態(tài)代理實現(xiàn)程序功能的統(tǒng)一維護的一種技術(shù)。AOP是OOP(面向?qū)ο缶幊?#xff09;的延續(xù),是軟件開發(fā)中的一個熱點,也是Spring框架中的一個重要內(nèi)容,是函數(shù)式編程的一種衍生范型。利用AOP可以對業(yè)務(wù)邏輯的各個部分進行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時提高了開發(fā)的效率。
AOP采取橫向抽取機制,取代了傳統(tǒng)縱向繼承體系重復(fù)性代碼
經(jīng)典應(yīng)用:事務(wù)管理、性能監(jiān)視、安全檢查、緩存 、日志等
Spring AOP使用純Java實現(xiàn),不需要專門的編譯過程和類加載器,在運行期通過代理方式向目標類織入增強代碼
AspectJ是一個基于Java語言的AOP框架,Spring2.0開始,Spring AOP引入對Aspect的支持,AspectJ擴展了Java語言,提供了一個專門的編譯器,在編譯時提供橫向代碼的織入
代理
AOP實現(xiàn)原理
aop底層將采用代理機制進行實現(xiàn)。
接口 + 實現(xiàn)類:spring采用 jdk 的動態(tài)代理Proxy。
實現(xiàn)類:spring 采用 cglib字節(jié)碼增強。
AOP術(shù)語【掌握】
? ? ? target目標類:需要被代理的類。例如:UserService
Joinpoint連接點:所謂連接點是指那些可能被攔截到的方法。例如:所有的方法
?PointCut切入點:已經(jīng)被增強的連接點。例如:addUser()
? ? ? ? ? ? ? ?advice:通知/增強,增強代碼。例如:after、before
? ? Weaving織入:是指把增強advice應(yīng)用到目標對象target來創(chuàng)建新的代理對象proxy的過程.
? ? ? ? ? ? ? ? proxy:代理類
? ? ? ?Aspect切面:是切入點pointcut和通知advice的結(jié)合
一個線是一個特殊的面。
一個切入點和一個通知,組成成一個特殊的面。
手動方式(了解)
JDK動態(tài)代理
JDK動態(tài)代理 對“裝飾者”設(shè)計模式 簡化。使用前提:必須有接口
1.目標類:接口 + 實現(xiàn)類
2.切面類:用于存通知 MyAspect
3.工廠類:編寫工廠生成代理
4.測試
目標類
public interface UserService {public void addUser();public void updateUser();public void deleteUser(); }切面類
public class MyAspect {public void before(){System.out.println("雞首");}public void after(){System.out.println("牛后");} }工廠
過程:
參數(shù)1:loader ,類加載器,動態(tài)代理類 運行時創(chuàng)建,任何類都需要類加載器將其加載到內(nèi)存。
 ?? ?一般情況:當前類.class.getClassLoader();
 ?? ?目標類實例.getClass().get...
 參數(shù)2:Class[] interfaces 代理類需要實現(xiàn)的所有接口
 ?? ?方式1:目標類實例.getClass().getInterfaces() ?;注意:只能獲得自己接口,不能獲得父元素接口
 ?? ?方式2:new Class[]{UserService.class} ??
 ?? ?例如:jdbc 驅(qū)動 ?--> DriverManager ?獲得接口 Connection
 參數(shù)3:InvocationHandler ?處理類,接口,必須進行實現(xiàn)類,一般采用匿名內(nèi)部
 ?? ?提供 invoke 方法,代理類的每一個方法執(zhí)行時,都將調(diào)用一次invoke
 ?? ?參數(shù)3.1:Object proxy :代理對象
 ?? ?參數(shù)3.2:Method method : 代理對象當前執(zhí)行的方法的描述對象(反射)
 ?? ??? ?執(zhí)行方法名:method.getName()
 ?? ??? ?執(zhí)行方法:method.invoke(對象,實際參數(shù))
 ?? ?參數(shù)3.3:Object[] args :方法實際參數(shù)
?
測試
@Test public void demo01(){UserService userService = MyBeanFactory.createService();userService.addUser();userService.updateUser();userService.deleteUser(); }?
?
CGLIB字節(jié)碼增強(了解)
- 沒有接口,只有實現(xiàn)類。
- 采用字節(jié)碼增強框架cglib,在運行時創(chuàng)建目標類的子類,從而對目標類進行增強。
- 導(dǎo)入jar包:
?????? 自己導(dǎo)包(了解):
????????????? 核心:hibernate-distribution-3.6.10.Final\lib\bytecode\cglib\cglib-2.2.jar
????????????? 依賴:struts-2.3.15.3\apps\struts2-blank\WEB-INF\lib\asm-3.3.jar
?????? spring-core..jar 已經(jīng)整合以上兩個內(nèi)容
工廠類
public class MyBeanFactory {public static UserServiceImpl createService(){//1 目標類final UserServiceImpl userService = new UserServiceImpl();//2切面類final MyAspect myAspect = new MyAspect();// 3.代理類 ,采用cglib,底層創(chuàng)建目標類的子類//3.1 核心類Enhancer enhancer = new Enhancer();//3.2 確定父類enhancer.setSuperclass(userService.getClass());/* 3.3 設(shè)置回調(diào)函數(shù) , MethodInterceptor接口 等效 jdk InvocationHandler接口* intercept() 等效 jdk invoke()* 參數(shù)1、參數(shù)2、參數(shù)3:以invoke一樣* 參數(shù)4:methodProxy 方法的代理*/enhancer.setCallback(new MethodInterceptor(){@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//前myAspect.before();//執(zhí)行目標類的方法Object obj = method.invoke(userService, args);// * 執(zhí)行代理類的父類 ,執(zhí)行目標類 (目標類和代理類 父子關(guān)系)methodProxy.invokeSuper(proxy, args);//后myAspect.after();return obj;}});//3.4 創(chuàng)建代理UserServiceImpl proxService = (UserServiceImpl) enhancer.create();return proxService;} }?
AOP聯(lián)盟通知類型
AOP聯(lián)盟為通知Advice定義了org.aopalliance.aop.Advice
Spring按照通知Advice在目標類方法的連接點位置,可以分為5類
前置通知 org.springframework.aop.MethodBeforeAdvice
- 在目標方法執(zhí)行前實施增強
后置通知 org.springframework.aop.AfterReturningAdvice
- 在目標方法執(zhí)行后實施增強
環(huán)繞通知 org.aopalliance.intercept.MethodInterceptor
- 在目標方法執(zhí)行前后實施增強
異常拋出通知 org.springframework.aop.ThrowsAdvice
- 在方法拋出異常后實施增強
引介通知 org.springframework.aop.IntroductionInterceptor
- 在目標類中添加一些新的方法和屬性
環(huán)繞通知,必須手動執(zhí)行目標方法
try{
?? //前置通知
?? //執(zhí)行目標方法
?? //后置通知
} catch(){
?? //拋出異常通知
}
spring編寫代理:半自動
讓spring 創(chuàng)建代理對象,從spring容器中手動的獲取代理對象。
導(dǎo)入jar包:
? ? ? ?核心:4+1
?????? AOP:AOP聯(lián)盟(規(guī)范)、spring-aop (實現(xiàn))
目標類
public interface UserService {public void addUser();public void updateUser();public void deleteUser(); }?
?
?
?
切面類
切面類中確定通知,需要實現(xiàn)不同接口,接口就是規(guī)范,從而就確定方法名稱。
采用“環(huán)繞通知” MethodInterceptor
public class MyAspect implements MethodInterceptor {@Overridepublic Object invoke(MethodInvocation mi) throws Throwable {System.out.println("前3");//手動執(zhí)行目標方法Object obj = mi.proceed();System.out.println("后3");return obj;} }?
?
spring配置
<!-- 1 創(chuàng)建目標類 --><bean id="userServiceId" class="com.itheima.b_factory_bean.UserServiceImpl"></bean><!-- 2 創(chuàng)建切面類 --><bean id="myAspectId" class="com.itheima.b_factory_bean.MyAspect"></bean><!-- 3 創(chuàng)建代理類 * 使用工廠bean FactoryBean ,底層調(diào)用 getObject() 返回特殊bean* ProxyFactoryBean 用于創(chuàng)建代理工廠bean,生成特殊代理對象interfaces : 確定接口們通過<array>可以設(shè)置多個值只有一個值時,value=""target : 確定目標類interceptorNames : 通知 切面類的名稱,類型String[],如果設(shè)置一個值 value=""optimize :強制使用cglib<property name="optimize" value="true"></property>底層機制如果目標類有接口,采用jdk動態(tài)代理如果沒有接口,采用cglib 字節(jié)碼增強如果聲明 optimize = true ,無論是否有接口,都采用cglib--><bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean"><property name="interfaces" value="com.itheima.b_factory_bean.UserService"></property><property name="target" ref="userServiceId"></property><property name="interceptorNames" value="myAspectId"></property></bean>?
?
?
?
?
測試
@Testpublic void demo01(){String xmlPath = "com/itheima/b_factory_bean/beans.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);//獲得代理類UserService userService = (UserService) applicationContext.getBean("proxyServiceId");userService.addUser();userService.updateUser();userService.deleteUser();}?
總結(jié)
以上是生活随笔為你收集整理的java元婴期(19)----java进阶(spring(3)----AOP相关概念实现方式)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: java元婴期(18)----java进
- 下一篇: java元婴期(20)----java进
