当前位置: 首页 > news >正文

青岛网站建设 新视点10个暴利小生意创业

青岛网站建设 新视点,10个暴利小生意创业,wordpress添加自定义模板,1sose wordpress设计模式第二章(装饰器模式) ​ 装饰器模式(Decorator Pattern) 也称为包装模式(Wrapper Pattern) 是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于…

设计模式第二章(装饰器模式)

​ 装饰器模式(Decorator Pattern) 也称为包装模式(Wrapper Pattern) 是指在不改变原有对象的基础之上,将功能附加到对象上,提供了比继承更有弹性的替代方案(扩展原有对象的功能),属于结构型模式。装饰器模式的核心是功能扩展,使用装饰器模式可以透明且动态地扩展类的功能。

案例一

​ 需求背景,我们现在需要删除一个集合中的元素,但是我们需要记录了那些元素是被删除的,我们想想是不是需要一个 list来记录那些元素是被删除的呢,还需要有 Set的功能,那么就需要一个代理对象。

代码部分

public class HistorySet<E> implements Set<E> {//记录删除的元素List<E> removeList = new ArrayList<>();// 代理对象private final Set<E> delegate;public HistorySet(Set<E> delegate) {this.delegate = delegate;}@Overridepublic int size() {return delegate.size();}@Overridepublic boolean isEmpty() {return delegate.isEmpty();}@Overridepublic boolean contains(Object o) {return delegate.contains(o);}@Overridepublic Iterator<E> iterator() {return delegate.iterator();}@Overridepublic Object[] toArray() {return delegate.toArray();}@Overridepublic <T> T[] toArray(T[] a) {return delegate.toArray(a);}@Overridepublic boolean add(E e) {return delegate.add(e);}@Overridepublic boolean remove(Object o) {if (delegate.remove(o)) {// 记录被删除的元素removeList.add((E)o);return true;}return false;}@Overridepublic boolean containsAll(Collection<?> c) {return delegate.containsAll(c);}@Overridepublic boolean addAll(Collection<? extends E> c) {return delegate.addAll(c);}@Overridepublic boolean retainAll(Collection<?> c) {return delegate.retainAll(c);}@Overridepublic boolean removeAll(Collection<?> c) {return delegate.removeAll(c);}@Overridepublic void clear() {delegate.clear();}@Overridepublic String toString() {return delegate.toString() + ", 删除的元素:"+removeList;}
}

测试部分

    public static void main(String[] args) {Set<String> historySet1 = new HistorySet<>(new HashSet<>());Set<String> historySet = new HistorySet<>(historySet1);historySet.add("1");historySet.add("2");historySet.add("3");historySet.add("4");historySet.add("5");historySet.remove("2");historySet.remove("2");historySet.remove("3");historySet.remove("5");historySet.remove("5");System.out.println(historySet);}

在这里插入图片描述

思考部分

​ 装饰器的本质就是增强,自己的内部有一个需要被代理的对象,实际上调用的都是被代理对象的方法,我们不需要更新额外的更改,需要实现被代理对象的接口。那么就拥有和代理对象一样的功能了。

案例一

我们通过字节流读取一个读取一个pdf,这个文件大小为2.6m的大小,我们看传统的字节流读取需要花费多少时间。

代码部分

public static void main(String[] args) {File file = new File("E:\\技术文档\\springboot\\SpringBoot-1.pdf");long s = Instant.now().toEpochMilli();try (FileInputStream fileInputStream = new FileInputStream(file)){while (true) {int length = fileInputStream.read();if (length == -1) {break;}}System.out.println("耗时:"+(Instant.now().toEpochMilli() - s) + " 毫秒!");} catch (IOException e) {throw new RuntimeException(e);}}

在这里插入图片描述

思考部分

我们看到读取一个字节的文件花费了2.5秒的时间,那么这个耗时的动作在哪里呢。我们打开了read()

看到这个范围是 -1到255 个字节之间,那么也就是说每次只能读一个 255的字节的数据,频繁的读取增加了耗时

在这里插入图片描述

优化代码

我们利用装饰器模式,自己的内部有一个FileInputStream 我们利用现有的功能进行增强,只需要将buffer 扩大是不是就可以实现呢

