閱讀384 返回首頁    go 阿裏雲 go 技術社區[雲棲]


第三章 AOP 通過Java API創建增強


3.3.1增強類型

前置增強:org.springframework.aop.MethodBeforeAdvice

後置增強:org.springframework.aop.AfterReturningAdvice

環繞增強:org.aopalliance.intercept.MethodInterceptor

異常拋出增強:org.springframework.aop.ThrowsAdvice

引介增強:org.springframework.aop.support.DelegatingIntroductionInterceptor


3.3.2前置增強

就是在連接點方法執行之前執行的內容。
如:我們在UserDaoImpl的save()方法執行之前執行一些內容。

a、UserDaoUserDaoImpl:

  1. public interface UserDao {    
  2.     public void save();    
  3. }    
  1. public class UserDaoImpl implements UserDao {    
  2.     public void save() {    
  3.         System.out.println("保存用戶...");    
  4.     }    
  5. }    

b、創建一個增強類實現MethodBeforeAdvice接口
public class UserDaoBeforeAdvice implements MethodBeforeAdvice {
	public void before(Method method, Object[] args, Object object)
			throws Throwable {
		System.out.println("我是前置增強");
	}
}


c、配置
<!-- 把增強類交由spring管理 -->
	<bean  ></bean>

	<!-- 把目標類交由spring管理 -->
	<bean  ></bean>

	<!-- 
		設置代理類 
		p:target-ref 目標對象
		p:proxyInterfaces 代理所要實現的接口,也就是目標對象的接口
		p:interceptorNames 織入的增強Bean,可以是多個,用","號分開
	-->
	<bean  
		
		p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
		p:interceptorNames="userDaoBeforeAdvice"
		p:target-ref="userDao"
	 />

d、main方法中測試
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		//通過代理來獲取userDao對象
		UserDao userDao = (UserDao) context.getBean("adviceUserDao");
		userDao.save();

f、結果
我是前置增強
保存用戶...

3.3.3後置增強

就是在連接點方法執行之後執行的內容。

a、UserDaoUserDaoImpl:

  1. public interface UserDao {    
  2.     public void save();    
  3. }    
  1. public class UserDaoImpl implements UserDao {    
  2.     public void save() {    
  3.         System.out.println("保存用戶...");    
  4.     }    
  5. }    

b、創建一個增強類實現AfterReturningAdvice接口
public class UserDaoAfterAdvice implements AfterReturningAdvice {
	@Override
	public void afterReturning(Object object, Method method, Object[] args,
			Object arg3) throws Throwable {
		System.out.println("我是後置增強");
	}
}



c、配置
<bean  ></bean>
	<bean  ></bean>

	<bean  ></bean>

	
	<bean  
		
		p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
		p:interceptorNames="userDaoBeforeAdvice,userDaoAfterAdvice"
		p:target-ref="userDao"
	 />


d、main方法中測試
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		//通過代理來獲取userDao對象
		UserDao userDao = (UserDao) context.getBean("adviceUserDao");
		userDao.save();

f、結果
保存用戶...
我是後置增強


3.3.4環繞增強

環繞增強與struts2AOP類似。



a、UserDaoUserDaoImpl:

  1. public interface UserDao {    
  2.     public void save();    
  3. }    
  1. public class UserDaoImpl implements UserDao {    
  2.     public void save() {    
  3.         System.out.println("保存用戶...");    
  4.     }    
  5. }    

b、創建一個增強類實現MethodInterceptor接口
public class UserDaoSurroundAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("環繞增強在方法前執行...");
		Object object = invocation.proceed();
		System.out.println("環繞增強在方法後執行...");
		return object;
	}

}


c、配置
<bean  ></bean>
	
	<bean  ></bean>

	<bean  
		
		p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
		p:interceptorNames=" userDaoSurroundAdvice"
		p:target-ref="userDao"
	 />



d、main方法中測試
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		//通過代理來獲取userDao對象
		UserDao userDao = (UserDao) context.getBean("adviceUserDao");
		userDao.save();

f、結果
環繞增強在方法前執行...
保存用戶...
環繞增強在方法後執行...


3.3.5異常拋出增強

就是在方法出現異常之後執行的代碼。



a、UserDaoUserDaoImpl:

  1. public interface UserDao {    
  2.     public void save();    
  3. }    
public class UserDaoImpl implements UserDao {    
     public void save() {    
         System.out.println("保存用戶...");    
         //使方法在運行的時候拋出一個異常
          throw new RuntimeException("運行時異常...");

    }    
}  


