领先一步
VMware 提供培训和认证,以加速你的进步。
了解更多欢迎来到又一期的 *你可能不需要另一个库来实现它* (YMNNALFT)! 自 2016 年以来,我花了很多时间在 我的 Spring Tips 视频中阐明(或者试图阐明!)Spring 生态系统中一些更大的机会。然而,今天,我以不同的精神来到你面前,希望专注于那些小而有时隐藏的宝石,它们可以完成出色的工作,并且可能会让你免于额外的第三方依赖及其隐含的复杂性。
我们都遇到过这种情况。你想要一些日常的字符串操作例程,所以你将其提取到一个单独的抽象类中,并将其公开为一个 static
方法。然后,有一些工厂方法用于构建 java.util.Collection<T>
,因此你将其提取到一个单独的类中,并将其公开为一个 static
方法。最终,你在代码库中散布着这些东西的集合,它们之间几乎没有凝聚力。毕竟,没有什么太多可说的,对吧? 这些本质上只是全局函数,而不是有状态对象上的真正方法,本身。
并不是说构建你自己的静态方法本质上是错误的,只要你以一些约定来对待它们。 例如,我们通常使用带有静态方法的抽象类。
这一切都始于如此无害。 当然,事实确实如此。 你知道这个周期。 首先,是一个孤立类中的一些方法,被困在一个公司范围内的工件存储库中的 jar 中。 然后有类,复数。 现在包已经进入视野。 包是麻烦! 你将开始意识到最好对组织进行一些思考,否则事情会很快失控。 你开始接受拉取请求。 在某些时候,会出现重大更改,并且手持干草叉的开发人员会在你的门口排队。 你想知道为什么每个人都一直在上班时削减你的轮胎。 太多了! 所以你让公司开源你正在起步的模块。 现在是世界的问题! 就像电子宠物和真人秀一样,没有尽头。 那个广阔的世界? 好吧,那个广阔的世界喜欢在点发布中进行重大更改,并且他们会爱你的!
也许吧。
还有另一种方法。
市面上有很多质量参差不齐的第三方实用程序库:GS Collections、Apache Commons、Guava 等。这里不乏选择。你知道 Spring 本身在框架中提供了几个实用程序类,可能会让你免于依赖吗? 我并不是说它们会完成你可以从杰出竞争对手那里获得的一切,但你可能会感到惊讶! 此示例将查看其中的一些实用程序类,但在类路径上还有许多其他实用程序类。 你通常可以通过进入你的 IDE 并在类搜索中搜索 *Utils
或在文件搜索中搜索 *Utils.java
来找到它们。 让我们来看一些。
org.springframework.boot
: spring-boot-starter
这是代码
package bootiful.utils;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.Bean;
import org.springframework.core.ResolvableType;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jmx.support.JmxUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.*;
import javax.annotation.PostConstruct;
import java.beans.PropertyDescriptor;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Serializable;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.*;
@Log4j2
@SpringBootApplication
public class BootifulApplication {
@Data
@AllArgsConstructor
@Component
public static class DemoClass {
@PostConstruct
public void begin() {
log.info("begin()");
}
private final List<Map<String, Object>> list = new ArrayList<>();
}
@Bean
ApplicationListener<ApplicationReadyEvent> ready(DemoClass demo) {
return event -> {
Assert.notNull(demo.getList(), "the list can't be null");
beansUtils(demo);
classUtils();
systemPropertyUtils();
fileCopyUtils();
aop(demo);
reflection();
ensure();
collections();
serialize();
};
}
private void ensure() {
int counter = 2;
Assert.state(counter == 2, () -> "the counter should be 2 or more. Was " + counter);
Assert.hasText("Hello, world!", () -> "this string should be a non-null, non-empty String");
}
private void reflection() {
ReflectionUtils.doWithFields(DemoClass.class, field -> log.info("field = " + field.toString()));
ReflectionUtils.doWithMethods(DemoClass.class, method -> log.info("method = " + method.toString()));
Field list = ReflectionUtils.findField(DemoClass.class, "list");
log.info(Objects.requireNonNull(list).toString());
ResolvableType rt = ResolvableType.forField(list);
log.info(rt.toString());
}
private void aop(DemoClass demoClass) {
Class<?> targetClass = AopUtils.getTargetClass(demoClass);
log.info("Class<?> is " + targetClass);
log.info("is AOP proxy? " + AopUtils.isAopProxy(demoClass));
log.info("is CGlib proxy? " + AopUtils.isCglibProxy(demoClass));
}
private void collections() {
Collection<String> names = Arrays.asList("Tammie", "Kimly", "Josh");
boolean contains = CollectionUtils.containsAny(names, Arrays.asList("Josh"));
Assert.state(contains, () -> "one or more of the names in " + names.toString() + " should be present");
}
private void serialize() {
Customer in = new Customer(593232329, "Josh");
byte[] bytes = SerializationUtils.serialize(in);
Customer out = (Customer) SerializationUtils.deserialize(bytes);
Assert.state(out.getId() == in.getId() && out.getName().equals(in.getName()),
() -> "the " + Customer.class.getName() + " did not serialize correctlyy");
}
private void fileCopyUtils() {
Resource cpr = new ClassPathResource("/application.properties");
try (Reader r = new InputStreamReader(cpr.getInputStream())) {
String contents = FileCopyUtils.copyToString(r);
log.info("application.properties contents: " + contents);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private void systemPropertyUtils() {
String resolvedText = SystemPropertyUtils.resolvePlaceholders("my home directory is ${user.home}");
log.info("resolved text: " + resolvedText);
}
private void classUtils() {
Constructor<DemoClass> demoClassConstructor = ClassUtils.getConstructorIfAvailable(DemoClass.class);
log.info("demoClassConstructor: " + demoClassConstructor);
try {
DemoClass demoClass = demoClassConstructor.newInstance();
log.info("newInstance'd demoClass: " + demoClass);
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
private void beansUtils(DemoClass demo) {
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(demo.getClass());
for (PropertyDescriptor pd : descriptors) {
log.info("pd: " + pd.getName());
}
}
public static void main(String[] args) {
SpringApplication.run(BootifulApplication.class, args);
}
}
@Data
class Customer implements Serializable {
static final long serialVersionUID = 1L;
private int id;
private String name;
public Customer(int id, String name) {
this.id = id;
this.name = name;
}
}
此示例介绍了 Spring 生态系统中各种 Utils
类实现的什锦拼盘。 它着眼于
BeanUtils
- 用于处理 JavaBeans 的有用函数ClassUtils
- 用于以反射方式询问类型问题的有用函数SystemPropertyUtils
- 用于处理 System
属性的有用函数FileCopyUtils
- 用于复制 InputStream
和 OutputStream
实现的有用函数AopUtils
- 用于处理 Spring 的 AOP 代理的有用函数ReflectionUtils
- 用于广泛处理反射的有用函数Assert
- 用于帮助设计合同样式断言的有用函数CollectionUtils
- 用于处理各种 Java java.util.Collection
类型的有用函数SerializeUtils
- 用于处理 Java 序列化的有用函数这里有大量令人兴奋的东西,即使这个密集的例子甚至没有开始触及表面!
你喜欢这种一览无遗的宝石方法吗? 你学到了什么吗? 与往常一样,我渴望收到你的来信,所以 请在 Twitter 上发声 (@starbuxman) ! 我会带着另一期 YMNNALFT 回来,所以请务必不要错过。