动态代理-AOP
1 什么是AOP?
- Aspect Oriented Programming的縮寫,面向切面編程,切面指定就是動態(tài)代理的方法,作用是在不改變業(yè)務(wù)層方法源代碼的基礎(chǔ)上對方法進(jìn)行增強(qiáng),底層使用的是動態(tài)代理技術(shù),面向切面編程也可以理解成面向動態(tài)代理編程。
2 AOP相關(guān)概念
- Target(目標(biāo)對象):被代理的對象就是目標(biāo)對象
- Proxy(代理對象):被增強(qiáng)后的對象就是代理對象
- Joinpoint(連接點(diǎn)):就是目標(biāo)對象中所有被攔截到的方法
- Pointcut(切入點(diǎn)):就是目標(biāo)對象中被增強(qiáng)的方法
- Advice(通知):執(zhí)行目標(biāo)方法之前或者之后調(diào)用的方法就是通知
- Aspect(切面):通知方法和切入點(diǎn)方法結(jié)合所在的位置叫做切面
- Weaving(織入):通知方法和切入點(diǎn)方法結(jié)合的過程,織入之后的結(jié)果就是切面
總結(jié)一下:
連接點(diǎn)是所有被攔截到的方法,切入點(diǎn)是所有被增強(qiáng)的方法,連接點(diǎn)不一定是切入點(diǎn),但是切入點(diǎn)一定是連接點(diǎn)。在執(zhí)行目標(biāo)對象方法之前或者之后要做的事叫做通知,通知中有增強(qiáng)的業(yè)務(wù)。將切入點(diǎn)和通知組織到一起叫織入,織入形成的結(jié)果就是切面。
3 AOP配置實(shí)現(xiàn)步驟
<1>【第一步】導(dǎo)入相關(guān)依賴:spring-context、aspectjweaver
<!--spring核心依賴--> <dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.1.9.RELEASE</version> </dependency> <!--切入點(diǎn)表達(dá)式依賴,作用:通過表達(dá)式找到哪些方法需要增強(qiáng),也就是找到切入點(diǎn)--> <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.6</version> </dependency><2>【第二步】定義通知類和目標(biāo)對象
- AOP目標(biāo)接口:
- AOP目標(biāo)實(shí)現(xiàn)類:
注:代理的為接口對象,接口中沒有的方法,實(shí)現(xiàn)類自己的方法不會被增強(qiáng)
- 通知類:
<3>xml文件配置AOP
1 配置目標(biāo)對象,添加到spring容器中2 配置通知對象,添加到spring容器中3 配置切入點(diǎn)方法和通知方法織入過程,也就配置切面- 純XML配置:
- 注解配置:
注:
使用注解配置AOP,后置通知和異常通知會在最終通知之后調(diào)用,
在spring-context的5.1.9版本中是這樣的,在更高的版本中可能得到了解決,
(5.2.6及以上版本解決了)。
但是我們可以使用環(huán)繞通知解決這個問題,推薦使用環(huán)繞通知
- 核心配置類代替XML
4.底層動態(tài)代理類似原理[studentService動態(tài)代理工廠]
package com.itheima.proxy; import com.itheima.aop.Advice; import com.itheima.service.StudentService; import com.itheima.service.impl.StudentServiceImpl; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;public class StudentServiceProxyFactory {public static StudentService createStudentServiceProxy() {Advice advice = new Advice();//1.創(chuàng)建真實(shí)對象StudentService studentService = new StudentServiceImpl();//可采用set注入//2.創(chuàng)建代理對象/**ClassLoader loader,創(chuàng)建代理對象的class對象Class<?>[] interfaces,告訴代理對象要和目標(biāo)對象實(shí)現(xiàn)相同的接口,就具有相同的功能。InvocationHandler h,處理增強(qiáng)的邏輯*/ClassLoader classLoader = studentService.getClass().getClassLoader();Class<?>[] interfaces = studentService.getClass().getInterfaces();//獲取所有的直接實(shí)現(xiàn)的接口StudentService service = (StudentService) Proxy.newProxyInstance(classLoader, interfaces, new InvocationHandler() {/*** @param proxy 代理對象* @param method 調(diào)用代理對象的方法,findAll、findById、transfer、update。。。* @param args 調(diào)用代理對象方法傳遞進(jìn)來的參數(shù)們* @return 此處的返回值將返回給調(diào)用處* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = null;if (method.getName().equals("transfer") || method.getName().equals("delete")) {try {//1.開啟事務(wù)advice.before();//2.執(zhí)行操作,調(diào)用目標(biāo)方法result = method.invoke(studentService, args);//3.提交事務(wù)advice.afterReturn();} catch (Exception e) {e.printStackTrace();//4.如果有異常則回滾事務(wù)advice.afterThrowable();} finally {//5.釋放資源advice.after();}} else {//執(zhí)行操作,調(diào)用目標(biāo)方法result = method.invoke(studentService, args);}return result;}});return service;} }注:只可對單一實(shí)現(xiàn)類對象進(jìn)行增強(qiáng)
總結(jié)
- 上一篇: 自定义通配器导入bean对象
- 下一篇: 爱似水仙歌词 爱似水仙歌词是什么