动态代理的两种实现方式
动态代理
基于JDK版实现
1. 基于jdk版本实现的动态代理
要求目标类和代理类共同实现一个接口
基本的实现如下:
目标类:
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Override
public void transfer(String sourceAccountName, String targetAccountName, Float amount) {
//查询
Account sourceAccount = accountDao.findByName(sourceAccountName);
Account targetAccount = accountDao.findByName(targetAccountName);
//更改
sourceAccount.setBalance(sourceAccount.getBalance() - amount);
targetAccount.setBalance(targetAccount.getBalance() + amount);
//更新
accountDao.update(sourceAccount);
int i = 1 / 0;
accountDao.update(targetAccount);
}
}
产生的代理对象:基于接口
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AccountServiceTest {
@Autowired
private AccountService accountService;
@Autowired
private TxManager txManager;
@Test
public void testTransfer() {
//代理逻辑
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj = null;
try {
//关闭自动提交
txManager.begin();
obj = method.invoke(accountService, args);
//手动提交
txManager.commit();
} catch (Exception e) {
//事务回滚
txManager.rollback();
} finally {
//事务关闭
txManager.close();
}
return obj;
}
};
//产生代理对象
AccountService instance = (AccountService) Proxy.newProxyInstance(
accountService.getClass().getClassLoader(),
accountService.getClass().getInterfaces(),
invocationHandler
);
//转账
instance.transfer("B01", "B02", 1f);
}
}
基于Cglib实现的
# 使用Cglib实现的动态代理
当目标对象没有实现的接口的时候 只能使用Cglib来实现动态代理
目标对象: 没有实现的接口的时候
@Service
public class AccountServiceImpl {
@Autowired
private AccountDao accountDao;
public void transfer(String sourceAccountName, String targetAccountName, Float amount) {
//查询
Account sourceAccount = accountDao.findByName(sourceAccountName);
Account targetAccount = accountDao.findByName(targetAccountName);
//更改
sourceAccount.setBalance(sourceAccount.getBalance() - amount);
targetAccount.setBalance(targetAccount.getBalance() + amount);
//更新
accountDao.update(sourceAccount);
int i = 1 / 0;
accountDao.update(targetAccount);
}
public void desc(){
System.out.println("Hello");
}
}
代理对象:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AccountServiceTest {
@Autowired
private AccountServiceImpl accountService;
@Autowired
private TxManager txManager;
@Test
public void testTransfer() {
//代理逻辑
InvocationHandler invocationHandler = new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object obj = null;
try {
//关闭自动提交
txManager.begin();
obj = method.invoke(accountService, args);
//手动提交
txManager.commit();
} catch (Exception e) {
//事务回滚
txManager.rollback();
} finally {
//事务关闭
txManager.close();
}
return obj;
}
};
//创建一个增强器
Enhancer enhancer = new Enhancer();
//设置父类
enhancer.setSuperclass(AccountServiceImpl.class);
//设置代理逻辑
enhancer.setCallback(invocationHandler);
//产生代理对象
AccountServiceImpl instance = (AccountServiceImpl) enhancer.create();
//转账
instance.transfer("B01", "B02", 1f);
}
}
总结:
# 当目标对象有实现的接口的时候,我们选择的是使用jdk版本的动态代理
因为效率高,基于接口来实现的动态代理
# 当目标对象没有实现的接口的时候 ,我们只能使用Cglib来实现动态代理
基于继承来实现的动态代理