第七章:AOP技術
前言:
AOP技術是根據動態代理設計模式進行的技術。動態代理技術分jdk動態代理和cglib動態代理
jdk動態代理特點:
(1)繼承java.lang.reflect.proxy類
(2)實現了真實類實現的接口
(3)真實類和代理類之間的關系是:他們都實現了相同的接口
cglib動態代理特點:
特點:
(1)代理類是真實類的子類
注:本片文章主要理解AOP編程,至於動態代理技術不做過多介紹,有需要的話,可以留言,下篇文章可以進行講解。
7.1:AOP原理概述
AOP:Aspect Oriented Programming,面向切面編程
傳統形式,web項目執行流程:
缺點:
(1)Bad Smell現象,指一些代碼邏輯出現了在了不合適的層次。
例如:在service層有數據庫的事務處理代碼,不合乎規范
改進:
AOP編程:
本質上,屬於動態代理設計模式
切面編程:類似於在鏈式程序指定流程中,在service層處進行截斷,此處的斷層成為切面,此處的service處的程序運行為豎向,可以看作service層的強化操作。
概念:
(1)Point(切點):表示要對哪個方法進行增強
(2)Advice(通知):表示額外增加的功能
(3)Aspect(切面):就是代理對象,(切面+切點)
(4)Weaving(織入):將通知添加到切點中的操作,生成動態代理的過程
7.2:AOP實現過程
7.2.1:導包
1. 日志包:
commons-logging.jar
2. Spring核心包:
spring-core.jar
spring-beans.jar
spring-context.jar
spring-expression.jar
3. aop依賴的jar包:
spring-aop.jar
aopalliance.jar -aop聯盟提供的對aop的具體實現
7.2.2:測試用的service代碼
spring支持兩種動態代理的實現:
(1)如果提供了接口,就用jdk動態代理
(2)如果沒有提供接口,就用cglib動態代理
7.2.3:提供通知
spring中的通知類型:
(1)前置通知:在切點方法調用前操作,MethodBeforeAdvice
(2)后置操作:在切點方法掉用后操作,AfterReturningAdvice
(3)異常通知:在切點方法執行發生異常時執行,ThrowsAdvice
(4)環繞通知:包含了前置通知、后置通知和異常通知,MethodInterceptor
public class DemoBeforeAdvice implements MethodBeforeAdvice { @Override public void before(Method method, Object[] objects, Object o) throws Throwable { System.out.println("我是前置通知...."); } }
7.2.4:配置AOP(織入/動態代理)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--配置service對象--> <bean id="userService" class="com.bjsxt.service.impl.UserServiceImpl" /> <bean id="testService" class="com.bjsxt.service.TestService" /> <!--配置通知對象--> <bean id="demoBefore" class="com.bjsxt.advice.DemoBeforeAdvice" /> <!--配置織入, 生成動態代理--> <bean id="proxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <!--配置目標對象--> <property name="targetName" value="userService" /> <!--配置通知--> <property name="interceptorNames"> <array> <value>demoBefore</value> </array> </property> </bean> <bean id="testProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="targetName" value="testService" /> <property name="interceptorNames"> <array> <value>demoBefore</value> </array> </property> </bean> </beans>
7.2.5:測試代碼
public class TestAOP { @Test public void testAop2() { //cglib動態代理 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); TestService testProxy = context.getBean("testProxy", TestService.class); System.out.println(testProxy.getClass().getName()); System.out.println(testProxy.getClass().getSuperclass().getName()); testProxy.test(); } @Test public void testAop() { //jdk動態代理 ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserService userService = context.getBean("proxy", UserService.class); System.out.println(userService.getClass().getName()); userService.demo(); } }