日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

这波 SpringFramework5.x 我先干了(AOP编程)

發布時間:2024/1/18 javascript 101 豆豆
生活随笔 收集整理的這篇文章主要介紹了 这波 SpringFramework5.x 我先干了(AOP编程) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、靜態代理設計模式

1.為什么需要代理設計模式
1.1問題

  • 在JavaEE分層開發過程中,哪個層次對于我們來講最重要

    DAO—>Service–>Controller
    JavaEE分層開發中,最為重要的是Service Service業務層

  • Service層中包含了哪些代碼?

    Service層中 =核心功能代碼(幾十行 上百行)+額外功能代碼(附加功能)1.核心功能業務運算DAO調用2.額外功能不屬于業務可有可無代碼量小例如:事務、日志、性能。。。
  • 額外功能書寫在Service層中好不好?

    Service層的調用者(controller):需要在Service層書寫額外功能軟件設計者:Service層不需要額外功能
  • 現實生活中 的解決方式

    2.代理設計模式
    2.1概念

    通過代理類,為原始類(目標)增加額外功能
    好處:利于原始類(目標)的維護

    2.2名詞解釋

    1.目標類 原始類指的是 業務類(核心功能 --->業務運算 DAO調用)2.目標方法 原始方法目標類(原始類)中的方法 就是目標方法(原始方法)3.額外功能(附加功能) 日志,事務,性能

    2.3代理開發的核心要素

    代理類=目標類(原始類)+額外功能+原始類(目標類)實現相同的接口 房東---->public interface UserService{m1(){}m2(){}}UserServiceImpl implements UserService{m1(){}m2(){}}

    2.4編碼

    靜態代理: 為每一個原始類,手工編寫一個代理類(.java .class)

    2.5靜態代理存在的問題

    1.靜態類文件過多,不利于項目管理UserServiceImpl UserServiceProxyOrderServiceImpl OrderServiceProxy2.額外功能維護性差代理類中 額外功能修改復雜(麻煩)

二、Spring的動態代理開發

1.Spring動態代理的概念

概念:通過代理類為原始類(目標類)增加額外功能
好處:利于原始類(目標類)的維護

2.搭建開發環境

<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>

3.Spring動態代理的開發步驟
①創建原始對目標對象

public class UserServiceImpl implements UserService {@Overridepublic void register(User user) {System.out.println("UserServiceImpl.register===核心業務代碼注冊 調用DAO");}@Overridepublic boolean login(String name, String password) {System.out.println("UserServiceImpl.login======核心業務代碼登錄 調用DAO");return false;} } <bean id="userService" class="com.myspring.proxy.UserServiceImpl" />

②、額外功能
MethodBeforeAdvice接口

額外的功能書寫在接口的實現中,運行在原始方法之前運行額外功能

public class Before implements MethodBeforeAdvice {/*作用:需要把運行在原始方法執行之前運行的額外功能,書寫在before方法中*/@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("======額外功能=====");} } <bean id="before" class="com.myspring.dynamic.Before" />

③、定義切入點

切入點:額外功能加入的位置目的:由程序員根據自己的需要,決定額外功能加入給哪個原始方法 registe / longin 簡單的測試:所有方法都作為切入點都加入額外的功能。 <aop:config><!--定義切入的方式--><aop:pointcut id="pc" expression="execution(* *(..))"/></aop:config>

④、組裝(②、③整合)

表達的含義:所有方法 都加入before的額外功能<aop:advisor advice-ref="before" pointcut-ref="pc"/> 這是④的完整配置<aop:config><!--定義切入的方式--><aop:pointcut id="pc" expression="execution(* *(..))"/><aop:advisor advice-ref="before" pointcut-ref="pc"/></aop:config>

⑤、調用

目的:獲得Sporing工廠的動態代理對象,并進行調用ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");注意:1.Spring的工廠通過原始對象的id值獲得的是代理對象2.獲得代理對象后,可以通過聲明接口類型,進行對象的存儲UserService userService = applicationContext.getBean("userService", UserService.class);userService.login("bugz","123456");userService.register(new User("bugz","123456"));

4.動態代理細節分析
①、Spring創建的動態代理類在那里?

Spring框架在運行時,通過動態字節碼技術,在JVM創建的,運行在JVM內部,等程序結束后,會和JVM一起消失。
————————————————————————————————————————————————————
什么叫動態字節碼技術:通過第三方動態字節碼框架,在JVM中創建對應類的字節碼,進而創建對象,當虛擬機結束,動態字節碼跟著消失。
—————————————————————————————————————————————————
結論:動態代理不需要定義類文件,都是JVM運行過程中動態創建的,所以不會造成靜態代理,類文件數量過多,影響項目管理的問題。

②、動態代理編程簡化代理的開發

