第七章: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();
}
}
