代理模式是主要對我們方法執(zhí)行之前與之后實現(xiàn)增強。
代理模式應(yīng)用場景
1,日志采集
2,權(quán)限控制
3,實現(xiàn)aop
4,mybatis mapper
5,Spring的事務(wù)
6,全局捕獲異常
7,rpc遠程調(diào)用接口(傳遞就是接口)
8,代理數(shù)據(jù)源
9,自定義注解
aop---基于代理實現(xiàn)
代理模式實現(xiàn)的原理
代理模式主要包含三個角色,即抽象主題角色(Subject),委托類角色(被代理角色,Proxied)以及代理類角色(Proxy)
抽象主題角色:可以是接口,也可以是抽象類;
委托類角色: 真實主題角色,業(yè)務(wù)邏輯的具體執(zhí)行者;
代理類角色: 內(nèi)部含有對真實對象RealSubject的引用,負責對真實主題角色的調(diào)用,并在真實主題角色處理前后做預(yù)處理和后處理。
代理模式創(chuàng)建方式:
相關(guān)測試代碼:
package com.taotao.proxy.service;
/**
* @Author: wangjin
* @CreateTime: 2022-07-03 21:23
*/
public interface OrderService {
/**
* 追加訂單數(shù)據(jù)
*/
String addOrder(String orderName);
}
package com.taotao.proxy.service.impl;
import com.taotao.proxy.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
/**
* @Author: wangjin
* @CreateTime: 2022-07-03 21:24
*/
@Service("OrderService")
@Slf4j
public class OrderServiceImpl implements OrderService {
@Override
public String addOrder(String orderName) {
log.info("<orderName:{}>", orderName);
log.info("addOrder方法之后處理");
return "OK";
}
}
package com.taotao.proxy.service.proxy;
import com.taotao.proxy.service.OrderService;
import lombok.extern.slf4j.Slf4j;
/**
* @Author: wangjin
* @CreateTime: 2022-07-03 21:37
*/
@Slf4j
public class OrderServiceProxy implements OrderService {
//代理類 到底是需要調(diào)用哪一個 被代理類
private OrderService orderService;
public OrderServiceProxy(OrderService orderService) {
this.orderService = orderService;
}
@Override
public String addOrder(String orderName) {
log.info("<在adder方法之前處理 orderName:{}>", orderName);
String resultString = orderService.addOrder(orderName);//調(diào)用被代理類
return resultString;
}
}
package com.taotao.proxy.service;
import com.taotao.proxy.service.impl.OrderServiceImpl;
import com.taotao.proxy.service.proxy.OrderServiceProxy;
/**
* @Author: wangjin
* @CreateTime: 2022-07-03 21:44
*/
public class Test01 {
public static void main(String[] args) {
//被代理類
OrderServiceProxy orderServiceProxy=new OrderServiceProxy(new OrderServiceImpl());
String result= orderServiceProxy.addOrder("hello");
System.out.println(result);
}
}
package com.taotao.proxy.service;
import com.taotao.proxy.service.proxy1.OrderServiceProxy;
/**
* @Author: wangjin
* @CreateTime: 2022-07-03 21:56
*/
public class Test02 {
public static void main(String[] args) {
OrderServiceProxy orderServiceProxy=new OrderServiceProxy();
String result= orderServiceProxy.addOrder("oooo");
System.out.println(result);
}
}
package com.taotao.proxy.service.proxy1;
import com.taotao.proxy.service.impl.OrderServiceImpl;
import lombok.extern.slf4j.Slf4j;
/**
* @Author: wangjin
* @CreateTime: 2022-07-03 21:51
*/
@Slf4j
public class OrderServiceProxy extends OrderServiceImpl {
//讓我們代理類 繼承 代理類
@Override
public String addOrder(String orderName) {
log.info("<在addOrder方法之前處理 orderName:{}>",orderName);
String result=super.addOrder(orderName);
//目標方法 執(zhí)行 被代理類
log.info("<在addOrder方法之后處理 orderName:{}>",orderName);
return result;
}
}
動態(tài)代理是在實現(xiàn)階段不用關(guān)心代理類,而是在運行階段才指定哪一個對象。
動態(tài)代理類的源碼是在程序運行期間由JVM根據(jù)反射等機制動態(tài)生成。
jdk動態(tài)代理的一般步驟如下:
1,創(chuàng)建被代理的接口和類
2,實現(xiàn)InvocationHandler接口,對目標接口中聲明的所有方法進行統(tǒng)一處理;
3,調(diào)用Proxy的靜態(tài)方法,創(chuàng)建代理類并生成相應(yīng)的代理對象;
實現(xiàn)原理: 利用攔截器機制必須實現(xiàn)InvocationHandler 接口中的invoke方法實現(xiàn)對我們的目標方法增強
JDK API 動態(tài)代理方法:
package com.taotao.proxy.service;
import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* @Author: wangjin
* @CreateTime: 2022-07-03 22:36
*/
@Slf4j
public class JdkInvocationHandler implements InvocationHandler {
/**
* 目標對象
*/
private Object target;
public JdkInvocationHandler(Object target){
this.target=target;
}
/**
*
* @param proxy jdk自動生成好的代理類
* @param method 木目標對象的接口
* @param args 參數(shù)類
* @return
* @throws Throwable
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log.info("<jdk動態(tài)代理目標方法之前>,args:{}",args);
Object result=method.invoke(target,args);
log.info("<jdk動態(tài)代理目標方法之后,args:{}", args);
return result;
}
public <T> T getProxy() {
return (T) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
}
package com.taotao;
import com.taotao.proxy.service.JdkInvocationHandler;
import com.taotao.proxy.service.OrderService;
import com.taotao.proxy.service.impl.OrderServiceImpl;
/**
* @Author: wangjin
* @CreateTime: 2022-07-05 22:25
*/
public class Test03 {
public static void main(String[] args) {
OrderService orderService=new JdkInvocationHandler(new OrderServiceImpl()).getProxy();
orderService.addOrder("taotao");
}
}
動態(tài)代理與靜態(tài)代理的區(qū)別
動態(tài)代理不需要寫代理類對象,通過程序自動生成,而靜態(tài)代理需要我們自己寫代理類對象。