在額外功能不變的前提下,創建其他目標類(原始類)的代理對象時,只需要指定原始(目標)對象即可。

③動態代理額外功能的維護性大大增強

三、Spring動態代理詳解

1.額外功能的詳解

  • MethodBeforeAdvice分析
1.MethodBeforeAdvice接口作用:額外功能運行在原始方法之前,進行額外功能操作。public class Before implements MethodBeforeAdvice {/*作用:需要把運行在原始方法執行之前運行的額外功能,書寫在before方法中方法參數介紹:Method method: 額外功能所增加給的那個原始方法Object[] objects: 額外功能所增加給的那個原始方法的參數。Object o:額外功能所增加給的那個原始對象*/@Overridepublic void before(Method method, Object[] objects, Object o) throws Throwable {System.out.println("======額外功能=====");} } ——————————————————————————————————————————————————————————————————————————————————————2.before方法中的三個參數在實戰中該如何使用before方法中的參數,在實戰中,會根據需要進行使用,不一定都會用到,也有可能都不用。
  • MethodInterceptor(方法攔截器)
methodinterceptor接口:額外功能可以根據需要運行在原始方法執行 前、后、前后。-------------------------------------------------------------------public class Around implements MethodInterceptor {/*invoke方法的作用:額外功能書寫在invoke額外功能可以加在 原始方法之前原始方法之后原始方法之前and之后確定:原始方法怎么執行methodeINvocation.proceed();參數:MethodInvocation methodInvocation:額外功能所增加給的那個原始方法返回值:原始方法的返回值*/@Overridepublic Object invoke(MethodInvocation methodInvocation) throws Throwable {System.out.println("+++++++++++額外功能運行在之前+++++++++");Object proceed = methodInvocation.proceed();return proceed;}}

額外功能運行在原始代碼方法執行之后

@Overridepublic Object invoke(MethodInvocation methodInvocation) throws Throwable {Object proceed = methodInvocation.proceed();System.out.println("+++++++++++額外功能運行在之后+++++++++");return proceed;}

額外功能運行在原始代碼方法執行之前、之后。

什么樣的額外功能,運行在原始方法之前,之后都要添加? 例:事務@Overridepublic Object invoke(MethodInvocation methodInvocation) throws Throwable {System.out.println("+++++++++++額外功能運行在之前+++++++++");Object proceed = methodInvocation.proceed();System.out.println("+++++++++++額外功能運行在之后+++++++++");return proceed;}

額外功能運行在原始方法拋出異常的時候

@Overridepublic Object invoke(MethodInvocation methodInvocation) throws Throwable {Object proceed = null;try {proceed = methodInvocation.proceed();} catch (Throwable throwable) {System.out.println("+++++++++++ 拋出異常時的 額外功能+++++++++");throwable.printStackTrace();}return proceed;}

MethodInterceptor影響原始方法的返回值

原始方法的返回值,直接作為invoke方法的返回值返回,MethodInterceptor不會影響原始方法的返回值 MethodInterceptor影響原始方法的返回值 Invoke方法的返回值,不要直接返回原始方法的運行結果即可。@Overridepublic Object invoke(MethodInvocation methodInvocation) throws Throwable {System.out.println("+++++++++++額外功能+++++++++");Object proceed = methodInvocation.proceed();return false;}

2.切入點詳解

切入點決定額外功能加入位置(方法) <aop:pointcut id="pc" expression="execution(* *(..))"/> execution(* *(..)) --->匹配了所有方法 a b c1.execution() 切入點函數 2.* *(..) 切入點表達式

2.1切入點表達式
①、方法切入點表達式

* *(..) -->所有方法 * --->修飾符 返回值 * --->方法名 () --->參數表 .. --->對于參數沒有要求(參數有沒有,參數有幾個都行,參數是什么類型的都行)
  • 定義login方法的切入點* login(..) #定義register作為切入點 * register(..)
  • 定義long方法且login方法有兩個字符串類型的參數 作為切入點* login(String,String) #注意:非Java.lang包中的類型,必須要寫全限定名 * register(com.xxx.xxx.User) # ..可以和具體的參數類型連用 * login(String,..) -> login(String)/login(String,String)/login(String,com.xxx.User)
  • 精準方法切入點限定修飾符 返回值 包.類.方法(參數) * com.xxx.xxx.login() * com.xxx.xxx.login(String,String)

②、類切入點

指定特定類作為切入點(額外功能加入的位置),自然這個類中的所有方法,都會加上額外的功能

  • 語法1#類中所有的方法加入了額外功能 * com.xx.xx.UserServiceImpl.*(..)
  • 語法2 #忽略包1.類只存在一級包 com.UserServiceImpl* *.UserServiceImpl.*(..)2.類存在多級包 com.xxx.xxx.xxx.UserServiceImpl* *..UserServiceImpl.*(..)

