代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。在讲述动态代理前,我们先通过一个例子了解一下什么是静态代理,这里以事务控制为例。
1.静态代理
1.1 pom.xml文件配置
<properties>
<!-- Spring -->
<spring.version>4.1.3.RELEASE</spring.version>
</properties>
<dependencies>
<!-- Spring Begin -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>${spring.version}</version>
</dependency>
<!-- Spring End -->
</dependencies>
1.2 业务接口代码
public interface UserService {
/**
*
* 功能描述: <br>
* 〈保存用户〉
*
* @since [1.0.0](可选)
*/
public void saveUser();
/**
*
* 功能描述: <br>
* 〈更新用户〉
*
* @since [1.0.0](可选)
*/
public void updateUser();
}
1.3 业务实现类代码
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public void saveUser() {
System.out.println("userService saveUser()...");
}
@Override
public void updateUser() {
System.out.println("userService updateUser()...");
}
}
1.4 事务管理类代码
@Service("transactionManager")
public class TransactionManager {
public void beginTransaction() {
System.out.println("开启事务....");
}
public void commint() {
System.out.println("提交事务....");
}
public void rollback() {
System.out.println("回滚事务....");
}
}
1.5 代理类代码
@Service("userServiceProxy")
public class UserServiceProxy implements UserService {
@Resource(name = "userService")
private UserService userService;
@Resource(name = "transactionManager")
private TransactionManager transactionManager;
@Override
public void saveUser() {
try {
transactionManager.beginTransaction();
userService.saveUser();
transactionManager.commint();
} catch (Exception e) {
transactionManager.rollback();
}
}
@Override
public void updateUser() {
try {
transactionManager.beginTransaction();
userService.updateUser();
transactionManager.commint();
} catch (Exception e) {
transactionManager.rollback();
}
}
}
1.6 测试类代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ProxyTest {
@Resource(name = "userServiceProxy")
private UserService userService;
@Test
public void testStaticProxy() {
userService.saveUser();
}
}
1.7 测试结果
开启事务....
userService saveUser()...
提交事务....
从上面的代码,可以看出静态代理给我们带来的一系列问题,如在代理对象中包含了真实对象的引用,如果我们需要为不同的业务进行代理,就需要为每个业务都创建一个代理对象,甚是麻烦,所以引出了动态代理。
2.JDK动态代理
2.1 业务类接口
public interface UserService {
/**
*
* 功能描述: <br>
* 〈保存用户〉
*
* @since [1.0.0](可选)
*/
public void saveUser();
/**
*
* 功能描述: <br>
* 〈更新用户〉
*
* @since [1.0.0](可选)
*/
public void updateUser();
}
2.2 业务实现类
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public void saveUser() {
System.out.println("userService saveUser()...");
}
@Override
public void updateUser() {
System.out.println("userService updateUser()...");
}
}
2.3 事务管理类代码
@Service("transactionManager")
public class TransactionManager {
public void beginTransaction() {
System.out.println("开启事务....");
}
public void commint() {
System.out.println("提交事务....");
}
public void rollback() {
System.out.println("回滚事务....");
}
}
2.4 代理类代码
@Service("transactionManagerProxy")
public class TransactionManagerProxy implements InvocationHandler {
private Object target;
@Resource(name = "transactionManager")
private TransactionManager transactionManager;
public Object createProxyObject(Object object) {
this.target = object;
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
transactionManager.beginTransaction();
Object object = null;
try {
object = method.invoke(target, args);
transactionManager.commint();
} catch (Exception e) {
transactionManager.rollback();
}
return object;
}
}
2.5 测试类代码
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ProxyTest {
@Resource(name = "transactionManagerProxy")
private TransactionManagerProxy transactionManagerProxy ;
@Test
public void testStaticProxy() {
UserService userService = (UserService) transactionManagerProxy.createProxyObject(new UserServiceImpl());
userService.saveUser();
}
}
2.6 测试结果
开启事务....
userService saveUser()...
提交事务....
但是,JDK的动态代理依靠接口实现,如果有些类并没有实现接口,则不能使用JDK代理,这就要使用cglib动态代理了。
3.CGLIB动态代理
3.1 业务接口类
public interface UserService {
/**
*
* 功能描述: <br>
* 〈保存用户〉
*
* @since [1.0.0](可选)
*/
public void saveUser();
/**
*
* 功能描述: <br>
* 〈更新用户〉
*
* @since [1.0.0](可选)
*/
public void updateUser();
}
3.2 业务实现类
@Service("userService")
public class UserServiceImpl implements UserService {
@Override
public void saveUser() {
System.out.println("userService saveUser()...");
}
@Override
public void updateUser() {
System.out.println("userService updateUser()...");
}
}
3.3 事务管理类
@Service("transactionManager")
public class TransactionManager {
public void beginTransaction() {
System.out.println("开启事务....");
}
public void commint() {
System.out.println("提交事务....");
}
public void rollback() {
System.out.println("回滚事务....");
}
}
3.4 事务代理类
public class TransactionManagerProxy implements org.springframework.cglib.proxy.InvocationHandler {
private Object target;
private TransactionManager transactionManager;
public TransactionManagerProxy(Object target, TransactionManager transactionManager) {
this.target = target;
this.transactionManager = transactionManager;
}
// 创建代理对象
public Object getProxyInstance() {
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(this.getClass().getClassLoader());
enhancer.setSuperclass(target.getClass());
enhancer.setCallback(this);
return enhancer.create();
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
transactionManager.beginTransaction();
Object object = null;
try {
object = method.invoke(target, args);
transactionManager.commint();
} catch (Exception e) {
transactionManager.rollback();
}
return object;
}
}
3.5 测试类
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class ProxyTest {
@Resource(name = "transactionManager")
private TransactionManager transactionManager;
@Test
public void testStaticProxy() {
UserServiceImpl userServiceImpl = (UserServiceImpl) new TransactionManagerProxy(new UserServiceImpl(), transactionManager).getProxyInstance();
userServiceImpl.saveUser();
}
}
3.6 测试结果
开启事务....
userService saveUser()...
提交事务....
1.CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。
2.要求类不能是final的,要拦截的方法要是非final,非static,非private的
3.动态代理的最小单位是类(所有类中的方法都会被处理)
注:若目标对象实现了若干接口,Spring就会使用JDK动态代理,若目标对象没有实现任何接口,Spring就使用CGLIB库生成目标对象的子类。