1. 代理模式(Proxy Pattern)
代理模式(Proxy Pattern) ,给某一个对象提供一个代理,并由代理对象控制对原对象的引用,对象结构型模式。这种也是静态代理

代理模式包含如下角色:
Subject: 抽象主体角色(抽象类或接口)
Proxy: 代理主体角色(代理对象类)
RealSubject: 真实主体角色(被代理对象类)
2. 静态代理
- 静态代理就是装饰器模式
- 装饰器模式是代理模式的一种
Subject: 抽象主体角色(抽象类或接口)
/*** 抽象主体 被代理角色*/public interface ManTikTok {void tiktok();}
Proxy: 代理主体角色(代理对象类)
/*** 代理一般和被代理对象属于同一个接口* 静态代理就是装饰器模式* 装饰器模式是代理模式的一种*/public class TiktokProxy implements ManTikTok{//被代理对象private MiTikTok miTikTok;public TiktokProxy(MiTikTok miTikTok) {this.miTikTok = miTikTok;}@Overridepublic void tiktok() {System.out.println("增强功能");miTikTok.tiktok();}}
RealSubject: 真实主体角色(被代理对象类)
/*** subject 主体**/public class MiTikTok implements ManTikTok{@Overridepublic void tiktok() {System.out.println("雷军正在直播");}}
测试
public static void main(String[] args) {TiktokProxy tiktokProxy = new TiktokProxy(new MiTikTok());tiktokProxy.tiktok();}
3. JDK动态代理
利用JDK动态代理 反射增强
Subject: 抽象主体角色(抽象类或接口)
/*** 抽象主体 被代理角色*/public interface ManTikTok {void tiktok();}
public interface SellTiktok {void send();}
Proxy: 代理主体角色(代理对象类)
public class JdkTiktokProxy<T> implements InvocationHandler {private T target;//接受被代理对象public JdkTiktokProxy(T target) {this.target = target;}/*** 获取被代理对象的 代理对象** @param t* @param <T>* @return*/public static <T> T getProxy(T t) {/*** ClassLoader loader, 当前被代理的类加载器* Class<?>[] interfaces, 当前被代理对象所实现的所有接口 必须要有接口 如果无则会报异常 代理对象无法创建* InvocationHandler h 当前被代理对象执行目标方法的时候我们使用h可以定义拦截增强方法*/Object o = Proxy.newProxyInstance(t.getClass().getClassLoader(),t.getClass().getInterfaces(),new JdkTiktokProxy<>(t));return (T) o;}/*** 定义目标方法的拦截逻辑:每个方法都会进来的** @param proxy* @param method* @param args* @return* @throws Throwable*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {//反射执行System.out.println("被代理对象原身方法被执行");Object invoke = method.invoke(target, args);System.out.println("返回值" + invoke);return invoke;}}
RealSubject: 真实主体角色(被代理对象类)
/*** subject 主体**/public class MiTikTok implements ManTikTok,SellTiktok {@Overridepublic void tiktok() {System.out.println("雷军正在直播");}@Overridepublic void send() {System.out.println("卖货 只要999");}public void self(){System.out.println("自身方法");}}
测试方法
/*** 动态代理模式* JDK要求被代理对象必须要有接口**/public class MainTest {public static void main(String[] args) {ManTikTok miTikTok = new MiTikTok();ManTikTok proxy = JdkTiktokProxy.getProxy(miTikTok);proxy.tiktok();System.out.println("---------------");SellTiktok sellTikTok = (SellTiktok)miTikTok;SellTiktok proxy1 = JdkTiktokProxy.getProxy(sellTikTok);proxy1.send(); //只能调用某个接口的实现方法System.out.println("---------------");MiTikTok miTikTok1 = (MiTikTok) miTikTok;//无法代理对象本类自己的方法 proxy只能转成接口类// MiTikTok proxy2 = JdkTiktokProxy.getProxy(miTikTok1);miTikTok1.self();System.out.println(Arrays.asList(miTikTok1.getClass().getInterfaces()));}}
4. cglib动态代理
在pom.xml导入cglib依赖
<dependencies><dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.1</version></dependency></dependencies>
cglib不依赖于接口代理反射,他会根据代理对象去继承一个新类,从而代理这个对象。
Proxy: 代理主体角色(代理对象类)
public class CglibProxy {//为任意对象创建代理public static <T> T crateProxy(T t) {//1. 创建一个增强器Enhancer enhancer = new Enhancer();//2.设置增强哪个类的功能 增强器为这个类动态创建一个子类enhancer.setSuperclass(t.getClass());//3.设置回调enhancer.setCallback(new MethodInterceptor() {@Overridepublic Object intercept(Object o, Method method //为了能获取原方法的一些原数据信息, Object[] objects, MethodProxy methodProxy) throws Throwable {//编写拦截逻辑System.out.println("cglib 代理");//当前方法的信息// method.getAnnotatedReturnType();//目标方法进行执行 原对象的方法Object invoke = methodProxy.invokeSuper(o, objects);return invoke;}});//创建代理对象Object o = enhancer.create();return (T)o;}}
RealSubject: 真实主体角色(被代理对象类)
/*** subject 主体**/public class MiTikTok {public void self(){System.out.println("自身方法");}}
测试类
public class CglibTest {public static void main(String[] args) {//原对象都不用newMiTikTok miTikTok = new MiTikTok();MiTikTok proxy = CglibProxy.crateProxy(miTikTok);proxy.self();}}
5. 应用场景
MyBatis的mapper到底是什么?怎么生成的?
动态代理
UserMapper、CityMapper,mybatis帮我们写实现MapperProxy
Alibaba Seata的DataSourceProxy是什么?
DruidDataSource存在的Proxy模式
- 监控链…