③、包切入點 實戰

指定包作為額外功能加入的位置,自然包中所有類及其方法都會加入額外功能

  • 語法1

    #切入包中的所有類,必須在xxx中,不能在xxx包的子包中 * com.a.xxx.*.*(..)
  • 語法2

    #切入點當前包及其子包都生效 * com.a.xxx..*.*(..)

2.2切入點函數

切入點函數:用于執行切入點表達式

①、execution

最為重要的切入點函數,功能最全 執行 方法切入點表達式 類切入點表達式 包切入點表達式弊端:execution執行切入點表達式,書寫麻煩execution(* com.xxx.xxx..*.*(..)) 注意: 其他的切入點函數 簡化execution書寫復雜度,功能上完全一致

②、args

作用:主要用于函數(方法)參數的匹配 切入點:例如---方法參數必須得是2個字符串類型的參數execution(* *(String,String))args(String,String)

③、within

作用:主要用于進行類、包切入點表達式的匹配 切入點:UserServiceImpl這個類execution(* *..UserServiceImpl.*(..))within(*..UserServiceImpl)execution(* com.xx.xx..*.*(..))within(com.xx.xx..*)

④、@annotation

作用:為具有特殊注解的方法加入額外功能 <aop:pointcut id="pc" expression="@annotation(com.xx.Log)"/>

⑤、切入點函數的邏輯運算

指的是整合多個切入點函數一起配合工作,進而完成更為復雜的需求

  • and與操作
案例:login 同時 參數2個字符串1.exection(* login(String,String))2.exection(* login(.)) and args(String,String)注意 與操作不同用于同種類型的切入點函數案例:register方法和login方法作為切入點exection(* login(..)) or execution(* register(..))
  • or或操作
案例:register方法和login方法作為切入點exection(* login(..)) or execution(* register(..))

四、AOP編程

1.AOP編程

AOP(Aspect Oriented Programming) 面向切面編程 = Spring動態代理開發
以切面為基本單位的程序開發,通過切面間的彼此協同,相互調用,完成程序的構建
切面 = 切入點+額外功能

OOP(Object Oriented Programming) 面向對象編程 JAVA
以對象為基本單位的程序開發,通過對象間的彼此協同,相互調用,完成程序的構建

POP(Procedure Oriented Programming) 面向過程(方法、函數)編程 c語言
以過程為單位的程序開發,通過過程間的彼此協同,相互調用,完成程序的構建。

AOP的概念:本質就是Spring的動態代理開發,通過代理類為原始類增加額外功能。
好處:利于原始類的維護
注意:AOP編程不可能取代OOP,OOP編程有意補充。

2.AOP編程的開發步驟

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

3.切面的名詞解釋

切面 = 切入點+額外功能
幾何學:面=點+相同性質

五、AOP底層實現原理

1.核心問題

1.AOP如何創建動態代理類(動態字節碼技術) 2.Spring工廠如何加工創建代理類對象通過原始類對象的id值,獲得的是代理對象

2.動態代理類的創建
2.1、JDK的動態代理

  • Proxy.newProxyInstance方法參數詳解


  • 編碼
public class TestJDKProxy {public static void main(String[] args) {//1.創建原始對象UserServiceImpl userService = new UserServiceImpl();InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("====log====");//原始方法運行Object invoke = method.invoke(userService, args);return invoke;}};//2.JDK創建動態代理UserService userService1 =(UserService) Proxy.newProxyInstance(UserService.class.getClassLoader(),userService.getClass().getInterfaces(),invocationHandler);userService1.login("bugz","123");userService1.register(new User("bugz","123"));/*細節問題:1.借用類加載器 UserService/TestJDKProxy2.JDK8.x前 需要這樣寫 final UserServiceImpl userService = new UserServiceImpl();*/}

2.2 CGlib動態代理

CGlib創建動態代理的原理:父子繼承關系創建代理對象,原始類作為父類,代理類作為子類,這樣既可以保證二者方法一致,同時在代理類中提供新的實現(額外功能+原始方法)

