Spring第三天筆記java
今日內容spring
(1) 代理模式- 動態代理express
① JDK的動態代理 (Java官方)編程
② CGLIB 第三方代理設計模式
(2) AOP思想在Spring中的具體體現(AOP底層使用的就是動態代理)數組
AOP爲Aspect Oriented Programming的縮寫, 意爲:面向切面編程, 經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術. AOP是OOP的延續, 是函數式編程的一種衍生範型. 利用AOP能夠對業務邏輯的各個部分進行隔離, 從而使得業務邏輯各部分之間的耦合度下降, 提升程序的可重用性, 同時提升了開發的效率. -解耦session
|
|
|
做用:app
在程序運行期間,不修改任何相關源碼對已有方法進行加強。框架
優點:ide
減小重複代碼、提升開發效率、維護方便
使用動態代理模式來實現
可能經過上面的介紹,咱們仍是沒有一個清晰的認識。不要緊,咱們看看下面的具體應用。
經過下面的實現代碼,咱們能看出什麼問題嗎?
public class TransactionManagerHandler { public void begin() { System.out.println("開啓事務"); }
public void commit() { System.out.println("提交事務"); }
public void rollback() { System.out.println("回滾事務"); }
public void close() { System.out.println("關閉session"); } } |
public class UserServiceImpl implements UserService { // 引入事務管理器 private TransactionManagerHandler txManager = new TransactionManagerHandler();
@Override public void insert(String username) { try { txManager.begin(); System.out.println("調用dao層插入方法"); txManager.commit(); } catch (Exception e) { txManager.rollback(); } finally { txManager.close(); } }
@Override public void update(String username) { try { txManager.begin(); System.out.println("調用dao層修改方法"); txManager.commit(); } catch (Exception e) { txManager.rollback(); } finally { txManager.close(); } } } |
上面代碼的問題就是:咱們的事務控制的代碼是重複性的。這還只是一個業務類,若是有多個業務了,每一個業務類中都會有這些重複性的代碼。是否是重複代碼太多了?
思考:咱們有什麼辦法解決這個問題嗎?
Java中的動態代理,就是使用者使用的不是真實的對象,而是使用的一個代理對象,而這個代理對象中包含的就是真實的對象,代理對象就是不改變原有對象的功能方法的基礎之上封裝新的功能
JDK動態代理是Java官方的代理
使用JDK官方的Proxy類建立代理對象
1、java.lang.reflect.Proxy 類: Java 動態代理機制生成的全部動態代理類的父類,它提供了一組靜態方法來爲一組接口動態地生成代理類及其對象。 主要方法: public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler hanlder) 方法職責:爲指定類加載器、一組接口及調用處理器生成動態代理類實例 參數: loader :類加載器 interfaces : 模擬的接口 hanlder :代理執行處理器
返回:動態生成的代理對象 |
2、java.lang.reflect.InvocationHandler接口: public Object invoke(Object proxy, Method method, Object[] args) 方法職責:負責集中處理動態代理類上的全部方法調用 參數: proxy :生成的代理對象 method :當前調用的真實方法對象 args :當前調用方法的實參
返回: 真實方法的返回結果 ------------------------------------------------------------------------------------ njdk動態代理操做步驟 ① 實現InvocationHandler接口,建立本身加強代碼的處理器。 ② 給Proxy類提供ClassLoader對象和代理接口類型數組,建立動態代理對象。 ③ 在處理器中實現加強操做。 |
在咱們的UserServiceImpl的實現類中,使用JDK的動態代理,進行方法的加強,加強事物的功能
JDK動態代理類 |
public class DynamicProxyHandler { //被代理的對象 private Object target; //事務管理器 private TransactionManagerHandler txManager; /** * 返回一個代理對象,代理對象就作了方法的加強,(事物管理,日誌控制,權限管理等等) */ public <T> T getProxyObject(Class<T> clz) {
/* * JDK內置有一個代理類,專門負責建立動態代理對象的,類 * Proxy 類 , Proxy爲被代理的對象建立代理對象 * 理論上建立被代理對象,是須要被代理對象的類對應的字節碼的 * Proxy 在JVM動態的建立被代理對象的字節碼,冬天的建立代理對象 */
/* * loader: 類加載器,類加載器就是從當前classpath下面加載字節碼,在整個應用有且只有一個類加載器 * 如何或者類加載器, * 方式一: 使用當前線程 * ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); * 方式二: 使用任何一個類的字節碼 * target.getClass().getClassLoader() * interfaces : 被代理對象的接口 * h : 處理器: 真正作代碼加強的地方 */ //代理對象 Object newProxyInstance = Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() { /** * 代理內的加強方法,正常加強的地方 * @param proxy 代理對象 * @param method 被代理對象的方法 * @param args 被代理對象方法的參數 * @return 被代理對象執行的結果 * @throws Throwable */
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //執行被代理對象的方法 Object result = null; try { //方法以前執行操做 //開始事務 txManager.begin(); result = method.invoke(target, args); //方法以後執行操做 //提交事物 txManager.commit(); } catch (Exception e) { //回滾事物 txManager.rollback(); }finally { txManager.close(); } return result; } });
//返回代理對象 return (T) newProxyInstance; }
public void setTarget(Object target) { this.target = target; }
public void setTxManager(TransactionManagerHandler txManager) { this.txManager = txManager; } } |
配置文件 |
<!-- 配置事物管理器 --> <bean id="txMananger" class="cn.zj.spring.TransactionManagerHandler"/>
<!-- 配置動態代理類 --> <bean id="dynamicProxy" class="cn.zj.spring.proxy.DynamicProxyHandler"> <!-- 注入事物管理器 --> <property name="txManager" ref="txMananger"/>
<!-- 配置被代理對象 --> <property name="target"> <bean class="cn.zj.spring.service.impl.UserServiceImpl"/> </property> </bean> |
測試代碼 |
@RunWith(SpringJUnit4ClassRunner.class) // 表示先啓動Spring容器,把junit運行在Spring容器中 @ContextConfiguration("classpath:applicationContext.xml") // 讀取Spring的配置文件 public class DynamicProxyTest { // 自動注入 UserService @Autowired private DynamicProxyHandler proxy;
@Test public void testInsert() throws Exception {
// 獲取代理類對象的中的獲取動態代理對象的方法 UserService proxyObject = proxy.getProxyObject(UserServiceImpl.class); proxyObject.insert("張三"); } @Test public void testUpdate() throws Exception { // 獲取代理類對象的中的獲取動態代理對象的方法 UserService proxyObject = proxy.getProxyObject(UserServiceImpl.class); proxyObject.update("李四"); } } |
1,JDK動態代理的對象必需要實現一個接口;
2,須要爲每一個對象建立代理對象;
3,動態代理的最小單位是類(全部類中的方法都會被處理),查詢方法不須要事務,可能不須要被代理
CGLIB(Code Generation Library)是一個開源項目
CGLIB和JDK動態代理同樣都是動態代理,可是CGLIB代理沒有接口能夠進行代理
Spring默認已經集成CGLIB代理,直接可使用便可,不用拷貝任何jar包
|
在咱們的UserServiceImpl的實現類中,使用CGLIB的動態代理,進行方法的加強,加強事物的功能
CGLIB代理類 |
public class CglibProxyHandler { //被代理的對象 private Object target; //事務管理器 private TransactionManagerHandler txManager; /** * 返回一個代理對象,代理對象就作了方法的加強,(事物管理,日誌控制,權限管理等等) * @return */ public <T> T getProxyObject(Class<T> clz) {
//使用CGLIB代理,CGLIB代理 能夠沒有接口,直接使用類代理
//建立Enhancer CGLIB代理鍍錫 Enhancer enhancer = new Enhancer(); //設置類加載器 enhancer.setClassLoader(this.getClass().getClassLoader()); //設置被代理對象字節碼 enhancer.setSuperclass(target.getClass());
//代理的具體實現 enhancer.setCallback(new org.springframework.cglib.proxy.InvocationHandler() {
/** * 代理內的加強方法,正常加強的地方 * @param proxy 代理對象 * @param method 被代理對象的方法 * @param args 被代理對象方法的參數 * @return 被代理對象執行的結果 * @throws Throwable */
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //執行被代理對象的方法 Object result = null; try { //方法以前執行操做 //開始事務 txManager.begin(); result = method.invoke(target, args); //方法以後執行操做 //提交事物 txManager.commit(); } catch (Exception e) { //回滾事物 txManager.rollback(); }finally { txManager.close(); } return result; } });
//建立代理對象 Object proxy = enhancer.create();
//返回代理對象 return (T) proxy; } public void setTarget(Object target) { this.target = target; }
public void setTxManager(TransactionManagerHandler txManager) { this.txManager = txManager; } } |
配置文件 |
<!-- 配置事務管理器 --> <bean id="txMananger" class="cn.zj.spring.TransactionManagerHandler"/>
<!-- 配置CGLIB代理類 --> <bean id="dynamicProxy" class="cn.zj.spring.cglib.CglibProxyHandler"> <!-- 注入事務管理器 --> <property name="txManager" ref="txMananger"/>
<!-- 配置被代理對象 --> <property name="target"> <bean class="cn.zj.spring.service.impl.UserServiceImpl"/> </property> </bean> |
測試代碼 |
@RunWith(SpringJUnit4ClassRunner.class) // 表示先啓動Spring容器,把junit運行在Spring容器中 @ContextConfiguration("classpath:applicationContext.xml") // 讀取Spring的配置文件 public class DynamicProxyTest { // 自動注入 UserService @Autowired private DynamicProxyHandler proxy; @Test public void testInsert() throws Exception { // 獲取代理類對象的中的獲取動態代理對象的方法 UserService proxyObject = proxy.getProxyObject(UserServiceImpl.class); proxyObject.insert("張三"); } @Test public void testUpdate() throws Exception { // 獲取代理類對象的中的獲取動態代理對象的方法 UserService proxyObject = proxy.getProxyObject(UserServiceImpl.class); proxyObject.update("李四"); } } |
1,CGLIB能夠生成目標類的子類,並重寫父類非final修飾符的方法。
2,要求類不能是final的,要代理的方法要是非final、非static、非private的。
3,動態代理的最小單位是類(全部類中的方法都會被處理);
在Spring中:
若目標對象實現了若干接口,Spring就會使用JDK動態代理。
若目標對象沒有實現任何接口,Spring就使用CGLIB庫生成目標對象的子類。
動態代理模式的缺陷是:
如何解決這個問題:Spring提供了AOP的實現。
Spring經過動態代理模式的實現後,咱們能夠定義AOP其實就是用於經過規則設置來攔截方法,加入能夠統一處理的代碼。
在spring中,框架會根據目標類是否實現了接口來決定採用哪一種動態代理的方式。
Joinpoint(鏈接點):
所謂鏈接點是指那些被攔截到的點。在spring中,這些點指的是方法,由於spring只支持方法類型的鏈接點。
---就是根據規則,能夠指定攔截的方法,咱們將每個被攔截的方法稱爲鏈接點。
Pointcut(切入點):
--所謂的切入點,就是攔截方法設置的規則
所謂切入點是指咱們要對哪些Joinpoint進行攔截的定義。
Advice(通知/加強):
--就是能夠設置在方法以前攔截或者方法執行以後攔截或者方法出異常後攔截,或者方法以前和以後都攔截。咱們將這些攔截場景稱爲通知
所謂通知是指攔截到Joinpoint以後所要作的事情就是通知。
通知的類型:前置通知,後置通知,異常通知,最終通知,環繞通知。
Aspect(切面):
--所謂的切面就是咱們的攔截處理類。
是切入點和通知的結合。
Weaving(織入):
-把切面加入到對象,並建立出代理對象的過程。(該過程由Spring來完成)
經過XML的方式配置AOP
需求:編寫一個切面類,在執行insert,update方法,分別在方法執行前、方法以後、異常出現後、分別方法執行先後調用編寫統一處理的代碼,
建立一個Java項目,加入Spring框架的基礎支持包
|
package cn.zj.spring.service;
import cn.zj.spring.pojo.User;
public interface UserService { void insert(User user); void update(User user); }
|
package cn.zj.spring.service.impl;
import cn.zj.spring.pojo.User; import cn.zj.spring.service.UserService;
public class UserServiceImpl implements UserService{
public void insert(User user) { System.out.println("---調用DAO層保存方法---"); } public void update(User user) { System.out.println("---調用DAO層修改方法---"); } }
|
引入aop的命名空間
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- 配置UserService層 --> <bean id="userService" class="cn.zj.spring.service.impl.UserServiceImpl"/> </beans> |
package cn.zj.spring.test;
import javax.annotation.Resource;
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.zj.spring.pojo.User; import cn.zj.spring.service.impl.UserServiceImpl;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class UserServiceTest {
@Resource private UserServiceImpl service;
@Test public void testSave() { User user = new User(null, "張三", "zhangsan@qq.com"); service.insert(user); }
@Test public void testUpdate() { User user = new User(1, "李四", "lisi@qq.com"); service.update(user); } }
|
AOP 思想必須使用AspectJ語法,而AOP思想不是Spring框架設計出來的,而是叫一個AOP聯盟組織提出這種思想,因此開發者須要導入 AOP聯盟提供的 aspectjweaver.jar(aspectweaver織入包)
|
package cn.zj.spring;
import java.util.Arrays;
import org.aspectj.lang.JoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
public class TransactionManagerHandler {
/** * 環繞加強的方法 * * @param pjp ProceedingJoinPoint 鏈接點 ProceedingJoinPoint 鏈接點 * */ public void allInOne(ProceedingJoinPoint pjp) { try { begin(pjp); // 執行方法 pjp.proceed(); //此方法在環繞方法中能夠調用正在的業務方法
System.out.println("提交事務");
} catch (Throwable e) { System.out.println("回滾事務 :" + e.getMessage()); } finally { System.out.println("關閉session"); } }
// JoinPoint : 鏈接點, 獲取被代理對象的相關信息 public void begin(JoinPoint jp) { // 獲取被代理對象的類型 Class<?> clz = jp.getTarget().getClass(); System.out.println(clz); // 獲取被代理對象執行方法對應的參數 Object[] args = jp.getArgs(); System.out.println(Arrays.toString(args)); System.out.println("開啓事務"); }
public void begin() { System.out.println("開啓事務"); }
public void commit() { System.out.println("提交事務"); }
/* * public void rollback() { System.out.println("回滾事務"); } */
public void rollback(Throwable e) {
System.out.println("回滾事務 : " + e.getMessage()); }
public void close() { System.out.println("關閉session"); } } |
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd ">
<!-- 配置UserService層 --> <bean id="userService" class="cn.zj.spring.service.impl.UserServiceImpl"/>
<!-- 配置事物管理器 --> <bean id="txMananger" class="cn.zj.spring.TransactionManagerHandler"/>
<!-- AOP 相關配置: W (where)W(when)W(what) 原則 -->
<!-- 配置切入點: where --> <aop:config> <!-- 作什麼(what:加強的功能) --> <aop:aspect ref="txMananger"> <!-- 切入點(Pointcut):在哪些類,哪些方法上切入(where); --> <aop:pointcut expression="execution( * cn.zj.spring.service..*.*(..))" id="pt"/>
<!-- 加強(Advice):早期翻譯爲通知,在方法執行的什麼時機(when:方法前/方法後/方法先後) 前置加強 : method : 須要加強的方法 --> <aop:before method="begin" pointcut-ref="pt"/>
<aop:after-returning method="commit" pointcut-ref="pt"/><!-- 後置加強 -->
<!-- 異常加強 : 拋出的異是常異常頂級類Throwable throwing : 是異常增城方法,參數的名稱: 必須和參數一致 --> <aop:after-throwing throwing="e" method="rollback" pointcut-ref="pt"/><!-- 異常加強 -->
<aop:after method="close" pointcut-ref="pt"/><!-- 最終加強 -->
<!-- 環繞加強: 將多個增長集中到一塊兒了 --> <!-- <aop:around method="allInOne" pointcut-ref="pt"/> -->
</aop:aspect> <!-- 織入(Weaving):把切面加入到對象,並建立出代理對象的過程。(該過程由Spring來完成)。 --> </aop:config> </beans> |
execution:
匹配方法的執行(經常使用) execution(表達式) 表達式語法:execution([修飾符] 返回值類型 包名.類名.方法名(參數)) 寫法說明: 全匹配方式: public void cn.zj.service.impl.CustomerServiceImpl.saveCustomer() 訪問修飾符能夠省略 void com.zj.service.impl.CustomerServiceImpl.saveCustomer() 返回值可使用*號,表示任意返回值 * com.zj.service.impl.CustomerServiceImpl.saveCustomer() 包名可使用*號,表示任意包,可是有幾級包,須要寫幾個* * *.*.*.*.CustomerServiceImpl.saveCustomer() 使用..來表示當前包,及其子包 * com..CustomerServiceImpl.saveCustomer() 類名可使用*號,表示任意類 * com..*.saveCustomer() 方法名可使用*號,表示任意方法 * com..*.*() 參數列表可使用*,表示參數能夠是任意數據類型,可是必須有參數 * com..*.*(*) 參數列表可使用..表示有無參數都可,有參數能夠是任意類型 * com..*.*(..) 全通配方式: * *..*.*(..) |
做用:
用於聲明開始aop的配置
做用:
用於配置切面。
屬性:
id:給切面提供一個惟一標識。
ref:引用配置好的通知類bean的id。
做用:
用於配置切入點表達式
屬性:
expression:用於定義切入點表達式。
id:用於給切入點表達式提供一個惟一標識。
做用:
用於配置前置通知
屬性:
method:指定通知中方法的名稱。
pointct:定義切入點表達式
pointcut-ref:指定切入點表達式的引用
做用:
用於配置後置通知,若是出了異常就必定不會調用切面的方法
屬性:
method:指定通知中方法的名稱。
pointct:定義切入點表達式
pointcut-ref:指定切入點表達式的引用
做用:
用於配置異常通知,只有出了異常纔會調用切面對應的方法
屬性:
method:指定通知中方法的名稱。
pointct:定義切入點表達式
pointcut-ref:指定切入點表達式的引用
做用:
用於配置最終通知,無論出不出異常,調用的切面的方法
屬性:
method:指定通知中方法的名稱。
pointct:定義切入點表達式
pointcut-ref:指定切入點表達式的引用
做用:
用於配置環繞通知
屬性:
method:指定通知中方法的名稱。
pointct:定義切入點表達式
pointcut-ref:指定切入點表達式的引用
建立一個Java項目,加入Spring框架的基礎支持包
|
package cn.zj.spring.service;
import cn.zj.spring.pojo.User;
public interface UserService { void insert(User user); void update(User user); }
|
package cn.zj.spring.service.impl;
import cn.zj.spring.pojo.User; import cn.zj.spring.service.UserService;
public class UserServiceImpl implements UserService{
public void insert(User user) { System.out.println("---調用DAO層保存方法---"); } public void update(User user) { System.out.println("---調用DAO層修改方法---"); } }
|
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- 配置UserService層 --> <bean id="userService" class="cn.zj.spring.service.impl.UserServiceImpl"/> </beans> |
package cn.zj.spring.test;
import javax.annotation.Resource;
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import cn.zj.spring.pojo.User; import cn.zj.spring.service.impl.UserServiceImpl;
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath:applicationContext.xml") public class UserServiceTest {
@Resource private UserServiceImpl service;
@Test public void testSave() { User user = new User(null, "張三", "zhangsan@qq.com"); service.insert(user); }
@Test public void testUpdate() { User user = new User(1, "李四", "lisi@qq.com"); service.update(user); } }
|
--注意:必需要導入加入支持AOP的包。
Spring的AOP包基於AspectJ框架,因此必須加入AspectJ-->aspectjweaver.jar
|
package cn.zj.spring;
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 //在此類中可使用註解進行aop的相關配置 <aop:aspect> public class TransactionManagerHandler {
//<aop:pointcut expression="execution( * cn.zj.spring.service..*.*(..))" id="當前方法名就是id"/> @Pointcut("execution( * cn.zj.spring.service..*.*(..))") public void pointcut() {}
@Before("pointcut()") //<aop:before method="begin" pointcut-ref="pt"/> public void begin() { System.out.println("開啓事務"); }
@AfterReturning("pointcut()")//<aop:after-returning method="commit" pointcut-ref="pt"/> public void commit() { System.out.println("提交事務"); }
//<aop:after-throwing throwing="e" method="rollback" pointcut-ref="pt"/> @AfterThrowing(pointcut="pointcut()",throwing="ex") public void rollback(Throwable ex) { System.out.println("註解的回滾事務 : " + ex.getMessage()); }
@After("pointcut()")//<aop:after method="close" pointcut-ref="pt"/> public void close() { System.out.println("關閉session"); }
//環繞加強 @Around("pointcut()") //<aop:around method="allInOne" pointcut-ref="pt"/> public Object allInOne(ProceedingJoinPoint pjp) { Object result = null; try { System.out.println("開啓事務------"); //執行被代理對象當前須要執行業務方法 result = pjp.proceed(); System.out.println("提交事務------"); } catch (Throwable ex) { System.out.println("------回滾事務 : " + ex.getMessage()); }finally { System.out.println("關閉session------"); } return result; } }
|
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:p="http://www.springframework.org/schema/p" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- 配置spring的包掃描 --> <context:component-scan base-package="cn.zj.spring"/> <!-- 使用註解配置AOP配置配置自動注入AOP --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans> |
做用:
把當前類聲明爲切面類。
做用:
把當前方法當作是前置通知。
屬性:
value:用於指定切入點表達式,還能夠指定切入點表達式的引用。
做用:
把當前方法當作是後置通知。報異常,就不執行
屬性:
value:用於指定切入點表達式,還能夠指定切入點表達式的引用。
做用:
把當前方法當作是異常通知。只有報異常才執行
屬性:
value:用於指定切入點表達式,還能夠指定切入點表達式的引用。
做用:
把當前方法當作是最終通知。無論報不報異常都執行
屬性:
value:用於指定切入點表達式,還能夠指定切入點表達式的引用。
做用:
把當前方法當作是環繞通知。
屬性:
value:用於指定切入點表達式,還能夠指定切入點表達式的引用。
做用:
指定切入點表達式
屬性:
value:指定表達式的內容
今日內容
AOP 思想
(1) 目的: 減小重複代碼
(1) Java動態代理,不直接編寫類的代理類,在程序的運行過程當中,在JVM中動態的爲被代理的類建立一份新的字節碼,並使用這份新的字節碼建立對應的代理對象。
(2) JDK 動態代理
① 缺點:必須有接口代理,沒有接口不能代理
② 使用的 java.lang.reflect.Proxy 代理的靜態方法
1) Object obj = Proxy.newProxyInstance(類加載器,被代理數據類型的接口字節碼,處理器)
(3) CGLIB代理
① 便可有接口的類,又能夠沒有接口的類
1) 使用Enhancer 類建立代理對象
(1) Joinpoint 鏈接點(具體的方法)
(2) Pointcut 切入點 具體的某一類方法
(3) Advice 通知/加強 (具體要作的事情,如:事務處理)
(4) Aspect :切面 = 切入點(pointcut)+通知(advice)
(5) Weaving : 織入,將整個AOP的配置在運行階段組織在一塊兒,由Spring框架完成
(1) 引入相關的依賴包
(2) 引入命名空間(通俗講:xml約束配置)
(3) AOPxml標籤具體配置