栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

深入SpringBoot源码(十一)SpringApplication与Environment的绑定(下)

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

深入SpringBoot源码(十一)SpringApplication与Environment的绑定(下)

上一章讲到了SpringApplication的bindToSpringApplication的Binder.get(environment)方法, 这章接着讲Binder的bind方法。

bindToSpringApplication方法通过Binder.get(environment)方法得到了Binder实例,再调用bind(String name, Bindable target)方法使用此 binder的property sources绑定指定的目标Bindable。

	public  BindResult bind(String name, Bindable target) {
		return bind(ConfigurationPropertyName.of(name), target, null);
	}

	public  BindResult bind(ConfigurationPropertyName name, Bindable target, BindHandler handler) {
		T bound = bind(name, target, handler, false);
		return BindResult.of(bound);
	}
	
	private  T bind(ConfigurationPropertyName name, Bindable target, BindHandler handler, boolean create) {
		Assert.notNull(name, "Name must not be null");
		Assert.notNull(target, "Target must not be null");
		handler = (handler != null) ? handler : this.defaultBindHandler;
		Context context = new Context();
		return bind(name, target, handler, context, false, create);
	}

	private  T bind(ConfigurationPropertyName name, Bindable target, BindHandler handler, Context context,
			boolean allowRecursiveBinding, boolean create) {
		try {
			Bindable replacementTarget = handler.onStart(name, target, context);
			if (replacementTarget == null) {
				return handleBindResult(name, target, handler, context, null, create);
			}
			target = replacementTarget;
			Object bound = bindObject(name, target, handler, context, allowRecursiveBinding);
			return handleBindResult(name, target, handler, context, bound, create);
		}
		catch (Exception ex) {
			return handleBindError(name, target, handler, context, ex);
		}
	}

Bindable是可以由Binder绑定的源,其ofInstance方法使用与该实例相等的现有值创建指定实例类型的新Bindable。

	public static  Bindable ofInstance(T instance) {
		Assert.notNull(instance, "Instance must not be null");
		Class type = (Class) instance.getClass();
		return of(type).withExistingValue(instance);
	}
	
	
	public static  Bindable of(Class type) {
		Assert.notNull(type, "Type must not be null");
		return of(ResolvableType.forClass(type));
	}

	public static  Bindable of(ResolvableType type) {
		Assert.notNull(type, "Type must not be null");
		ResolvableType boxedType = box(type);
		return new Bindable<>(type, boxedType, null, NO_ANNOTATIONS, NO_BIND_RESTRICTIONS);
	}

	private static ResolvableType box(ResolvableType type) {
		Class resolved = type.resolve();
		if (resolved != null && resolved.isPrimitive()) {
			Object array = Array.newInstance(resolved, 1);
			Class wrapperType = Array.get(array, 0).getClass();
			return ResolvableType.forClass(wrapperType);
		}
		if (resolved != null && resolved.isArray()) {
			return ResolvableType.forArrayComponent(box(type.getComponentType()));
		}
		return type;
	}

调用Bindable类的构造方法时,传入的参数如下:

在调用bind(ConfigurationPropertyName name, Bindable target, BindHandler handler, Context context, boolean allowRecursiveBinding, boolean create)方法时,传入的参数如下:

handleBindResult方法的源码:

	private  T handleBindResult(ConfigurationPropertyName name, Bindable target, BindHandler handler,
			Context context, Object result, boolean create) throws Exception {
		if (result != null) {
			result = handler.onSuccess(name, target, context, result);
			result = context.getConverter().convert(result, target);
		}
		if (result == null && create) {
			result = create(target, context);
			result = handler.onCreate(name, target, context, result);
			result = context.getConverter().convert(result, target);
			Assert.state(result != null, () -> "Unable to create instance for " + target.getType());
		}
		handler.onFinish(name, target, context, result);
		return context.getConverter().convert(result, target);
	}

获取到的bound为null:

