一:靜態代理
這種代理方式需要代理對象和目標對象實現一樣的接口
優點:可以在不修改目標對象的情況下擴展目標對象的功能(經紀人是明星的代理,可以爲明星做另外的一些事情)
缺點:
- 冗餘。由於代理對象要實現與目標對象一致的接口,會產生過多的代理類。
- 不易維護。一旦接口增加方法,目標對象與代理對象都要進行修改。
舉例:
//接口IUserDao
package com.proxy;
public interface IUserDao {
public void save();
}
//目標對象UserDao
package com.proxy;
public class UserDao implements IUserDao{
@Override
public void save() {
System.out.println("保存數據");
}
}
//靜態代理對象:UserDapProxy 需要實現IUserDao接口!
package com.proxy;
public class UserDaoProxy implements IUserDao{
private IUserDao target;
public UserDaoProxy(IUserDao target) {
this.target = target;
}
@Override
public void save() {
System.out.println("開啓事務");//擴展了額外功能
target.save();
System.out.println("提交事務");
}
}
//測試類:TestProxy
package com.proxy;
import org.junit.Test;
public class StaticUserProxy {
@Test
public void testStaticProxy(){
//目標對象
IUserDao target = new UserDao();
//代理對象
UserDaoProxy proxy = new UserDaoProxy(target);
proxy.save();
}
}
輸出結果:
開啓事務
保存數據
提交事務
二:動態代理
1:動態代理利用了JDK API,動態地在內存中構建代理對象,從而實現對目標對象的代理功能。動態代理又被稱爲JDK代理或接口代理。
2:動態代理對象不需要實現接口,但是要求目標對象必須實現接口,否則不能使用動態代理。
3:動態代理利用了反射的機制,我們在運行時動態的利用反射獲取目標對象的方法,這個代理代碼較爲通用,不是爲某個具體的目標對象而創建,是一種抽象。
目標接口和目標對象實現相同
//動態代理對象
package com.proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyFactory {
private Object target;// 維護一個目標對象
public ProxyFactory(Object target) {
this.target = target;
}
// 爲目標對象生成代理對象
public Object getProxyInstance() {
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("開啓事務");
// 執行目標對象方法
Object returnValue = method.invoke(target, args);
System.out.println("提交事務");
return null;
}
});
}
}
測試類:
package com.proxy;
import org.junit.Test;
public class TestProxy {
@Test
public void testDynamicProxy (){
IUserDao target = new UserDao();
System.out.println(target.getClass()); //輸出目標對象信息
IUserDao proxy = (IUserDao) new ProxyFactory(target).getProxyInstance();
System.out.println(proxy.getClass()); //輸出代理對象信息
proxy.save(); //執行代理方法
}
}
輸出結果:
開啓事務
保存數據
提交事務