2022-2023年英語週報九年級第39期答案彙總
阿新 • • 發佈:2022-03-13
代理模式
使用一個代理物件將物件包裝起來,然後用該代理物件來取代該物件,任何對原始物件的呼叫都要通過代理,代理物件決定是否以及何時呼叫原始物件的方法 .
以下例子來源於大神狂神!!!
1、靜態代理
1. Rent介面,負責出租房子的人和中介共同需要乾的事出租房子
//租房
public interface Rent {
//租房子
public void rent();
}
2. Proxy表示中介去繼承租房的介面
- 房東只需要把房子交給中介就行了,有中介代理,中介有些自己的事情要做....
@Component(value = "proxy") public class Proxy implements Rent{ @Autowired @Qualifier("host") private Host host; public Proxy() { } public Proxy(Host host) { this.host = host; } @Override public void rent() { lookHouse(); host.rent(); signContract(); harvestFees(); } public void lookHouse(){ System.out.println("看" + host.getHostName() +"的房子"); } public void signContract(){ System.out.println("籤合同"); } public void harvestFees(){ System.out.println("收中介費"); } }
3. 房東Host,需要出租房屋,他就只幹一件事,租房子
@Component(value = "host") public class Host implements Rent{ private String hostName; public String getHostName() { return hostName; } public void setHostName(String hostName) { this.hostName = hostName; } @Override public void rent() { System.out.println("房東要出租房"); } }
4. 需要租房的人,People,需要找中介租房,不直接聯絡房東,由中介全權代理
//需要租房的人 public class People { @Test public void makeHouse(){ ApplicationContext context = new AnnotationConfigApplicationContext(SsyConfig.class); Host host = context.getBean("host", Host.class); host.setHostName("水三丫"); Proxy proxy = context.getBean("proxy", Proxy.class); proxy.rent(); } } //執行結果 看水三丫的房子 房東要出租房 籤合同 收中介費 Process finished with exit code 0
靜態代理的缺點:一個真實的角色會引數一個代理角色,程式碼量會翻倍,需要動態代理來解決
2、動態代理
利用Java的反射技術(Java Reflection),在執行時建立一個實現某些給定介面的新類(也稱“動態代理類”)及其例項(物件),代理的是介面(Interfaces),不是類(Class),也不是抽象類。在執行時才知道具體的實現,spring aop就是此原理。
2.1 需要了解兩個類
- Proxy:代理
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class<?>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
-
loader: 用哪個類載入器去載入代理物件
-
interfaces:動態代理類需要實現的介面
-
h:動態代理方法在執行時,會呼叫h裡面的invoke方法去執行
- InvocationHandler介面:呼叫處理程式
2.2 測試
- 需要代理的介面
public interface UserService {
public void add();
public void update();
public void delete();
public void query();
}
- 實現該介面的類
public class UserServiceImpl implements UserService{
@Override
public void add() {
System.out.println("增加了一個使用者");
}
@Override
public void update() {
System.out.println("更新了一個使用者");
}
@Override
public void delete() {
System.out.println("刪除了一個使用者");
}
@Override
public void query() {
System.out.println("查詢了一個使用者");
}
}
- 實現該InvocationHandler介面的通過反射獲取代理類的類
@Component("proxyInvocationHandler")
public class ProxyInvocationHandler implements InvocationHandler {
private Object target;
public Object getTarget() {
return target;
}
public void setTarget(Object target) {
this.target = target;
}
//生成代理類
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
}
//處理代理事例並返回結果,當代理類呼叫方法時會走這個method,invoke()
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(method.getName());
before();
Object result = method.invoke(target, args);
after();
return result;
}
public void before(){
System.out.println("操作之前列印日誌");
}
public void after(){
System.out.println("操作之後列印日誌");
}
}
- 需要操作的客戶
public class UserServlet {
@Test
public void test(){
ApplicationContext context = new AnnotationConfigApplicationContext(SsyConfigService.class);
UserServiceImpl userServiceImpl = context.getBean("userService", UserServiceImpl.class);
ProxyInvocationHandler pih = context.getBean("proxyInvocationHandler", ProxyInvocationHandler.class);
pih.setTarget(userServiceImpl);
UserService proxy = (UserService) pih.getProxy();
proxy.update();
}
}