前言
- 動態代理在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代理實現
動態代理的優點
-
解決了靜態代理中冗餘的代理實現類問題。
-
系統擴展性和維護性增強。