7.AOP之JDK动态代理
原创
©著作权归作者所有:来自51CTO博客作者wx63560c7d74933的原创作品,请联系作者获取转载授权,否则将追究法律责任
1.简介
基于接口的动态代理技术,利用拦截器(必须实现invocationHandler)和反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来实现方法增强。
2.生成代理对象
在项目目录“/src/main/java/com/steven”下新建proxy目录,并在proxy目录下新建JDKProxyFactory类,在类中提供一个创建JDK代理对象的方法createJDKProxyObject,具体代码如下。
public class JDKProxyFactory {
@Autowired
private IAccountService accountService;
@Autowired
private TransactionManager transactionManager;
public IAccountService createJDKProxyObject() {
/**
* 采用JDK动态代理技术生成目标类的代理对象
* classLoader 类加载器,借助被代理类对象获取类加载器
* interface 代理对象所需实现的全部接口,借助被代理类对象获取所需实现的全部接口
* invocationHandler 当代理对象调用接口中的任意方法时,都会执行InvocationHandler中invoke方法
*/
IAccountService accountServiceProxy = (IAccountService) Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() {
/**
* @param proxy 代理对象引用
* @param method 被代理对象方法引用
* @param args 被代理对象方法入参
*/
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
//手动开启事务
transactionManager.beginTransaction();
System.out.println("被代理类对象方法将要被执行");
//让被代理对象的原方法执行
method.invoke(accountService, args);
System.out.println("被代理类对象方法已经被执行");
//手动提交事务
transactionManager.commit();
} catch (Exception e) {
e.printStackTrace();
//手动回滚事务
transactionManager.rollback();
} finally {
//手动释放资源
transactionManager.release();
}
return null;
}
});
return accountServiceProxy;
}
}
3.修改业务层代码
在转账工程基础上,删除业务层的事务控制代码,具体代码如下。
@Service
public class AccountServiceImpl implements IAccountService {
@Autowired
private IAccountDao accountDao;
public void transfer(String outUser, String inUser, Double money) {
accountDao.out(outUser, money);
int i = 1 / 0;
accountDao.in(inUser, money);
}
}
4.将JDKProxyFactory交给Spring容器管理
在applicationContext.xml文件中添加如下bean标签。
<bean id="jdkProxyFactory" class="com.steven.proxy.JDKProxyFactory"/>
5.编写测试类
public class Test {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
JDKProxyFactory jdkProxyFactory = (JDKProxyFactory) context.getBean("jdkProxyFactory");
IAccountService accountService = jdkProxyFactory.createAccountServiceJDKProxy();
accountService.transfer("steven", "sherry", 100d);
}
}
程序执行成功,查看数据库数据,steven和sherry的10000元数额未发生变化。