Spring 从入门到精通 (十三) 动态代理详解
关键词:Spring | 动态代理 | 详解
一、MethodBeforeAdvice接口
啥时候用? 额外功能运行在原始方法之前时使用它,实现接口方法 before 就可以了
二、before 方法参数详解
-
@param method 额外功能增加给的那个原始方法 @param objects 额外功能所增加给的那个原始方法的方法参数 @param o 额外功能所增加给的那个原始对象 @throws Throwable
public class Before implements MethodBeforeAdvice { /** * @param method 额外功能增加给的那个原始方法 * @param objects 额外功能所增加给的那个原始方法的方法参数 * @param o 额外功能所增加给的那个原始对象 * @throws Throwable */ @Override public void before(Method method, Object[] objects, Object o) throws Throwable { } }
三、MethodInterceptor(方法拦截器)
这个接口更加灵活,它可以在原始方法前使用,也可以在原始方法之后使用,或者前后都使用,比如事务……
注意,这个接口重名了,我们这里使用的是 aop 包下的这个接口
MyInter
自己编写的方法拦截器,实现MethodInterceptor 接口,并实现其中的invoke方法
-
@param methodInvocation 额外功能所增加的那个原始方法
我们通过这个参数,拦截方法,通过proceed方法控制方法执行时机,此时就可以添加前置附加操作,后置附加操作,前后都加附加操作等等,更加灵活
public class MyInter implements MethodInterceptor { /** * @param methodInvocation 额外功能所增加的那个原始方法 */ @Override public Object invoke(MethodInvocation methodInvocation) throws Throwable { Object obj = null; System.out.println("----开启事务----"); try { // 执行原始方法,同时获取执行后的对象,用作整个方法的返回值 obj = methodInvocation.proceed(); } catch (Exception e) { // 异常了,回滚事务 System.out.println("----回滚事务----"); return null; } // 没问题,提交事务 System.out.println("----提交事务----"); return obj; } }
spring.xml
在工厂中配置我们自定义分拦截器类,并将切面配置为我们刚定义的拦截器类
<bean class="com.liu.proxy.MyInter" id="myInter"/> <aop:config> <aop:pointcut id="pc" expression="execution(* *(..))"/> <aop:advisor advice-ref="myInter" pointcut-ref="pc"/> </aop:config>
UserServiceImpl
我们在注册方法实现中添加一个除0异常,猜想登录方法会正常开启事务,处理业务,提交事务,而注册方法会开启事务,执行业务,遇到除0异常被拦截器捕获并回滚事务,最后结束方法。
public class UserServiceImpl implements UserService{ @Override public void register(User user) { System.out.println("UserServiceImpl register + DAO"); System.out.println(1/0); } @Override public boolean login(String name, String pwd1) { System.out.println("UserServiceImpl login + DAO"); return true; } }
运行测试看效果
下面就执行测试类,看看是不是我们先想的那样子呢
@Test public void t2() { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("/spring.xml"); UserService userService = (UserService) context.getBean("userService"); userService.login("123","1232"); userService.register(new User()); }
----开启事务---- UserServiceImpl login + DAO ----提交事务---- ----开启事务---- UserServiceImpl register + DAO ----回滚事务----
很棒,和我们想的一样
四、写在最后
座右铭:不要在乎别人如何看你,要在乎你自己如何看未来,看梦想,看世界…!