第三章 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、UserDao與UserDaoImpl:
- public interface UserDao {
- public void save();
- }
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("保存用戶...");
- }
- }
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、UserDao與UserDaoImpl:
- public interface UserDao {
- public void save();
- }
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("保存用戶...");
- }
- }
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環繞增強
環繞增強與struts2的AOP類似。
a、UserDao與UserDaoImpl:
- public interface UserDao {
- public void save();
- }
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("保存用戶...");
- }
- }
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、UserDao與UserDaoImpl:
- public interface UserDao {
- public void save();
- }
public class UserDaoImpl implements UserDao { public void save() { System.out.println("保存用戶..."); //使方法在運行的時候拋出一個異常 throw new RuntimeException("運行時異常..."); } }
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、UserDao與UserDaoImpl:
- public interface UserDao {
- public void save();
- }
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("保存用戶...");
- }
- }
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