1.简介

基于接口的动态代理技术,利用拦截器(必须实现invocationHandler)和反射机制生成一个代理接口的匿名类,在调用具体方法前调用InvokeHandler来实现方法增强。

7.AOP之JDK动态代理_对象方法

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元数额未发生变化。