博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
设计模式之代理模式
阅读量:3913 次
发布时间:2019-05-23

本文共 11684 字,大约阅读时间需要 38 分钟。

定义:代理模式(Proxy Pattern)是指为其他对象提供一种代理,以控制对这个对象的访问

代理对象在客户端和目标对象之间起到中介作用

属于结构型设计模式

适用场景

保护目标对象
增强目标对象

优点

代理模式能将代理对象与真实被调用的目标对象分离
一定程度上降低了系统的耦合程度,易于扩展
代理可以起到保护目标对象的作用
增强目标对象的职责

缺点

代理模式会造成系统设计中类的数目增加
在客户端和目标对象之间增加了一个代理对象,请求处理速度变慢
增加了系统的复杂度

Spring中的代理选择原则

1.当Bean有实现接口时,Spring就会用JDK的动态代理
2.当Bean没有实现接口时,Spring选择CGlib.
3.Spring 可以通过配置强制使用CGlib,只需在Spring的配置文件中加入如下代码:
静态代理和动态代理的跟本区别
静态代理:硬编码,手动注入,手动拿到目标对象的引用,手动调用代理目标的方法
动态代理:具有更强的扩展性,自动注入,自动生成一个新的类(同一个继承体系)
特征:

拿到代理目标对象的引用

实现功能增强
保护目标对象

例子

