javascript
Spring学习总结二
Spring框架的代理與AOP、AspectJ
- Spring學(xué)習(xí)總結(jié)二
- 0、在理解什么是AOP之前的一些話
- 1、什么是AOP
- 2、AOP的重要概念
- 3、代理模式
- 3.1、靜態(tài)代理
- 3.2、動態(tài)代理
- 3.2.1、創(chuàng)建UserService接口
- 3.2.2、創(chuàng)建UserServiceImp類
- 3.2.3、創(chuàng)建MyAspect方面類
- 3.2.4、動態(tài)代理UserService的工具類
- 3.2.5、測試
- 4、cglib代理
- 4.1、導(dǎo)jar包
- 4.2、創(chuàng)建接口
- 4.3、創(chuàng)建實(shí)現(xiàn)類
- 4.4、創(chuàng)建方面類
- 4.5、用cglib的工具類來生成目標(biāo)類
- 4.6、測試
- 5、使用spring.xml配置實(shí)現(xiàn)動態(tài)代理
- 5.1、導(dǎo)jar包
- 5.2、創(chuàng)建接口
- 5.3、創(chuàng)建目標(biāo)類
- 5.4、創(chuàng)建方面類
- 5.5、配置spring.xml
- 5.6、測試
- 6、使用spring.xml實(shí)現(xiàn)AOP編程
- 6.1、在上面一個(gè)例子的基礎(chǔ)上加一個(gè)包
- 6.2、創(chuàng)建接口
- 6.3、創(chuàng)建實(shí)現(xiàn)類
- 6.4、創(chuàng)建方面類
- 6.5、配置spring.xml
- 6.6、測試
- 7、使用AspectJ配置spring.xml實(shí)現(xiàn)AOP編程
- 7.1、導(dǎo)包
- 7.2、創(chuàng)建接口
- 7.3、創(chuàng)建實(shí)現(xiàn)類
- 7.4、創(chuàng)建MyAspect類
- 7.5、編寫spring.xml
- 7.6、測試
- 8、使用注解的AspectJ
- 8.1、導(dǎo)包
- 8.2、創(chuàng)建接口
- 8.3、創(chuàng)建實(shí)現(xiàn)類
- 8.4、創(chuàng)建MyAcpect
- 8.5、編寫spring.xml
- 8.6、測試
Spring學(xué)習(xí)總結(jié)二
今天的主要內(nèi)容就是AOP:
0、在理解什么是AOP之前的一些話
下面1、2兩點(diǎn)都是我百度上抄的,說實(shí)話,我是不太能說出這么精準(zhǔn)的術(shù)語來。
AOP,通俗來說就是在執(zhí)行特定的方法前或者后,去做"某些事情"(比如:轉(zhuǎn)賬前需要將設(shè)置事務(wù),轉(zhuǎn)賬"成功"后需要提交事務(wù))。
我們將尺度放大!有一些業(yè)務(wù)經(jīng)常需要換一些功能。而我們不想再去改項(xiàng)目的硬編碼,從而有了AOP,或者是說,我想通過xml配置來動態(tài)的增加以及減少一些功能,這時(shí)候AOP就可以大顯身手了。
如何學(xué)好AOP?
先訓(xùn)練,再看概念!理清楚思路,你將對AOP的概念讀上幾遍。
1、什么是AOP
AOP: (Aspect Oriented Programming) 面向切面編程。是目前軟件開發(fā)中的一個(gè)熱點(diǎn),也是Spring框架中容。利用AOP可以對業(yè)務(wù)邏輯的各個(gè)部分進(jìn)行隔離,從而使得業(yè)務(wù)邏輯各部分之間的耦合度降低,提高程序的可重用性,同時(shí)提高了開發(fā)的效率。主要的功能是:日志記錄,性能統(tǒng)計(jì),安全控制,事務(wù)處理,異常處理等等。
AOP、OOP在字面上雖然非常類似,但卻是面向不同領(lǐng)域的兩種設(shè)計(jì)思想。OOP(面向?qū)ο缶幊?#xff09;針對業(yè)務(wù)處理過程的實(shí)體及其屬性和行為進(jìn)行抽象封裝,以獲得更加清晰高效的邏輯單元劃分。 而AOP則是針對業(yè)務(wù)處理過程中的切面進(jìn)行提取,它所面對的是處理過程中的某個(gè)步驟或階段,以獲得邏輯過程中各部分之間低耦合性的隔離效果。這兩種設(shè)計(jì)思想在目標(biāo)上有著本質(zhì)的差異。
舉個(gè)簡單的例子,對于“雇員”這樣一個(gè)業(yè)務(wù)實(shí)體進(jìn)行封裝,自然是OOP的任務(wù),我們可以為其建立一個(gè)“Employee”類,并將“雇員”相關(guān)的屬性和行為封裝其中。而用AOP設(shè)計(jì)思想對“雇員”進(jìn)行封裝將無從談起。
同樣,對于“權(quán)限檢查”這一動作片斷進(jìn)行劃分,則是AOP的目標(biāo)領(lǐng)域。而通過OOP對一個(gè)動作進(jìn)行封裝,則有點(diǎn)不倫不類。 換而言之,OOP面向名詞領(lǐng)域,AOP面向動詞領(lǐng)域。
總之,AOP可以通過預(yù)編譯方式和運(yùn)行期動態(tài)代理實(shí)現(xiàn)在不修改源代碼的情況下給程序動態(tài)統(tǒng)一添加功能的一種技術(shù)。
2、AOP的重要概念
實(shí)現(xiàn)AOP的技術(shù),主要分為兩大類:一是采用動態(tài)代理技術(shù),利用截取消息的方式,對該消息進(jìn)行裝飾,以取代原有對象行為的執(zhí)行;二是采用靜態(tài)織入的方式,引入特定的語法創(chuàng)建“方面”,從而使得編譯器可以在編譯期間織入有關(guān)“方面”的代碼。然而殊途同歸,實(shí)現(xiàn)AOP的技術(shù)特性卻是相同的,分別為:
上述的技術(shù)特性組成了基本的AOP技術(shù),大多數(shù)AOP工具均實(shí)現(xiàn)了這些技術(shù)。它們也可以是研究AOP技術(shù)的基本術(shù)語。
3、代理模式
說到代理模式,我們就需要說到下面兩點(diǎn):
3.1、靜態(tài)代理
這里就不寫靜態(tài)代理的代碼了。自己百度去看,主要的是以下3個(gè)點(diǎn):
3.2、動態(tài)代理
需要做的事情就5步:
3.2.1、創(chuàng)建UserService接口
package com.csa.service; public interface UserService {public void addUser();public void updateUser();public void deleteUser(); }3.2.2、創(chuàng)建UserServiceImp類
package com.csa.service.Imp; import com.csa.service.UserService; public class UserServiceImp implements UserService{@Overridepublic void addUser() {// TODO Auto-generated method stubSystem.out.println("add User to ...");}@Overridepublic void updateUser() {// TODO Auto-generated method stubSystem.out.println("update User to ...");}@Overridepublic void deleteUser() {// TODO Auto-generated method stubSystem.out.println("delete User to ...");}}3.2.3、創(chuàng)建MyAspect方面類
package com.csa.aspect; public class MyAspect {public void before(){System.out.println("之前");}public void after(){System.out.println("之后");} }3.2.4、動態(tài)代理UserService的工具類
動態(tài)代理步驟:
想了解更多的可以看這篇代理模式深入理解
package com.csa.factory; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import com.csa.aspect.MyAspect; import com.csa.service.UserService; import com.csa.service.Imp.UserServiceImp; public class MyBeanFactory {public static UserService createService() {// 1. 目標(biāo)類UserService userService = new UserServiceImp();// 2. 切面類MyAspect myAspect = new MyAspect();// 3. 代理類UserService proxyService = (UserService) Proxy.newProxyInstance(MyBeanFactory.class.getClassLoader(),userService.getClass().getInterfaces(), new InvocationHandler() {public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// TODO Auto-generated method stubmyAspect.before();Object obj = method.invoke(userService,args);myAspect.after();return obj;}});return proxyService;} }3.2.5、測試
package com.csa.Test; import org.junit.Test; import com.csa.factory.MyBeanFactory; import com.csa.service.UserService; public class TestJDK {@Testpublic void demo(){UserService userService = MyBeanFactory.createService();userService.addUser();userService.updateUser();userService.deleteUser();}}測試結(jié)果:
4、cglib代理
分6步完成:
4.1、導(dǎo)jar包
spring各個(gè)版本官方下載地址
4.2、創(chuàng)建接口
(與上面動態(tài)代理的一樣)
4.3、創(chuàng)建實(shí)現(xiàn)類
(與上面動態(tài)代理的一樣)
4.4、創(chuàng)建方面類
(與上面動態(tài)代理的一樣)
4.5、用cglib的工具類來生成目標(biāo)類
package com.csa.factory;import java.lang.reflect.Method;import org.springframework.cglib.proxy.Enhancer; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy;import com.csa.aspect.MyAspect; import com.csa.service.UserService; import com.csa.service.Imp.UserServiceImp;public class MyBeanFactory {public static UserService createService() {// 1. 目標(biāo)類UserService userService = new UserServiceImp();// 2. 切面類MyAspect myAspect = new MyAspect();// 3. 代理類// 3.1 核心類Enhancer enhancer = new Enhancer();// 3.2 確定父類enhancer.setSuperclass(userService.getClass());// 3.3 設(shè)置回調(diào)函數(shù)enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object proxy, Method method, Object[] args,MethodProxy methodProxy) throws Throwable {// TODO Auto-generated method stubmyAspect.before();Object obj = method.invoke(userService, args);myAspect.after();return obj;}});UserServiceImp proxyService = (UserServiceImp) enhancer.create();return proxyService;} }4.6、測試
package com.csa.Test; import org.junit.Test; import com.csa.factory.MyBeanFactory; import com.csa.service.UserService; public class TestCGLIB {@Testpublic void demo(){UserService userService = MyBeanFactory.createService();userService.addUser();userService.updateUser();userService.deleteUser();}}測試結(jié)果:
5、使用spring.xml配置實(shí)現(xiàn)動態(tài)代理
分下面6個(gè)步驟:
5.1、導(dǎo)jar包
Spring下載地址
commons logging下載地址
aopalliance下載地址
最后導(dǎo)入的包是如下(簡稱為:4+1、aop聯(lián)盟):
5.2、創(chuàng)建接口
(與動態(tài)代理的一樣)
5.3、創(chuàng)建目標(biāo)類
(與動態(tài)代理的一樣)
5.4、創(chuàng)建方面類
需要做兩件事:
所有的接口:
5.5、配置spring.xml
注意,我的spring.xml在src的config包下:
spring.xml配置代碼:
5.6、測試
package com.csa.Test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.service.UserService;public class TestAOP {@Testpublic void demo(){String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserService userService = (UserService) applicationContext.getBean("proxyServiceId");userService.addUser();userService.updateUser();userService.deleteUser();}}測試結(jié)果:
6、使用spring.xml實(shí)現(xiàn)AOP編程
下面的幾個(gè)步驟:
6.1、在上面一個(gè)例子的基礎(chǔ)上加一個(gè)包
AspectJ Weaver包下載地址
最后的包是:
6.2、創(chuàng)建接口
(與動態(tài)代理的一樣)
6.3、創(chuàng)建實(shí)現(xiàn)類
(與動態(tài)代理的一樣)
6.4、創(chuàng)建方面類
(與上一個(gè)例子的一樣)
6.5、配置spring.xml
表達(dá)式簡書
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 1. 目標(biāo)類 --><bean id="userServiceId" class="com.csa.service.Imp.UserServiceImp"></bean><!-- 2. 切面類 --><bean id="myAspectId" class="com.csa.aspect.MyAspect"></bean><!-- 3. aop編程 --><!-- 簡單來說呢,就是連接點(diǎn):是"所有需要增加某一個(gè)特定功能的方法集合"織入:就是將某個(gè)有特定處理功能的類,加到"連接點(diǎn)"!--><aop:config proxy-target-class="true"><!-- 這里涉及得到一個(gè)表達(dá)式的問題,我給個(gè)超鏈接,自己看吧 --><!-- 下面是一個(gè)連接點(diǎn),這里的表達(dá)式就是為了告訴spring,哪些方法需要被加以處理! --><aop:pointcut expression="execution(* com.csa.service..*(..))" id="myPointcut"/><!-- 下面就是我們的切面類,切面類會被"織入"到連接點(diǎn) --><aop:advisor advice-ref="myAspectId" pointcut-ref="myPointcut"/></aop:config></beans>6.6、測試
package com.csa.Test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext;import com.csa.service.UserService;public class TestAOP {@Testpublic void demo(){String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserService userService = (UserService) applicationContext.getBean("userServiceId");userService.addUser();userService.updateUser();userService.deleteUser();}}測試結(jié)果:
7、使用AspectJ配置spring.xml實(shí)現(xiàn)AOP編程
分6步:
7.1、導(dǎo)包
在上一個(gè)例子的基礎(chǔ)上導(dǎo)入下面這個(gè)包!在spring的壓縮包下可以找到!
7.2、創(chuàng)建接口
不變
7.3、創(chuàng)建實(shí)現(xiàn)類
要加一個(gè)除零異常
package com.csa.service.Imp; import com.csa.service.UserService; public class UserServiceImp implements UserService {@Overridepublic void addUser() {System.out.println("addUser to ...");}@Overridepublic void updateUser() {int i = 1/0;System.out.println("updateUser to ...");}@Overridepublic void deleteUser() {System.out.println("deleteUser to ...");}}7.4、創(chuàng)建MyAspect類
以下是所有AOP的通知了!
package com.csa.aspect; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; public class MyAspect {/*** 前置* * @param joinPoint* 連接點(diǎn)*/public void myBefore(JoinPoint joinPoint) {System.out.println("前置通知: " + joinPoint.getSignature().getName());}/*** 后置* * @param joinPoint* 連接點(diǎn)*/public void myAfter(JoinPoint joinPoint) {System.out.println("后置通知: " + joinPoint.getSignature().getName());}/*** 環(huán)繞通知* * @param proceedingJoinPoint* 連接點(diǎn)* @return 返回被代理方法的具體返回值* @throws Throwable* proceedingJoinPoint.proceed()方法執(zhí)行拋出的異常*/public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("前:" + proceedingJoinPoint.getSignature().getName());Object obj = proceedingJoinPoint.proceed();System.out.println("后:" + proceedingJoinPoint.getSignature().getName());return obj;}/*** 異常通知* * @param joinPoint* 連接點(diǎn)* @param e* 被代理方法執(zhí)行出現(xiàn)異常*/public void myThrowing(JoinPoint joinPoint, Throwable e) {System.out.println("異常通知:" + joinPoint.getSignature().getName() + "\r\n異常類型:" + e.getMessage());}/*** 后置通知* * @param joinPoint* 連接點(diǎn)* @param ret被代理方法的具體返回值*/public void myReturning(JoinPoint joinPoint, Object ret) {System.out.println("后置通知:" + joinPoint.getSignature().getName() + "\r\n返回值:" + ret);}}7.5、編寫spring.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 目標(biāo)類 --><bean id="userServiceId" class="com.csa.service.Imp.UserServiceImp"></bean><!-- 切面類 --><bean id="myAspectId" class="com.csa.aspect.MyAspect"></bean><aop:config><!-- 注意是在這個(gè)標(biāo)簽下,直接引用了某個(gè)切面類 --><aop:aspect ref="myAspectId"><!-- 在這個(gè)標(biāo)簽的體中間寫"通知"和"被通知的方法集合" --><!-- 連接點(diǎn)--><aop:pointcut expression="execution(* com.csa.service..*(..) )" id="myPointcut"/><!-- 前置通知<aop:before method="myBefore" pointcut-ref="myPointcut"/>--><!-- 后置通知<aop:after method="myAfter" pointcut-ref="myPointcut"/>--><!-- 環(huán)繞通知<aop:around method="myAround" pointcut-ref="myPointcut"/>--><!--異常通知--><aop:after-throwing method="myThrowing" pointcut-ref="myPointcut" throwing="e"/><!--后置通知<aop:after-returning method="myReturning" pointcut-ref="myPointcut" returning="ret"/>--><!-- jdk1.8 最好別使用 spring3.*.*系列 --></aop:aspect></aop:config> </beans>7.6、測試
package com.csa.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.service.UserService; public class TestAspectJ {@Testpublic void demo() {String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserService userService = (UserService) applicationContext.getBean("userServiceId");userService.addUser();userService.updateUser();userService.deleteUser();} }測試結(jié)果:
8、使用注解的AspectJ
分6個(gè)步驟:
8.1、導(dǎo)包
與上一個(gè)例子的包一樣,沒有改變!
8.2、創(chuàng)建接口
沒變
8.3、創(chuàng)建實(shí)現(xiàn)類
與上一個(gè)AspectJ的例子一樣!
8.4、創(chuàng)建MyAcpect
package com.csa.aspect;import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component;@Component @Aspect public class MyAspect {/*** 連接點(diǎn)*/@Pointcut(value="execution(* com.csa.service..*(..) )")private void myPointcut() {}/*** 前置* * @param joinPoint* 連接點(diǎn)*/@Before(value="myPointcut()")public void myBefore(JoinPoint joinPoint) {System.out.println("前置通知: " + joinPoint.getSignature().getName());}/*** 后置* * @param joinPoint* 連接點(diǎn)*/@After(value="myPointcut()")public void myAfter(JoinPoint joinPoint) {System.out.println("后置通知: " + joinPoint.getSignature().getName());}/*** 環(huán)繞通知* * @param proceedingJoinPoint* 連接點(diǎn)* @return 返回被代理方法的具體返回值* @throws Throwable* proceedingJoinPoint.proceed()方法執(zhí)行拋出的異常*/@Around(value="myPointcut()")public Object myAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {System.out.println("前:" + proceedingJoinPoint.getSignature().getName());Object obj = proceedingJoinPoint.proceed();System.out.println("后:" + proceedingJoinPoint.getSignature().getName());return obj;}/*** 異常通知* * @param joinPoint* 連接點(diǎn)* @param e* 被代理方法執(zhí)行出現(xiàn)異常*/@AfterThrowing(value="myPointcut()",throwing="e")public void myThrowing(JoinPoint joinPoint, Throwable e) {System.out.println("異常通知:" + joinPoint.getSignature().getName() + "\r\n異常類型:" + e.getMessage());}/*** 后置通知* * @param joinPoint* 連接點(diǎn)* @param ret被代理方法的具體返回值*/@AfterReturning(value="myPointcut()",returning="ret")public void myReturning(JoinPoint joinPoint, Object ret) {System.out.println("后置通知:" + joinPoint.getSignature().getName() + "\r\n返回值:" + ret);}}8.5、編寫spring.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"><!-- 掃描 注解類 --><context:component-scan base-package="com.csa"></context:component-scan><!-- 確定 aop注解生效 --><aop:aspectj-autoproxy ></aop:aspectj-autoproxy></beans>8.6、測試
package com.csa.test; import org.junit.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.csa.service.UserService; public class TestAspectJ {@Testpublic void demo() {String xmlPath = "config/spring.xml";ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);UserService userService = (UserService) applicationContext.getBean("userServiceId");userService.addUser();userService.updateUser();userService.deleteUser();} }測試結(jié)果:
總結(jié)
以上是生活随笔為你收集整理的Spring学习总结二的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 2020年中国住宿业市场网络口碑报告
- 下一篇: Spring学习总结三