public class BufferInputStream extends InputStream {private byte[] buffer = new byte[8024];// 读取的位置private int position = -1;//读取的容量private int capacity = -1;private final FileInputStream fileInputStream;public BufferInputStream(FileInputStream fileInputStream) {this.fileInputStream = fileInputStream;}@Overridepublic int read() throws IOException {if (buffCanRead()) {// buff 可以读取return readFromBuffer();}//刷新 bufferrefreshBuffer();if (!buffCanRead()) {return -1;}return readFromBuffer();}private int readFromBuffer() {return buffer[position++] & 0xFF;}private void refreshBuffer() throws IOException {capacity = this.fileInputStream.read(buffer);position = 0;}private boolean buffCanRead() {if (capacity == -1) {return false;}if (position == capacity) {return false;}return true;}

测试部分

public static void main(String[] args) {File file = new File("E:\\技术文档\\springboot\\SpringBoot-1.pdf");long s = Instant.now().toEpochMilli();try (BufferInputStream fileInputStream = new BufferInputStream(new FileInputStream(file))){while (true) {int length = fileInputStream.read();if (length == -1) {break;}}System.out.println("耗时:"+(Instant.now().toEpochMilli() - s) + " 毫秒!");} catch (IOException e) {throw new RuntimeException(e);}}

在这里插入图片描述

实战部分

我们平时使用@ResponseBody 注解后,自动会解析为对象,那么我们能否在对象里面增加一个自己的属性呢。

前言

​ 我们创建一个springboot的工程,在接口上定义自己的注解。最终达到增加一个时间戳的值放进去,那么我们一步一步的debug 进去

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"><modelVersion>4.0.0</modelVersion><groupId>com.fashion</groupId><artifactId>decorator_pattern-boot</artifactId><version>0.0.1-SNAPSHOT</version><name>decorator_pattern-boot</name><description>decorator_pattern-boot</description><properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring-boot.version>3.4.1</spring-boot.version><maven.compiler.source>17</maven.compiler.source><maven.compiler.target>17</maven.compiler.target><java.version>17</java.version></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><version>1.18.30</version></dependency></dependencies><dependencyManagement><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-dependencies</artifactId><version>${spring-boot.version}</version><type>pom</type><scope>import</scope></dependency></dependencies></dependencyManagement></project>

controller部分

    @PostMappingpublic Map<String,Object> origin1(@RequestBody Map<String,Object> json) {return json;}POST http://localhost:8080/api
Content-Type: application/json{"name": "张三","age": 18
}

思考部分

  • 我们标记@RequestBody 注解后,是如何将参数组装起来的呢
  • @RequestBody 在何处被使用了呢
  • 找到 HandlerMethodArgumentResolverComposite 类

@RequestBody 参数解析源码部分

在这里插入图片描述

- com.fashion.decorator_patternboot.controller.DecoratorController#origin- org.springframework.web.method.support.InvocableHandlerMethod#doInvoke- org.springframework.web.method.support.InvocableHandlerMethod#invokeForRequest- org.springframework.web.method.support.InvocableHandlerMethod#getMethodArgumentValues- org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#getArgumentResolver

在这里插入图片描述

在这里插入图片描述

​ 至此我们找到了 HandlerMethodArgumentResolverComposite 所属类,我们看到这个类的结构,是不是就一个装饰器模式的使用,肚子里面有一堆解析器

HandlerMethodArgumentResolver

​ 该类为解析器的顶层入口,里面只有两个方法,一个是否支持,另外一个解释如何解析数据。
在这里插入图片描述

RequestResponseBodyMethodProcessor

我们看到该类继承了 extends AbstractMessageConverterMethodProcessor,里面实际上是实现了HandlerMethodArgumentResolver,那么我们可以得到 supportsParameter以及 resolveArgument 方法。

  • @Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(RequestBody.class);}
    
  • @Override
    @Nullable
    public Object resolveArgument(MethodParameter parameter, @Nullable ModelAndViewContainer mavContainer,NativeWebRequest webRequest, @Nullable WebDataBinderFactory binderFactory) throws Exception {parameter = parameter.nestedIfOptional();Object arg = readWithMessageConverters(webRequest, parameter, parameter.getNestedGenericParameterType());if (binderFactory != null) {String name = Conventions.getVariableNameForParameter(parameter);ResolvableType type = ResolvableType.forMethodParameter(parameter);WebDataBinder binder = binderFactory.createBinder(webRequest, arg, name, type);if (arg != null) {validateIfApplicable(binder, parameter);if (binder.getBindingResult().hasErrors() && isBindExceptionRequired(binder, parameter)) {throw new MethodArgumentNotValidException(parameter, binder.getBindingResult());}}if (mavContainer != null) {mavContainer.addAttribute(BindingResult.MODEL_KEY_PREFIX + name, binder.getBindingResult());}}return adaptArgumentIfNecessary(arg, parameter);
    }
    

增加自定义注解

TimestampBody 注解类,该类用来做一个标记。

@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface TimestampBody {
}

自定义解析器

public class TimeStampResponseBodyMethodProcessor implements HandlerMethodArgumentResolver {private RequestResponseBodyMethodProcessor processor;@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(TimestampBody.class);}@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {Object retObj = processor.resolveArgument(parameter, mavContainer, webRequest, binderFactory);if (retObj instanceof Map) {((Map) retObj).put("timestamp",System.currentTimeMillis()+"");}return retObj;}}

如何将我们自己的解析器放到解析器组合中

相当于我们需要把 TimeStampResponseBodyMethodProcessor 得类放到 HandlerMethodArgumentResolverComposite 的 argumentResolvers 中。

