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:
[java] view
plaincopyprint?
- public interface UserDao {
- public void save();
- }
[html] view
plaincopyprint?
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("保存用户...");
- }
- }
b、创建一个增强类实现MethodBeforeAdvice接口
public class UserDaoBeforeAdvice implements MethodBeforeAdvice { public void before(Method method, Object[] args, Object object) throws Throwable { System.out.println("我是前置增强"); } }
c、配置
<!-- 把增强类交由spring管理 --> <bean id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean> <!-- 把目标类交由spring管理 --> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <!-- 设置代理类 p:target-ref 目标对象 p:proxyInterfaces 代理所要实现的接口,也就是目标对象的接口 p:interceptorNames 织入的增强Bean,可以是多个,用","号分开 --> <bean id="adviceUserDao" class="org.springframework.aop.framework.ProxyFactoryBean" 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:
[java] view
plaincopyprint?
- public interface UserDao {
- public void save();
- }
[html] view
plaincopyprint?
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("保存用户...");
- }
- }
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 id="userDaoBeforeAdvice" class="cn.framelife.spring.advice.UserDaoBeforeAdvice"></bean> <bean id="userDaoAfterAdvice" class="cn.framelife.spring.advice.UserDaoAfterAdvice"></bean> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <bean id="adviceUserDao" class="org.springframework.aop.framework.ProxyFactoryBean" 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:
[java] view
plaincopyprint?
- public interface UserDao {
- public void save();
- }
[html] view
plaincopyprint?
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("保存用户...");
- }
- }
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 id="userDaoSurroundAdvice" class="cn.framelife.spring.advice.UserDaoSurroundAdvice"></bean> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <bean id="adviceUserDao" class="org.springframework.aop.framework.ProxyFactoryBean" 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:
[java] view
plaincopyprint?
- public interface UserDao {
- public void save();
- }
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 id="userDaoThrowAdvice" class="cn.framelife.spring.advice.UserDaoThrowsAdvice"></bean> <!-- p:proxyTargetClass="false" 如果目标对象是一个类,而不是一个接口,我们设置为true --> <bean id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <bean id="adviceUserDao" class="org.springframework.aop.framework.ProxyFactoryBean" 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:
[java] view
plaincopyprint?
- public interface UserDao {
- public void save();
- }
[html] view
plaincopyprint?
- public class UserDaoImpl implements UserDao {
- public void save() {
- System.out.println("保存用户...");
- }
- }
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 id="userDao" class="cn.framelife.spring.dao.impl.UserDaoImpl"></bean> <bean id="introductionAdvice" class="cn.framelife.spring.advice.IntroductionAdvice"></bean> <!-- 代理类设置 p:proxyTargetClass="true" 引介增强一定要通过创建子类来生成代理,所以要设置为true。 也不需要配置p:proxyInterfaces目标类的接口 p:interfaces 引介增强所实现的接口 --> <bean id="aProxy" class="org.springframework.aop.framework.ProxyFactoryBean" 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 保存用户... 方法执行后执行