简单代理
public interface ISubject {
void request();}
public class RealSubject implements ISubject{
@Override public void request() {
System.out.println("real service is called"); }}
public class Proxy implements ISubject{
private ISubject subject; @Override public void request() {
before(); subject.request(); after(); } public Proxy(ISubject subject){
this.subject = subject; } public void before(){
System.out.println("called before request()."); } public void after(){
System.out.println("called after request()."); }}
public class Client {
public static void main(String[] args) {
Proxy proxy = new Proxy(new RealSubject()); proxy.request(); }}
简单静态代理
public interface IPerson {
void findLove();}
public class LisiSon implements IPerson {
@Override public void findLove() {
System.out.println("要求: 肤白貌美大长腿"); }}
只能代理一个,所以这个代理不了
public class Wangwu implements IPerson {
@Override public void findLove() {
System.out.println("合适就好"); }}
代理类
public class Lisi implements IPerson {
private LisiSon lisiSon; public Lisi(LisiSon lisiSon){
this.lisiSon = lisiSon; } @Override public void findLove() {
System.out.println("开始物色"); lisiSon.findLove(); System.out.println("开始交往"); }}
public class Test {
public static void main(String[] args) {
Lisi lisi = new Lisi(new LisiSon()); //Lisi lisi1 = new Lisi(new Wangwu()); 代理不了 lisi.findLove(); }}
动态代理
jdk动态代理
public interface IPerson {
void findLove(); void buySafe();}
public class LisiSon implements IPerson {
@Override public void findLove() {
System.out.println("要求: 肤白貌美大长腿"); } @Override public void buySafe() {
System.out.println("购买30万保险"); }}
public class Wangwu implements IPerson {
@Override public void findLove() {
System.out.println("要求: 有车有房学历高"); } @Override public void buySafe() {
System.out.println("购买100万保险"); }}
public class JdkMatchmaker implements InvocationHandler {
private IPerson target; public IPerson getInstance(IPerson target){
this.target = target; Class
clazz = target.getClass(); return (IPerson) Proxy.newProxyInstance(clazz.getClassLoader(),clazz.getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before(); Object invoke = method.invoke(this.target, args); after(); return invoke; } private void after() {
System.out.println("开始物色"); } private void before() {
System.out.println("开始交往"); }}
客户端调用
public class Test {
public static void main(String[] args) {
JdkMatchmaker jdkMatchmaker = new JdkMatchmaker(); IPerson instance = jdkMatchmaker.getInstance(new LisiSon()); instance.findLove(); instance.buySafe(); // IPerson instance1 = jdkMatchmaker.getInstance(new Wangwu()); instance1.findLove(); instance1.buySafe(); //为了看一眼JDK动态生成的代理类 byte[] $Proxy0s = ProxyGenerator.generateProxyClass("$Proxy0", new Class[]{
IPerson.class}); try {
FileOutputStream os = new FileOutputStream("/opt/workspace/2020/09/22/$Proxy0.class"); os.write($Proxy0s); os.close(); } catch (IOException e) {
e.printStackTrace(); } }}
Cglib代理类使用
public class LisiSon {
public void findLove() {
System.out.println("要求: 肤白貌美大长腿"); } public void buySafe() {
System.out.println("购买30万保险"); }}
public class CglibMatchmaker implements MethodInterceptor {
public Object getInstance(Class
clazz){
Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(clazz); enhancer.setCallback(this); return enhancer.create(); } private void after() {
System.out.println("开始交往"); } private void before() {
System.out.println("开始物色"); } @Override public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
before(); Object invoke = methodProxy.invokeSuper(o, objects); after(); return invoke; }}
public class Test {
public static void main(String[] args) {
//CGlib 采用继承的方式,覆盖父类的方法 //JDK 采用的实现方式,必须要求代理的目标对象一定要实现一个接口 //思想:都是通过生成字节码,重组成一个新的类 //JDK Proxy 对于用户而言,依赖更强,调用也更复杂 //Cglib 对目标类没有任何的要求 //CGlib 效率更高,性能也更高,低层没有用到反射 //JDK Proxy 生成逻辑较为简单,执行效率要低,每次都要用反射 //Cglib 有个坑,目标代理类不能有final修饰的方法,忽略final修饰的方法 //生成cglib的动态代理类,用于查看动态生成的代码 System.setProperty(DebuggingClassWriter.DEBUG_LOCATION_PROPERTY,"/opt/workspace/2020/09/22/.cglib_proxy_class"); LisiSon lisi = (LisiSon)new CglibMatchmaker().getInstance(LisiSon.class); lisi.findLove(); lisi.buySafe(); }}
自动手写一个JDK类似的动态代理
public interface MyInvocationHandler {
Object invoke(Object proxy, Method method, Object[] args) throws Throwable;}
public class MyClassLoader extends ClassLoader{
private File classPathFile; public MyClassLoader(){
String classPath = MyClassLoader.class.getResource("").getPath(); this.classPathFile = new File(classPath); } @Override protected Class
findClass(String name) throws ClassNotFoundException {
String className = MyClassLoader.class.getPackage().getName() + "." + name; if(classPathFile != null){
File classFile = new File(classPathFile,name.replaceAll("\\.","/") + ".class"); FileInputStream in = null; ByteArrayOutputStream out = null; try {
in = new FileInputStream(classFile); out = new ByteArrayOutputStream(); byte[] buff = new byte[1024]; int len; while ((len = in.read(buff)) != -1) {
out.write(buff, 0, len); } return defineClass(className, out.toByteArray(), 0, out.size()); }catch (Exception e){
e.printStackTrace(); } } return super.findClass(name); }}
public class MyProxy {
public static final String LN = "\r\n"; public static Object newProxyInstance(MyClassLoader loader, Class
[] interfaces, MyInvocationHandler h) throws IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
//1.动态生成源代码 String src = generateSrc(interfaces); //2.java文件输出到磁盘,保存为文件$Proxy0.java String filePath = MyProxy.class.getResource("").getPath(); File f = new File(filePath + "$Proxy0.java"); FileWriter fw = new FileWriter(f); fw.write(src); fw.flush(); fw.close(); //3.把.java文件编译成$Proxy0.class文件 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null); Iterable
javaFileObjects = standardFileManager.getJavaFileObjects(f); JavaCompiler.CompilationTask task = compiler.getTask(null, standardFileManager, null, null, null, javaFileObjects); task.call(); //4.把生成的.class文件加载到jvm中 Class proxyClass = loader.findClass("$Proxy0"); Constructor constructor = proxyClass.getConstructor(MyInvocationHandler.class); //5.返回新的代理对象 f.delete(); return constructor.newInstance(h); } private static String generateSrc(Class
[] interfaces) {
StringBuilder sb = new StringBuilder(); sb.append("package com.study.pattern.proxy.dynamicproxy.myproxy.proxy;" + LN); sb.append("import com.study.pattern.proxy.dynamicproxy.myproxy.client.IPerson;" + LN); sb.append("import java.lang.reflect.*;" + LN); sb.append("public final class $Proxy0 implements " + interfaces[0].getName() + "{" + LN); sb.append("MyInvocationHandler h;" + LN); sb.append("public $Proxy0(MyInvocationHandler h){ " + LN); sb.append("this.h = h;" + LN); sb.append("}" + LN); for(Method m : interfaces[0].getMethods()){
Class
[] params = m.getParameterTypes(); StringBuilder paramNames = new StringBuilder(); StringBuilder paramValues = new StringBuilder(); StringBuilder paramClasses = new StringBuilder(); for(int i = 0; i < params.length; i++){
} sb.append("public " + m.getReturnType().getName() + " " + m.getName() + "(){" + LN); sb.append("try{ " + LN); sb.append("Method m =" + interfaces[0].getName() + ".class.getMethod(\""+ m.getName() + "\",new Class[]{});" + LN); sb.append("this.h.invoke(this,m,new Object[]{});" + LN); sb.append("return;" +LN); sb.append("}catch (RuntimeException | Error var3) {" +LN); sb.append(" throw var3;" +LN); sb.append(" } catch (Throwable var4) {" +LN); sb.append(" throw new UndeclaredThrowableException(var4);" +LN); sb.append(" }"); sb.append("}" + LN); } sb.append("}"); return sb.toString(); }}
public interface IPerson {
void findLove(); void buySafe();}
public class LisiSon implements IPerson {
@Override public void findLove() {
System.out.println("要求: 肤白貌美大长腿"); } @Override public void buySafe() {
System.out.println("购买30万保险"); }}
public class MyMatchmaker implements MyInvocationHandler {
private IPerson target; public IPerson getInstance(IPerson target) throws NoSuchMethodException, IOException, ClassNotFoundException, IllegalAccessException, InstantiationException, InvocationTargetException {
this.target = target; Class
clazz = target.getClass(); return (IPerson) MyProxy.newProxyInstance(new MyClassLoader(),clazz.getInterfaces(),this); } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
before(); Object invoke = method.invoke(this.target, args); after(); return invoke; } private void after() {
System.out.println("开始物色"); } private void before() {
System.out.println("开始交往"); }}
public class Test {
public static void main(String[] args) throws NoSuchMethodException, IOException, ClassNotFoundException, IllegalAccessException, InvocationTargetException, InstantiationException {
MyMatchmaker myMatchmaker = new MyMatchmaker(); IPerson instance = myMatchmaker.getInstance(new LisiSon()); instance.findLove(); instance.buySafe(); }}