BindResult用于返回Binder绑定操作结果的容器对象,可能包含成功绑定的对象或空结果。BindResult的of方法:

	static  BindResult of(T value) {
		if (value == null) {
			return (BindResult) UNBOUND;
		}
		return new BindResult<>(value);
	}
	
	private static final BindResult UNBOUND = new BindResult<>(null);

	private BindResult(T value) {
		this.value = value;
	}


在执行完bindToSpringApplication方法后,会判断当前环境是否是自定义环境,如果是,则会调用convertEnvironment方法:

	
	@Deprecated
	public StandardEnvironment convertEnvironment(ConfigurableEnvironment environment) {
		return new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment,
				deduceEnvironmentClass());
	}

由于绑定后的环境可能会被修改,所以需要再次执行ConfigurationPropertySources.attach方法

SpringApplication的configureIgnoreBeanInfo方法:

	private void configureIgnoreBeanInfo(ConfigurableEnvironment environment) {
		if (System.getProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME) == null) {
			Boolean ignore = environment.getProperty("spring.beaninfo.ignore", Boolean.class, Boolean.TRUE);
			System.setProperty(CachedIntrospectionResults.IGNORE_BEANINFO_PROPERTY_NAME, ignore.toString());
		}
	}

CachedIntrospectionResults是为Java 类缓存JavaBeans PropertyDescriptor信息的类,该类不适合应用程序代码直接使用。Spring自己在应用程序ClassLoader中缓存 bean 描述符所必需的,而不是依赖于 JDK 的系统范围的BeanInfo缓存(以避免在共享 JVM 中个别应用程序关闭时泄漏)。信息是静态缓存的,因此我们不需要为我们操作的每个 JavaBean 创建此类的新对象。因此,该类实现了工厂设计模式,使用私有构造函数和静态forClass(Class)工厂方法来获取实例。

	
	public static final String IGNORE_BEANINFO_PROPERTY_NAME = "spring.beaninfo.ignore";

	private Banner printBanner(ConfigurableEnvironment environment) {
		if (this.bannerMode == Banner.Mode.OFF) {
			return null;
		}
		ResourceLoader resourceLoader = (this.resourceLoader != null) ? this.resourceLoader
				: new DefaultResourceLoader(null);
		SpringApplicationBannerPrinter bannerPrinter = new SpringApplicationBannerPrinter(resourceLoader, this.banner);
		if (this.bannerMode == Mode.LOG) {
			return bannerPrinter.print(environment, this.mainApplicationClass, logger);
		}
		return bannerPrinter.print(environment, this.mainApplicationClass, System.out);
	}

printBanner方法用于打印Spring应用程序横幅


这里获取到banner是SpringBootBanner

class SpringBootBanner implements Banner {

	private static final String[] BANNER = { "", "  .   ____          _            __ _ _",
			" /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \", "( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \",
			" \\/  ___)| |_)| | | | | || (_| |  ) ) ) )", "  '  |____| .__|_| |_|_| |_\__, | / / / /",
			" =========|_|==============|___/=/_/_/_/" };

	private static final String SPRING_BOOT = " :: Spring Boot :: ";

	private static final int STRAP_LINE_SIZE = 42;

	@Override
	public void printBanner(Environment environment, Class sourceClass, PrintStream printStream) {
		for (String line : BANNER) {
			printStream.println(line);
		}
		String version = SpringBootVersion.getVersion();
		version = (version != null) ? " (v" + version + ")" : "";
		StringBuilder padding = new StringBuilder();
		while (padding.length() < STRAP_LINE_SIZE - (version.length() + SPRING_BOOT.length())) {
			padding.append(" ");
		}

		printStream.println(AnsiOutput.toString(AnsiColor.GREEN, SPRING_BOOT, AnsiColor.DEFAULT, padding.toString(),
				AnsiStyle.FAINT, version));
		printStream.println();
	}

}

printBanner运行后的结果如下:

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/820803.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号