b、創建一個增強類實現ThrowsAdvice接口
public class UserDaoThrowsAdvice implements ThrowsAdvice {
	public void afterThrowing(Method method,Object[] args,Object taglet,Exception ex)throws Throwable{
		System.out.println("我是異常拋出接口");
		System.out.println(method.getName());
		System.out.println(ex.getMessage());
	}
}



c、配置
<bean  ></bean>

<!--
	 p:proxyTargetClass="false"
	如果目標對象是一個類,而不是一個接口,我們設置為true
-->
	<bean  ></bean>

	<bean  
		
		p:proxyInterfaces="cn.framelife.spring.dao.UserDao"
		p:interceptorNames="userDaoThrowAdvice"
		p:target-ref="userDao"
		p:proxyTargetClass="false"
	 />




d、main方法中測試
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		//通過代理來獲取userDao對象
		UserDao userDao = (UserDao) context.getBean("adviceUserDao");
		userDao.save();

f、結果
保存用戶...
Exception in thread "main" java.lang.RuntimeException: 運行時異常...
	at cn.framelife.spring.dao.impl.UserDaoImpl.save(UserDaoImpl.java:12)
	at cn.framelife.spring.dao.impl.UserDaoImpl$$FastClassByCGLIB$$18bd6dee.invoke(<generated>)
	at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191)
	at org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
	at org.springframework.aop.framework.adapter.ThrowsAdviceInterceptor.invoke(ThrowsAdviceInterceptor.java:124)我是異常拋出接口
save
運行時異常...

	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
	at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621)
	at cn.framelife.spring.dao.impl.UserDaoImpl$$EnhancerByCGLIB$$5bbe38b0.save(<generated>)
	at cn.framelife.spring.test.Test.main(Test.java:17)


3.3.6引介增強

     引介增強是為目標類創建新的方法和屬性,引介增強的連接點是類級別的,不是方法級別的。通過引介增強,我們可以為目標類添加一個接口的實現,即原來目標類未實現某個接口,通過引介增強可以為目標類創建實現某個接口的代理。




a、UserDaoUserDaoImpl:

  1. public interface UserDao {    
  2.     public void save();    
  3. }    
  1. public class UserDaoImpl implements UserDao {    
  2.     public void save() {    
  3.         System.out.println("保存用戶...");    
  4.     }    
  5. }    


b、新建一個接口AInterface
public interface AInterface {
	public void say();
}



c、增強類繼承DelegatingIntroductionInterceptor實現AInterface
public class IntroductionAdvice extends DelegatingIntroductionInterceptor implements AInterface {
	/*
	 * 實現AInterface中的方法
	 */
	public void say() {
		System.out.println("UserDao要說話");
	}

	/*
	 * 重寫DelegatingIntroductionInterceptor的invoke方法
	 */
	public Object invoke(MethodInvocation mi) throws Throwable {
		System.out.println("方法執行前執行");
		System.out.println(mi.getClass().getName());
		System.out.println(mi.getMethod().getName());
		Object object = super.invoke(mi);
		System.out.println("方法執行後執行");
		return object;
	}	
}




d、配置

<bean  ></bean>

	<bean  ></bean>
	<!-- 
		代理類設置
		p:proxyTargetClass="true" 引介增強一定要通過創建子類來生成代理,所以要設置為true。
			也不需要配置p:proxyInterfaces目標類的接口
		p:interfaces 引介增強所實現的接口
	 -->
	<bean  
		
		p:interfaces="cn.framelife.spring.dao.AInterface" 
		p:interceptorNames="introductionAdvice"
		p:target-ref="userDao" 
		p:proxyTargetClass="true" />

e、main方法中測試
ApplicationContext context = new ClassPathXmlApplicationContext(new String[]{"applicationContext.xml"});
		UserDao userDao = (UserDao) context.getBean("aProxy");
		userDao.save();
		
		System.out.println("-------------");
		
		AInterface a = (AInterface)userDao;
		a.say();
		
		System.out.println("-------------");
		userDao.save();


f、結果
方法執行前執行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
save
保存用戶...
方法執行後執行
-------------
方法執行前執行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
say
UserDao要說話
方法執行後執行
-------------
方法執行前執行
org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation
save
保存用戶...
方法執行後執行







最後更新:2017-04-03 16:48:31

  上一篇:go Hadoop 使用Combiner提高Map/Reduce程序效率
  下一篇:go 我筆下的“名著”