debug 断点

在这里插入图片描述

  1. org.springframework.web.method.support.HandlerMethodArgumentResolverComposite#addResolvers(java.util.List<? extends org.springframework.web.method.support.HandlerMethodArgumentResolver>)
  2. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#afterPropertiesSet
  3. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getDefaultArgumentResolvers

在这里插入图片描述

在这里插入图片描述

getCustomArgumentResolvers

那么我们断点一下,看这个方法在什么时候进行调用的呢?

  1. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#getCustomArgumentResolvers
  2. org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#setCustomArgumentResolvers
  3. org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#requestMappingHandlerAdapter
  4. org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport#getArgumentResolvers
  5. org.springframework.web.servlet.config.annotation.DelegatingWebMvcConfiguration#addArgumentResolvers

在这里插入图片描述

在这里插入图片描述

至此我们来到了DelegatingWebMvcConfiguration 的类,这个类的肚子里面还有一个 WebMvcConfigurerComposite mvc 的组合

在这里插入图片描述

在这里插入图片描述

我们看到是通过spring注入的方式注入进去的,那么我们只需要自己实现一个 WebMvcConfigurer的接口,那么是不是就可以进去了 。

自定义process 实现

@Configuration
public class MyWebMvcConfigurer implements WebMvcConfigurer {@AutowiredApplicationContext applicationContext;@Overridepublic void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {resolvers.add(new TimeStampResponseBodyMethodProcessor(applicationContext));}
}
public class TimeStampResponseBodyMethodProcessor implements HandlerMethodArgumentResolver {private final ApplicationContext applicationContext;private RequestResponseBodyMethodProcessor processor;public TimeStampResponseBodyMethodProcessor(ApplicationContext applicationContext) {this.applicationContext = applicationContext;}@Overridepublic boolean supportsParameter(MethodParameter parameter) {return parameter.hasParameterAnnotation(TimestampBody.class);}@Overridepublic Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {setupProcessor();Object retObj = processor.resolveArgument(parameter, mavContainer, webRequest, binderFactory);if (retObj instanceof Map) {((Map) retObj).put("timestamp",System.currentTimeMillis()+"");}return retObj;}private void setupProcessor() {if (this.processor != null) {return;}List<HandlerMethodArgumentResolver> argumentResolvers = this.applicationContext.getBean(RequestMappingHandlerAdapter.class).getArgumentResolvers();for (HandlerMethodArgumentResolver resolver : argumentResolvers) {if (resolver instanceof RequestResponseBodyMethodProcessor) {this.processor = (RequestResponseBodyMethodProcessor) resolver;return;}}}
}
查看HandlerMethodArgumentResolverComposite 是否有我们这个对象

在这里插入图片描述

测试结果

    @PostMappingpublic Map<String,Object> origin(@TimestampBody Map<String,Object> json) {return json;}

在这里插入图片描述

总结部分

​ 特别感谢bi站的u主,学java的生生,我断点不熟练,导致来回的看调用栈。视频也是看了好几遍,动手尝试,现在有一些自己的理解

http://www.dtcms.com/a/412641.html

相关文章:

  • I/O详解
  • 如何将域名指向网站学习前端的网站
  • 企业应如何进行网站建设vi设计的基本要素
  • 鞍山制作网站做网站界面尺寸
  • 英文网站建设 潍坊数据库和网站建设的论文
  • 兰州市城乡建设局网站公布的信息网站开发环境windows7的优点
  • 承德网站网络营销方式选择考虑的因素
  • 萧山建设局网站用手机开发app
  • Wordpress标签与分类seo技术是什么意思
  • 秦皇岛学网站建设湖北工业信息化网站备案
  • 有关电子商务网站建设的 论文赣州建设网站公司
  • 重庆网站建设坤思特自豪地采用wordpress
  • 现在网站如何做优化西安到北京防疫政策
  • 数据库里建设好的网站为什么外网进不去网站网站怎么做成手机版
  • 大连网站建设服务公司wordpress商城主题模板下载
  • 石家庄网络建设seo快速排名源码
  • 不止Docker:探索容器化安装的四种前沿新玩法
  • 网站建设衤金手指谷哥十四wordpress 豆瓣
  • 网站建设公司厦门有哪些网站开发可选择的方案
  • 华清远见25072班C++学习day3
  • 南通做外贸网站网站建设视频格式
  • 网站搭建的人如何识别网页用什么网站做的
  • 下什么软件做网站wordpress升级设置密码
  • 九、Spring
  • 商业门户网站有哪些河南seo推广
  • HTML可以做彩票网站吗1元购网站怎么做
  • 深圳辰硕网站优化东莞网络营销推广公司
  • 大连 响应式网站珠海做网站的公司有哪些
  • 第三十五天:寻找质数
  • 专门做油画交流的网站泰安网站建设工作室