- aspect before
- Aspect biz
- aspect afteThrowing
- 上邊的結果因爲拋出異常後,不會正常的返回全部沒有aspect afterReturning輸出
5.1.4最終通知after(finally) advice
無論方法是否會拋出異常都會通知,就像try...catch..finallly
配置文件:
spring-aop-schema-advice.xml
- <aop:config>
- <aop:aspect id="aspectTest" ref="myAspect">
-
- <aop:pointcut expression="execution(* com.xxx.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/>
-
- <aop:before method="before" pointcut-ref="myPointcut"/>
-
- <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
-
- <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/>
-
- <aop:after method="after" pointcut-ref="myPointcut"/>
- </aop:aspect>
- </aop:config>
切面類:
- public class MyAspect {
-
- public void before(){
- System.out.println("aspect before");
- }
-
- public void afterReturning(){
- System.out.println("aspect afterReturning");
- }
-
- public void afteThrowing(){
- System.out.println("aspect afteThrowing");
- }
-
- public void after(){
- System.out.println("aspect after(finally)");
- }
- }
業務類:
- //業務類
- public class AspectBiz {
-
- public void biz(){
- System.out.println("Aspect biz");
- throw new RuntimeException();
- }
- }
測試結果:
- aspect before
- Aspect biz
- aspect afteThrowing
- aspect after(finally)
從結果中能夠看出,拋出異常後,切面類中的after方法仍是能夠執行
- 若是業務類以下:沒有異常,
- public class AspectBiz {
- public void biz(){
- System.out.println("Aspect biz");
-
- }
-
- }
結果:
- aspect before
- Aspect biz
- aspect after(finally)
由以上結果能夠看到,無論怎麼樣after方法仍是會執行,很像try...catch..finally
5.1.5環繞通知around
在方法的執行先後執行通知
配置文件:
spring-aop-schema-advice.xml
- <aop:config>
- <aop:aspect id="aspectTest" ref="myAspect">
-
- <aop:pointcut expression="execution(* com.xxx.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/>
-
- <aop:before method="before" pointcut-ref="myPointcut"/>
-
- <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
-
- <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/>
-
- <aop:after method="after" pointcut-ref="myPointcut"/>
-
- <aop:around method="around" pointcut-ref="myPointcut"/>
- </aop:aspect>
- </aop:config>
切面類:
能夠看出,環繞方法的第一參數必須四ProceedingJoinPoint類型
- public class MyAspect {
-
- public void before(){
- System.out.println("aspect before");
- }
-
- public void afterReturning(){
- System.out.println("aspect afterReturning");
- }
-
- public void afteThrowing(){
- System.out.println("aspect afteThrowing");
- }
-
- public void after(){
- System.out.println("aspect after(finally)");
- }
-
- public void around(ProceedingJoinPoint joinPoint){
- Object object = null;
- try{
- System.out.println("aspect around 1");
- object = joinPoint.proceed();
- System.out.println("aspect around 1");
- }catch(Throwable e){
- e.printStackTrace();
- }
- }
- }
測試結果:
- aspect around 1
- Aspect biz
- aspect around 1
從結果能夠看出,joinPoint.proceed其實就是執行業務方法,咱們能夠在其以前作和以後作一些操做
5.1.6通知中的參數傳遞
這裏咱們列舉環繞通知中的參數參數傳遞,其餘通知也是一樣的方式。
配置文件:
spring-aop-schema-advice.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-3.2.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
-
-
- <bean id="myAspect" class="com.xxx.spring.aop.bean.annotation.aop.MyAspect"></bean>
-
-
- <bean id="aspectBiz" class="com.xxx.spring.aop.bean.annotation.aop.AspectBiz"></bean>
-
- <aop:config>
-
- <aop:aspect id="aspectTest" ref="myAspect">
-
- <aop:pointcut expression="execution(* com.xxx.spring.aop.bean.annotation.aop.*Biz.*(..))" id="myPointcut"/>
-
- <aop:before method="before" pointcut-ref="myPointcut"/>
-
- <aop:after-returning method="afterReturning" pointcut-ref="myPointcut"/>
-
- <aop:after-throwing method="afteThrowing" pointcut-ref="myPointcut"/>
-
- <aop:after method="after" pointcut-ref="myPointcut"/>
-
-
-
-
- <aop:around method="aroundInit" pointcut="execution(* com.xxx.spring.aop.bean.annotation.aop.AspectBiz.init(String,int))
- and args(bizName,times)"/>
- </aop:aspect>
- </aop:config>
- </beans>
其中,通知中也能夠單獨指定的pointcut,切入點中,咱們單獨指定了init方法,且指定了方法的參數類型,和方法參數的名字,其中方法參數名字,能夠更實際的方法參數名字不一樣,好比說init(String biz,int t) 都是能夠匹配到的,不過爲了維護方便,最好仍是都同樣。
切面類:
- public class MyAspect {
-
- public void before(){
- System.out.println("aspect before");
- }
-
- public void afterReturning(){
- System.out.println("aspect afterReturning");
- }
-
- public void afteThrowing(){
- System.out.println("aspect afteThrowing");
- }
-
- public void after(){
- System.out.println("aspect after(finally)");
- }
-
- public void around(ProceedingJoinPoint joinPoint){
- Object object = null;
- try{
- System.out.println("aspect around 1");
- object = joinPoint.proceed();
- System.out.println("aspect around 2");
- }catch(Throwable e){
- e.printStackTrace();
- }
- }
-
-
- public void aroundInit(ProceedingJoinPoint joinPoint,String bizName,int times){
- System.out.println(bizName+"--"+times);
- Object object = null;
- try{
- System.out.println("aspect around 1");
- object = joinPoint.proceed();
- System.out.println("aspect around 1");
- }catch(Throwable e){
- e.printStackTrace();
- }
- }
- }
業務類:
- public class AspectBiz {
-
- public void biz(){
- System.out.println("Aspect biz");
- }
-
- public void init(String bizName,int times){
- System.out.println("aspectBiz init:"+bizName+" "+times);
- }
-
- }
測試:
- @Test
- public void aspectAround(){
- ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext("com/xxx/spring/chap4/spring-aop-schema-advice.xml");
- AspectBiz aspectBiz = (AspectBiz) ac.getBean("aspectBiz");
- aspectBiz.init("init", 3);
- }
測試結果:
- aspect before
- init--3
- aspect around 1
- aspectBiz init:init 3
- aspect around 1
- aspect after(finally)
- aspect afterReturning
- AfterClass 標註的方法 會最後執行
能夠看到,參數比順利的傳送過去
6.Advisor
Advisor就像一個小的自包含,只有一個advice切面經過一個bean標識,而且必須實現一個advice接口,同時advisor也能夠很好的利用aspectJ的切入點表達式Spring經過配置文件中 <aop:advisor>元素支持advisor實際使用中,大多數狀況下它會和transactional advice配合使用,用於事務控制
配置文件使用案例:
- <?xml version="1.0" encoding="UTF-8"?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:context="http://www.springframework.org/schema/context"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans
-
- http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
- http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd">
-
- <bean name="sessionFactory"
- class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
- <property name="configLocation">
-
- <value>classpath:hibernate.cfg.xml</value>
- </property>
- </bean>
-
-
- <bean id="txManager"
- class="org.springframework.orm.hibernate3.HibernateTransactionManager">
- <property name="sessionFactory">
- <ref local="sessionFactory" />
- </property>
- </bean>
-
- <!-- advisor配置 配置事務處理的Bean,定義切面(advice)
- 因爲getxxx,queryxxx,findxxx不涉及事務,能夠設置read-only爲true
- -->
- <tx:advice id="txAdvice" transaction-manager="txManager">
- <tx:attributes>
- <tx:method name="get*" read-only="true" />
- <tx:method name="query*" read-only="true" />
- <tx:method name="find*" read-only="true" />
- <tx:method name="save*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
- <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
- <tx:method name="del*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
- <tx:method name="update*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
- <tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
- </tx:attributes>
- </tx:advice>
-
-
- <aop:config>
-
- <aop:pointcut expression="excution(* com.xxx.spring.aop.bean.annotation.service.impl..(..))" id="serviceMethod" />
- <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethod" />
- </aop:config>
-
- </beans>
關於spring的事務控制將會在另一篇文章中介紹。
7.SpringAOP代理實現
這種實現方式,主要使用動態代理技術。 有接口的:使用JDK的動態裏,無接口的:使用CGLIB代理
這種方式不是很經常使用
7.1.1ProxyFactoryBean
1.使用SpringAOP代理最關鍵的是使用org.springframework.aop.framework.ProxyFactoryBean,能夠徹底控制切入點和通知advice以及他們的順序
2.使用ProxyFacotryBean或者其餘的IOC相關類來建立AOP代理的最重要的好處就是通知切入點能夠由IOC來管理
3.被代理的類沒有實現任何接口,使用CGLIB代理,否者使用JDK代理
4.經過設置ProxyTargetClass爲true能夠強制使用CGLIB,(不管是否實現接口)
5.若是目標類實現了一個或者多個接口,那麼建立代理的類型將依賴於ProxyFactoryBean的配置
6.若是ProxyFactoryBean的proxyInterfaces屬性被設置爲一個或者多個全限定接口名,基於JDK的代理被建立
7.若是ProxyFactoryBean的proxyInterfaces屬性沒有被設置,可是目標類實現類一個或多個接口,那麼ProxyFactoryBean將自動檢測到這個目標類已經實現了至少一個接口,建立一個基於JDK的代理
7.1.2使用代理實現環繞通知around
配置文件:
- <?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-3.2.xsd">
-
- <bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
-
- <bean name="advice" class="com.xxx.spring.aop.bean.AdviceTest"></bean>
-
- <bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
- <!--proxyInterfaces 若是ProxyFactoryBean的proxyInterfaces屬性沒有被設置,可是目標類實現類一個或多個接口,
- 那麼ProxyFactoryBean將自動檢測到這個目標類已經實現了至少一個接口,建立一個基於JDK的代理 -->
- <property name="proxyInterfaces" value="com.xxx.spring.aop.bean.UserDao"></property>
-
- <property name="target" ref="target"></property>
-
- <property name="interceptorNames">
- <list>
- <value>advice</value>
- </list>
- </property>
- </bean>
- </beans>
注意:
上邊的<property name="proxyInterfaces" value="com.xxx.spring.aop.bean.UserDao">能夠不用寫,Spring的ProxyFactoryBean將會自動檢測到
若是被代理的對象target實現了多個接口能夠按照以下配置:
- <property name="interfaces">
- <array>
- <value>com.xxx.spring.aop.bean.UserDao</value>
- </array>
- </property>
value中能夠寫多個接口
一樣:通知interceptorNames若是隻用一個通知能夠寫成<property name="interceptorNames" name="
advice">
若是有多個通知能夠寫成:
- <property name="interceptorNames">
- <list>
- <value>advice</value>
- </list>
- </property>
可是 通知是不能夠省略的,同時推薦結合的寫法
上邊的委託類即便普通的實現類:即ProxyFactoryBean被代理的對象
<bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
上邊的通知配置
<bean name="advice" class="com.briup.spring.aop.bean.AdviceTest"></bean>
ProxyFactoryBean的配置
須要配置被代理的目標對象,通知,目標類實現的接口(能夠省略,被ProxyFactoryBean自動識別
)
切面通知實現類
實現MethodInterceptor就能夠實現環繞通知,咱們能夠在方法的目標對象類的方法執行先後加入處理邏輯
- import java.util.Date;
- import org.aopalliance.intercept.MethodInterceptor;
- import org.aopalliance.intercept.MethodInvocation;
-
- public class AdviceTest implements MethodInterceptor{
-
- @Override
- public Object invoke(MethodInvocation method) throws Throwable {
- System.out.println("方法開始執行"+new Date());
- method.proceed();
- System.out.println("方法執行完畢"+new Date());
- return null;
- }
- }
目標類:
- public class UserDaoImpl implements UserDao {
-
- @Override
- public void saveUser() {
- System.out.println("保存用戶");
- }
-
- @Override
- public void deleteUser() {
- System.out.println("刪除用戶");
- }
-
- @Override
- public void updateUser() {
- System.out.println("更新用戶");
- }
-
- }
接口:
- public interface UserDao {
- public abstract void saveUser();
- public abstract void deleteUser();
- public abstract void updateUser();
- }
測試:
- @Test
- public void advice(){
- BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/advice.xml");
- UserDao userDao = factory.getBean("proxy", UserDao.class);
- userDao.saveUser();
- userDao.deleteUser();
- userDao.updateUser();
- }
測試結果:
- 方法開始執行Sun Sep 11 21:02:12 CST 2016
- 保存用戶
- 方法執行完畢Sun Sep 11 21:02:12 CST 2016
- 方法開始執行Sun Sep 11 21:02:12 CST 2016
- 刪除用戶
- 方法執行完畢Sun Sep 11 21:02:12 CST 2016
- 方法開始執行Sun Sep 11 21:02:12 CST 2016
- 更新用戶
- 方法執行完畢Sun Sep 11 21:02:12 CST 2016
7.1.3使用動態代理實現前置通知before
配置文件:
- <?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-3.2.xsd">
-
- <bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
-
- <bean name="before" class="com.xxx.spring.aop.bean.BeforeTest"></bean>
-
- <bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
-
- <property name="target" ref="target"></property>
-
- <property name="interfaces">
- <array>
- <value>com.xxx.spring.aop.bean.UserDao</value>
- </array>
- </property>
-
- <property name="interceptorNames">
- <array>
- <value>before</value>
- </array>
- </property>
- </bean>
- </beans>
切面前置通知實現類:
實現MethodBeforeAdvice
- import java.lang.reflect.Method;
- import org.springframework.aop.MethodBeforeAdvice;
- public class BeforeTest implements MethodBeforeAdvice{
-
- @Override
- public void before(Method method, Object[] obj, Object object)
- throws Throwable {
- System.out.println("version 1.0 author tom "+method.getName()+" is execute");
- }
-
- }
測試:
- @Test
- public void before(){
- BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/before.xml");
- UserDao userDao = factory.getBean("proxy", UserDao.class);
- userDao.saveUser();
- userDao.deleteUser();
- userDao.updateUser();
- }
結果:
- version 1.0 author tom saveUser is execute
- 保存用戶
- version 1.0 author tom deleteUser is execute
- 刪除用戶
- version 1.0 author tom updateUser is execute
- 更新用戶
7.1.4後置通知afterReturning
配置文件:
- <?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-3.2.xsd">
-
- <bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
-
- <bean name="after" class="com.xxx.spring.aop.bean.AfterTest"></bean>
-
- <bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
-
- <property name="target" ref="target"></property>
-
- <property name="interfaces">
- <array>
- <value>com.xxx.spring.aop.bean.UserDao</value>
- </array>
- </property>
-
- <property name="interceptorNames">
- <array>
- <value>after</value>
- </array>
- </property>
- </bean>
- </beans>
切面後置通知:
實現 AfterReturningAdivce接口
- import java.lang.reflect.Method;
- import org.springframework.aop.AfterReturningAdvice;
- public class AfterTest implements AfterReturningAdvice {
-
- @Override
- public void afterReturning(Object arg0, Method arg1, Object[] arg2,
- Object arg3) throws Throwable {
- System.out.println(arg1.getName()+" is over!");
- }
- }
測試:
- @Test
- public void after(){
- BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/after.xml");
- UserDao userDao = factory.getBean("proxy", UserDao.class);
- userDao.saveUser();
- userDao.deleteUser();
- userDao.updateUser();
- }
測試結果:
- 保存用戶
- saveUser is over!
- 刪除用戶
- deleteUser is over!
- 更新用戶
- updateUser is over!
7.1.5異常通知throw
配置文件:
- <?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-3.2.xsd">
-
- <bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
-
- <bean name="throws" class="com.xxx.spring.aop.bean.ThrowsAdiviceTest"></bean>
-
- <bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
-
- <property name="target" ref="target"></property>
-
- <property name="interfaces">
- <array>
- <value>com.xxx.spring.aop.bean.UserDao</value>
- </array>
- </property>
-
- <property name="interceptorNames">
- <list>
- <value>throws</value>
- </list>
- </property>
- </bean>
- </beans>
異常通知切面:
參數中必須有Throwable的子類,前邊的參數
afterThrowing([Method, args, target], subclassOfThrowable)[]號中的參數可選
- package com.briup.spring.aop.bean;
-
- import java.lang.reflect.Method;
-
- import org.springframework.aop.ThrowsAdvice;
-
- public class ThrowsAdiviceTest implements ThrowsAdvice{
-
-
- public void afterThrowing(Method method,Object[] args,Object target,Exception ex)throws Throwable{
- System.out.println("afterThrowing 2 ...."+method.getName()+" "+ target.getClass().getName());
- }
-
- }
測試:
- @Test
- public void throwTest(){
- BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/throw.xml");
- UserDao userDao = factory.getBean("proxy", UserDao.class);
- userDao.saveUser();
- userDao.deleteUser();
- userDao.updateUser();
- }
結果:
- 保存用戶
- afterThrowing 2 ....saveUser com.xxx.spring.aop.bean.UserDaoImpl
7.1.6切入點配置pointcut
使用代理方式也能夠配置切入點
NameMatchMethodPointcut,根據方法的名字進行匹配
mappedNames匹配的方法名集合
配置文件:
- <?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-3.2.xsd">
-
- <bean name="target" class="com.briup.spring.aop.bean.UserDaoImpl"></bean>
-
- <bean name="advice" class="com.xxx.spring.aop.bean.AdviceTest"></bean>
- <bean name="throws" class="com.xxx.spring.aop.bean.ThrowsAdiviceTest"></bean>
-
- <bean name="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
- <property name="mappedNames">
- <list>
- <value>sa*</value>
- </list>
- </property>
- </bean>
-
- <bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
- <property name="advice" ref="throws"></property>
- <property name="pointcut" ref="pointcutBean"></property>
- </bean>
-
- <bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
-
- <property name="target" ref="target"></property>
-
- <property name="interfaces">
- <array>
- <value>com.xxx.spring.aop.bean.UserDao</value>
- </array>
- </property>
-
- <property name="interceptorNames">
- <list>
- <value>defaultAdvisor</value>
- <value>throws</value>
- </list>
- </property>
- </bean>
- </beans>
如上邊切入點配置:
- <bean name="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
- <property name="mappedNames">
- <list>
- <value>sa*</value>
- </list>
- </property>
- </bean>
切面:
- <bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
- <property name="advice" ref="advice"></property>
- <property name="pointcut" ref="pointcutBean"></property>
- </bean>
7.1.7使用匿名的代理對象
使用匿名的代理對象能夠將bean的配置到代理裏邊,這樣就不用爲target目標對象配置單獨的對象,這樣能夠直接避免目標對象
配置文件:
- <?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-3.2.xsd">
-
- <bean name="advice" class="com.xxx.spring.aop.bean.AdviceTest"></bean>
- <bean name="throws" class="com.xxx.spring.aop.bean.ThrowsAdiviceTest"></bean>
-
- <bean name="pointcutBean" class="org.springframework.aop.support.NameMatchMethodPointcut">
- <property name="mappedNames">
- <list>
- <value>sa*</value>
- </list>
- </property>
- </bean>
-
- <bean id="defaultAdvisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
- <property name="advice" ref="advice"></property>
- <property name="pointcut" ref="pointcutBean"></property>
- </bean>
-
- <bean name="proxy" class="org.springframework.aop.framework.ProxyFactoryBean">
-
- <property name="target">
- <bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
- </property>
-
- <property name="interfaces">
- <array>
- <value>com.xxx.spring.aop.bean.UserDao</value>
- </array>
- </property>
-
- <property name="interceptorNames">
- <list>
- <value>defaultAdvisor</value>
- <value>throws</value>
- </list>
- </property>
- </bean>
- </beans>
7.1.8IntroductionInterceptor
Introduction是個特別的Advice,能夠在不修改代碼的基礎上添加一些方法,能夠參見
http://www.iteedu.com/webtech/j2ee/springdiary/35.php
http://go12345.iteye.com/blog/352745
8.自動代理實現
8.1.BeanNameAutoProxyCreator
Spring容許使用自動代理的bean定義,他能夠自動代理選定bean,這樣我麼就不用爲代理對象聲明接口,或者沒有實現接口的時候,使用CGLIB代理
配置文件:
- <?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-3.2.xsd">
-
- <bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
-
- <bean name="before" class="com.xxx.spring.aop.bean.BeforeTest"></bean>
-
- <bean name="proxy" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
-
- <property name="beanNames">
- <list>
- <value>targ*</value>
- </list>
- </property>
-
- <property name="interceptorNames">
- <list>
- <value>before</value>
- </list>
- </property>
- </bean>
- </beans>
經過,自動代理,proxy會自動幫咱們代理全部以targ開頭的目標委託類
實現類:
- public class UserDaoImpl implements UserDao {
- @Override
- public void saveUser(){
- System.out.println("保存用戶");
- }
-
- @Override
- public void deleteUser() {
- System.out.println("刪除用戶");
- }
-
- @Override
- public void updateUser() {
- System.out.println("更新用戶");
- }
-
- }
測試:
- @Test
- public void autoAdvisor(){
- BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/autoAdvisor.xml");
- UserDao userDao = factory.getBean("target", UserDao.class);
- userDao.saveUser();
- userDao.deleteUser();
- userDao.updateUser();
- }
結果:
- version 1.0 author tom saveUser is execute
- 保存用戶
- version 1.0 author tom deleteUser is execute
- 刪除用戶
- version 1.0 author tom updateUser is execute
- 更新用戶
8.2DefaultAdvisorAutoProxyCreator
使用DefaultAdvisorAutoProxyCreator咱們能夠不用顯示的指定advisor的bean定義
- <?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-3.2.xsd">
-
- <bean name="target" class="com.xxx.spring.aop.bean.UserDaoImpl"></bean>
-
- <bean name="before" class="com.xxx.spring.aop.bean.BeforeTest"></bean>
-
-
- <bean name="advisor" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
-
- <property name="advice" ref="before"></property>
-
- <property name="patterns">
- <list>
- <value>.*deleteUser</value>
- </list>
- </property>
- </bean>
-
-
- <bean name="proxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"></bean>
- </beans>
測試:
- @Test
- public void autoProxyByName(){
- BeanFactory factory = new ClassPathXmlApplicationContext("com/xxx/spring/chap2/autoProxyByName.xml");
- UserDao userDao = factory.getBean("target", UserDao.class);
- userDao.saveUser();
- userDao.deleteUser();
- userDao.updateUser();
- }
結果:
- 保存用戶
- version 1.0 author tom deleteUser is execute
- 刪除用戶
- 更新用戶