前言
- 动态代理在Java中有着广泛的应用,比如Spring AOP、Mybatis、RPC远程调用、Java注解对象获取、日志、用户鉴权、全局性异常处理、性能监控,甚至事务处理等。
代理模式
- 代理模式是给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问
- 代理模式根据Java字节码创建的时机划分为静态代理和动态代理
静态代理
- 静态代理也就是在程序运行前就已经存在代理类的字节码文件,代理类和真实主题角色的关系在运行前就确定了
- 代理类
public class StaticProxy {
private UserMapper target;
public StaticProxy(UserMapper mapper)
{
this.target =mapper;
}
public List<Pojo> select()
{
before();
List<Pojo> res= target.select();
after();
return res;
}
public void before(){
System.out.print(String.format("Load start:[%s]\r\n", new Date().toString()));
}
public void after() {
System.out.print(String.format("Load end:[%s]\r\n", new Date().toString()));
}
}
- 测试类
@Service
@Transactional
@Component
public class TestFunc {
@Autowired
private UserMapper oMapper;
@PostConstruct
private void test()
{
System.out.print("Load data from db start \r\n");
StaticProxy proxy = new StaticProxy(oMapper);
List<Pojo> results = proxy.select();
//List<Pojo> results = oMapper.select();
}
- 代理类实际上是目标对象的增强类
静态代理的缺点
- 虽然没有入侵实体类,但是实现目标类的多个接口,导致代理类过大
- 目标类的修改都要同步修改代理类,耦合严重
动态代理
- 动态代理的源码是在程序运行期间由JVM根据反射等机制动态的生成,所以在运行前并不存在代理类的字节码文件
- 代理类
public class MapperProxy implements InvocationHandler {
private Object target;
public MapperProxy(Object target){
this.target = target;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before();
Object obj = method.invoke(target, args);
after();
return obj;
}
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
private void before(){
System.out.print(String.format("Load start:[%s]\r\n", new Date().toString()));
}
private void after() {
System.out.print(String.format("Load end:[%s]\r\n", new Date().toString()));
}
}
- 测试类
@Autowired
private UserMapper oMapper;
@PostConstruct
private void test()
{
System.out.print("Load data from db start \r\n");
MapperProxy proxy = new MapperProxy(oMapper);
UserMapper mapper = proxy.getProxy();
mapper.select();
//List<Pojo> results = oMapper.select();
}
动态代理的划分
- 接口级别代理:JDK动态代理,动态代理类实现InvocationHandler接口
- 方法级别代理:Cglib代理,在内存中构建一个子类对象从而实现对目标对象功能的扩展
- 如果是一个对象的 一个或多个接口,可以使用JDK动态代理;如果目标类没有接口,可以使用Cglib代理实现
动态代理的优点
-
解决了静态代理中冗余的代理实现类问题。
-
系统扩展性和维护性增强。