  • 編碼
import com.myspring.proxy.User; 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 TestCglib {public static void main(String[] args) {//1.創建原始對象UserService userService = new UserService();/*2.通過cglib的方式創建動態代理對象JDK創建代理方式 Proxy.newProxyInstance(classloader,interfaces,invocationhandler)Enhancer.setClassLoader();Enhancer.setSuperClass();Enhancer.setCallback();---->MethodInterceptor(cglib)Enhancer.create()--->代理*/Enhancer enhancer = new Enhancer();enhancer.setClassLoader(TestCglib.class.getClassLoader());enhancer.setSuperclass(userService.getClass());MethodInterceptor methodInterceptor = new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {System.out.println("------cglib new log--------");Object invoke = method.invoke(userService, args);return invoke;}};enhancer.setCallback(methodInterceptor);UserService userServiceProxy=(UserService) enhancer.create();userServiceProxy.login("bugz","123456");userServiceProxy.register(new User());} }
  • 總結

1.JDK動態代理 Proxy.newProxyInstance() ------------通過接口創建代理的實現類
2.Cglib動態代理 Enhancer---------------------------------通過繼承父類創建代理類

3.Spring工廠如何加工原始對象

  • 思路分析
  • 編碼
import org.springframework.beans.BeansException; import org.springframework.beans.factory.config.BeanPostProcessor; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy;public class ProxyBeanPostProcessor implements BeanPostProcessor {@Overridepublic Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {return null;}//使用jdk代理模擬工廠的代理@Overridepublic Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {InvocationHandler invocationHandler = new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("---模擬代理的額外功能---");System.out.println(beanName);Object invoke = method.invoke(bean, args);return invoke;}};return Proxy.newProxyInstance(ProxyBeanPostProcessor.class.getClassLoader(),bean.getClass().getInterfaces(),invocationHandler);} } <!--原始對象--><bean id="userService" class="com.myspring.factory.UserServiceImpl"/><!--模擬代理1.實現BeanPostProcessor進行加工2.配置文件中對BeanPostProcessor進行配置--><bean id="beanPostProcessor" class="com.myspring.factory.ProxyBeanPostProcessor"/>

六、基于注解的AOP編程

1.基于注解的AOP開發步驟
1.原始對象
2.額外功能
3.切入點
4.組裝切面

#通過切面類 定義了 額外功能@Around定義了切入點@Around("execution(* login(..))")@Aspect 切面類/*1.額外功能public class MyAround implements MethodInterceptor{public Object invoke(MethodInvocation invocation){Object ret = invocation.proceed();return ret;}}2.切入點<aop:config<aop:pointcut id="" expression="execution(* login(..))"/>*/ @Aspect public class MyAspect {@Around("execution(* login(..))")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("---切面類額外功能");Object proceed = joinPoint.proceed();return proceed;} } <!--原始對象--><bean id="userService" class="com.myspring.aspectproxy.UserServiceImpl"/><!--切面1.額外功能2.切入點3.組裝切面--><bean id="arround" class="com.myspring.aspectproxy.MyAspect"/><!--告知Spring基于注解進行AOP編程--><aop:aspectj-autoproxy/>

2.切入點復用
(1)切入點復用

#切入點復用:在切面類中定義一個函數 上面加@Pointcut注解 通過這種方式,定義切入點表達式,后續更加有利于切入點復用。 @Aspect public class MyAspect { @Pointcut("execution(* login(..))")public void pointcut(){}@Around(value = "pointcut()")public Object around(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("---切面類額外功能111");Object proceed = joinPoint.proceed();return proceed;}@Around(value = "pointcut()")public Object around2(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("---切面類額外功能222");Object proceed = joinPoint.proceed();return proceed;} }

(2)、動態代理的創建方式

AOP底層實現 2種代理創建方式 1.JDK 通過實現接口 做新的實現類方式 創建代理對象 2.Cglib 通過繼承父類 做新的子類 創建代理對象默認情況 AOP編程底層應用JDK動態代理創建方式 如果切換Cglib1.基于注解AOP開發<aop:aspectj-autoproxy proxy-target-class="true"/>2.傳統的AOP開發<aop:config proxy-target-class="true"></aop:config>

七、AOP開發中的一個坑

坑:在同一個業務類中,進行業務方法間的相互調用,只有最外層的方法,才是加入了額外功能(內部的方法,通過普通的方式調用,都調用的是原始方法)。如果想讓內層的方法也調用代理對象的方法,就要ApplicationContextAware獲得工廠,進而獲得代理對象。 public class UserServiceImpl implements UserService, ApplicationContextAware {private ApplicationContext ctx;@Overridepublic void setApplicationContext(ApplicationContext applicationContext) throws BeansException {this.ctx = applicationContext;}@Overridepublic void register(User user) {System.out.println("UserServiceImpl.register");/*調用的是原始方法的login方法--->核心功能設計的目的:代理對象的log方法 ——————>額外功能+核心功能ApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("/applicationContext2.xml");UserService userService =(UserService) classPathXmlApplicationContext.getBean("userService");userService.login();Spring工廠重量級資源 一個應用中 應該只創建一個工廠*/UserService userService = (UserService) ctx.getBean("userService");userService.login("bugz", "123444");}@Overridepublic void login(String name, String password) {System.out.println("UserServiceImpl.login");} }

八、AOP階段知識總結

總結

以上是生活随笔為你收集整理的这波 SpringFramework5.x 我先干了(AOP编程)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。