简介
我们知道,java中的Optional是解决臭名昭著的空指针异常,在spring的依赖注入中,如果没有找到Bean也会抛异常,就算将required写为false,后面也会需要判空
在spring中也支持Optional的依赖注入
创建Optional
java8中创建Optional的api如下
Optional.of(T t) 创建一个 Optional 对象,参数 t 必须非空,如果你把 null 值作为参数传递进去,of() 方法会抛出 NullPointerException
Optional.empty() 创建一个空的 Optional 实例
Optional.ofNullable(T t) 创建一个 Optional 对象,如果参数 t 为非空,返回 Optional 描述的指定值,否则返回空的 Optional
使用
如果是一个普通的Bean注入,但是却找不到Bean,那么会抛异常,例如
为了好输出内容,使用构造器注入
@Component
public class OptionalBean {public OptionalBean(String obj) {System.out.println(obj);}}
报错
No qualifying bean of type 'java.lang.String' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
如果将字段类型Optional那么就不会报错
@Component
public class OptionalBean {public OptionalBean(Optional<String> obj) {System.out.println(obj);}
}输出
Optional.empty
源码解析
代码在依赖描述器处理逻辑里面,至于什么是依赖描述器后面文章详细介绍
org.springframework.beans.factory.support.DefaultListableBeanFactory#resolveDependency
public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,@Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {// 略...// 所需要的类型是Optionalif (Optional.class == descriptor.getDependencyType()) {return createOptionalDependency(descriptor, requestingBeanName);}// 略...
}private Optional<?> createOptionalDependency(DependencyDescriptor descriptor, @Nullable String beanName, final Object... args) {// 构造一个NestedDependencyDescriptorDependencyDescriptor descriptorToUse = new NestedDependencyDescriptor(descriptor) {@Overridepublic boolean isRequired() { // 重写isRequired,表示不需要真正找到Beanreturn false;}@Overridepublic Object resolveCandidate(String beanName, Class<?> requiredType, BeanFactory beanFactory) {return (!ObjectUtils.isEmpty(args) ? beanFactory.getBean(beanName, args) :super.resolveCandidate(beanName, requiredType, beanFactory));}};// 依赖注入Object result = doResolveDependency(descriptorToUse, beanName, null, null);// 如果result为null,那么将构造一个空的Optional,否则也是返回一个Optional但是非空return (result instanceof Optional ? (Optional<?>) result : Optional.ofNullable(result));
}// NestedDependencyDescriptor类
private static class NestedDependencyDescriptor extends DependencyDescriptor {public NestedDependencyDescriptor(DependencyDescriptor original) {super(original);// 嵌套级别+1increaseNestingLevel();}}
// 嵌套级别+1
public void increaseNestingLevel() {this.nestingLevel++;this.resolvableType = null;if (this.methodParameter != null) {this.methodParameter = this.methodParameter.nested();}
}
从上面逻辑就可以看出,其实就是不管找没找到值都是返回一个Optional,不会强制一定要找到Bean
那么如果是一个Optional,该怎么知道真实的类型呢。跟上面构造的NestedDependencyDescriptor有关系,嵌套级别+1
下面是获取Bean类型的代码
public Class<?> getDependencyType() {if (this.field != null) {// 如果是Optional,这里nestingLevel为2,表示有一层嵌套if (this.nestingLevel > 1) {Type type = this.field.getGenericType();// 循环嵌套层数,拿到真实的类型for (int i = 2; i <= this.nestingLevel; i++) {if (type instanceof ParameterizedType) {// 拿到真实的类型Type[] args = ((ParameterizedType) type).getActualTypeArguments();type = args[args.length - 1];}}if (type instanceof Class) {return (Class<?>) type;}else if (type instanceof ParameterizedType) {Type arg = ((ParameterizedType) type).getRawType();if (arg instanceof Class) {return (Class<?>) arg;}}return Object.class;}else {return this.field.getType();}}else {return obtainMethodParameter().getNestedParameterType();}
}
以上就是spring对Optional的处理了
欢迎关注,学习不迷路!