转载地址:http://ckjrn.baihongyu.com/

你可能感兴趣的文章
拥抱.NET 5,从自研微服务框架开始
查看>>
开源特训营 - Lesson 4 - 如何运营社区
查看>>
C# 中的 is 真的是越来越强大,越来越语义化
查看>>
简单理解CAP-BASE
查看>>
gRPC-微服务间通信实践
查看>>
Firefox 18周岁
查看>>
IdentityServer4系列 | 初识基础知识点
查看>>
自由软件基金会庆祝成立35周年
查看>>
网络知识 | 《图解TCP/IP》读书笔记(下)
查看>>
国产化之路-统信UOS /Nginx /Asp.Net Core+ EF Core 3.1/达梦DM8实现简单增删改查操作
查看>>
面试 .NET 开发,为什么也要考算法?
查看>>
BeetleX之TCP消息通讯Protobuf/TLS
查看>>
AA.Dapper升级了
查看>>
C#刷剑指Offer | 二叉树中和为某一值的路径
查看>>
你是个失败者,有什么资格说话?
查看>>
为什么我们总是「习惯性辩解」?
查看>>
.NET 异步解说
查看>>
Magicodes.IE 2.4发布
查看>>
程序员修神之路--它可能是分布式系统中最重要的枢纽
查看>>
如何理解Eating这个词?云原生与微服务专场介绍
查看>>