spring boot 源码
来源:互联网 发布:ug8.0车削加工编程 编辑:程序博客网 时间:2024/05/22 11:52
PropertySource和Enviroment http://blog.csdn.net/u011179993/article/details/51511364统一抽象资源---Resource http://blog.csdn.net/u011179993/article/details/51531140SpringApplicationRunListener及其周期 http://blog.csdn.net/u011179993/article/details/51555690BeanDefinition及读取、注册 http://blog.csdn.net/u011179993/article/details/51598567http://blog.csdn.net/u011179993/article/category/5623745BeanDefinitionRegistry 该类的作用主要是向注册表中注册 BeanDefinition 实例,完成 注册的过程。public interface BeanDefinitionRegistry extends AliasRegistry { // 关键 -> 往注册表中注册一个新的 BeanDefinition 实例 void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)throws BeanDefinitionStoreException; // 移除注册表中已注册的 BeanDefinition 实例 void removeBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; // 从注册中取得指定的 BeanDefinition 实例 BeanDefinition getBeanDefinition(String beanName) throws NoSuchBeanDefinitionException; // 判断 BeanDefinition 实例是否在注册表中(是否注册) boolean containsBeanDefinition(String beanName); // 取得注册表中所有 BeanDefinition 实例的 beanName(标识) String[] getBeanDefinitionNames(); // 返回注册表中 BeanDefinition 实例的数量 int getBeanDefinitionCount(); // beanName(标识)是否被占用 boolean isBeanNameInUse(String beanName);}http://blog.csdn.net/u011179993/article/details/51655057BeanFactoryPostProcessor 当spring初始化好BenaDefinnitionMap之后,提供了一个接口BeanFactoryPostProcessor,允许我们开发者自定义的去修改BeanFactory中的内容,这也是符合“spring”的开闭原则public interface BeanFactoryPostProcessor { /** * 这里提供了修改beanFacotry的机会 */ void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;}http://jinnianshilongnian.iteye.com/blog/2000183PropertySource:属性源,key-value属性对抽象,比如用于配置数据PropertyResolver 属性解析器,用来根据名字解析其值等public interface PropertyResolver { //是否包含某个属性 boolean containsProperty(String key); //获取属性值 如果找不到返回null String getProperty(String key); //获取属性值,如果找不到返回默认值 String getProperty(String key, String defaultValue); //获取指定类型的属性值,找不到返回null <T> T getProperty(String key, Class<T> targetType); //获取指定类型的属性值,找不到返回默认值 <T> T getProperty(String key, Class<T> targetType, T defaultValue); //获取属性值为某个Class类型,找不到返回null,如果类型不兼容将抛出ConversionException <T> Class<T> getPropertyAsClass(String key, Class<T> targetType); //获取属性值,找不到抛出异常IllegalStateException String getRequiredProperty(String key) throws IllegalStateException; //获取指定类型的属性值,找不到抛出异常IllegalStateException <T> T getRequiredProperty(String key, Class<T> targetType) throws IllegalStateException; //替换文本中的占位符(${key})到属性值,找不到不解析 String resolvePlaceholders(String text); //替换文本中的占位符(${key})到属性值,找不到抛出异常IllegalArgumentException String resolveRequiredPlaceholders(String text) throws IllegalArgumentException; } http://blog.csdn.net/u011179993/article/details/51598567BeanDefinition 这个接口描述bean的结构,对应XML中的< bean >或者配置类中的@Bean 它集成了BeanMetadataElement和AttributeAccessorPropertyValues 包含了一个或者多个PropertyValue对象,通常用作特定的一个目的bean的属性更新AttributeAccessor接口定义了最基本的对任意对象的元数据的修改或者获取private void initialize(Object[] sources) {if (sources != null && sources.length > 0) {this.sources.addAll(Arrays.asList(sources));}//判断是否web环境 //javax.servlet.Servlet"和"org.springframework.web.context.ConfigurableWebApplicationContext"类能被加载到代表为web环境this.webEnvironment = deduceWebEnvironment();/**通过Thread.currentThread().getContextClassLoader(); 获取到 类加载器*获取 spring-boot-{v}.jar/META-INF/spring.factories 文件中 org.springframework.context.ApplicationContextInitializer 的值* org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer 配置警告应用程序上下文初始化程序* org.springframework.boot.context.ContextIdApplicationContextInitializer 上下文Id 应用上下文初始化器* org.springframework.boot.context.config.DelegatingApplicationContextInitializer 委托应用程序上下文初始化程序 * org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer 设置端口*并通过各自的构造方法实例化**/setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); /* *获取 spring-boot-{v}.jar/META-INF/spring.factories 文件中 org.springframework.context.ApplicationListener 的值,并实例化 * org.springframework.boot.ClearCachesApplicationListener * org.springframework.boot.builder.ParentContextCloserApplicationListener * org.springframework.boot.context.FileEncodingApplicationListener * org.springframework.boot.context.config.AnsiOutputApplicationListener * org.springframework.boot.context.config.ConfigFileApplicationListener * org.springframework.boot.context.config.DelegatingApplicationListener * org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener * org.springframework.boot.logging.ClasspathLoggingApplicationListener * org.springframework.boot.logging.LoggingApplicationListener *setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));/**获取main方法所在的类*StackTraceElement[] stackTrace = new RuntimeException().getStackTrace(); 获取 虚拟机栈中 栈桢数组*/this.mainApplicationClass = deduceMainApplicationClass();}public ConfigurableApplicationContext run(String... args) {//计时器StopWatch stopWatch = new StopWatch();//开始计时stopWatch.start();ConfigurableApplicationContext context = null;FailureAnalyzers analyzers = null;//用来设置java.awt.headless 属性是true 还是false,是J2SE的一种模式用于在缺少显示屏、键盘 //或者鼠标时的系统配置configureHeadlessProperty();/**获得运行侦听器 获取 spring-boot-{v}.jar/META-INF/spring.factories 文件中 org.springframework.boot.SpringApplicationRunListener 的值* org.springframework.boot.context.event.EventPublishingRunListener 事件发布运行侦听器*在EventPublishingRunListener实例化时将 ApplicationListener的所有实现类添加 到SimpleApplicationEventMulticaster 事件中*/SpringApplicationRunListeners listeners = getRunListeners(args);/**启动SpringApplicationRunListeners侦听器*启动EventPublishingRunListener侦听器*org.springframework.boot.context.config.ConfigFileApplicationListener onApplicationEvent没有做任何事*org.springframework.boot.logging.LoggingApplicationListeneronApplicationEvent加载 LoggingSystem对象*org.springframework.boot.context.config.DelegatingApplicationListener onApplicationEvent没有做任何事*org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener onApplicationEvent没有做任何事*调用以上监听器的onApplicationEvent 方法 */listeners.starting();try {//设置应用参数ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);//加载配置ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments); //打印Banner 默认 SpringBootBanner.BANNERBanner printedBanner = printBanner(environment);//获取 上下文ApplicationContextcontext = createApplicationContext();//错误处理analyzers = new FailureAnalyzers(context);//准备上下文prepareContext(context, environment, listeners, applicationArguments,printedBanner);//刷新上下文refreshContext(context);//完成加载afterRefresh(context, applicationArguments);//完成侦听器listeners.finished(context, null);//停止记时stopWatch.stop();//记录启动信息if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}return context;}catch (Throwable ex) {handleRunFailure(context, listeners, analyzers, ex);throw new IllegalStateException(ex);}}private ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments) {// 创建和配置环境 StandardServletEnvironment.customizePropertySources获取配置加载顺序ConfigurableEnvironment environment = getOrCreateEnvironment();//获取启动配置configureEnvironment(environment, applicationArguments.getSourceArgs());/***通过 EventPublishingRunListener监听 发送ApplicationEnvironmentPreparedEvent 事件到下面监听器*加载配置以下配置的值并加载配置,并调用以下监听的 onApplicationEvent 方法*org.springframework.boot.context.config.ConfigFileApplicationListener 加载配置 * 获取org.springframework.boot.env.EnvironmentPostProcessor配置的值 * org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor* 获取 spring cloud config VCAP_APPLICATION 和 VCAP_SERVICES 的配置 * * org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor * 获取${spring.application.json:${SPRING_APPLICATION_JSON:}} 的配置 ** org.springframework.boot.context.config.ConfigFileApplicationListener* 添加属性源 [servletConfigInitParams,servletContextInitParams,systemProperties,systemEnvironment,random]* 获取 org.springframework.boot.env.PropertySourceLoader的值* org.springframework.boot.env.PropertiesPropertySourceLoader* org.springframework.boot.env.YamlPropertySourceLoader* 配置文件路径加载顺序 1.获取用户自定义路径地址(spring.config.location的值) 2.[file:./config/, file:./, classpath:/config/, classpath:/]* 文件加载顺序 1.获取用户自定义文件名(spring.config.name的值) 2.默认文件名(application)* 文件后缀加载顺序: [properties, xml, yml, yaml]* 1.file:./config/application.properties* 2.file:./config/application.xml* 3.file:./config/application.yml* 4.file:./config/application.yaml* file:./application.properties* file:./application.xml* file:./application.yml* file:./application.yaml* file:./application.yaml* classpath:/config/application.properties* classpath:/config/application.xml* classpath:/config/application.yml* classpath:/config/application.yaml* //我配置的是放在 classpath下的* classpath:/application.properties* classpath:/application-dev.properties * 读取完配置,过滤spring bean* 将配置绑定到 SpringApplication *org.springframework.boot.context.config.AnsiOutputApplicationListener *org.springframework.boot.logging.LoggingApplicationListener *org.springframework.boot.logging.ClasspathLoggingApplicationListener *org.springframework.boot.autoconfigure.BackgroundPreinitializer *org.springframework.boot.context.config.DelegatingApplicationListener *org.springframework.boot.context.FileEncodingApplicationListener * * **/listeners.environmentPrepared(environment);if (!this.webEnvironment) {environment = new EnvironmentConverter(getClassLoader()).convertToStandardEnvironmentIfNecessary(environment);}return environment;}/*** 配置优先级* StandardServletEnvironment.customizePropertySources* SERVLET_CONFIG_PROPERTY_SOURCE_NAME > SERVLET_CONTEXT_PROPERTY_SOURCE_NAME > JNDI_PROPERTY_SOURCE_NAME > 系统属性 > 环境变量* servlet配置属性源名称 > servlet上下文属性源名称 > jndi属性源名称 > 系统属性 > 环境变量**/@Overrideprotected void customizePropertySources(MutablePropertySources propertySources) {propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));}//获取系统属性、环境变量super.customizePropertySources(propertySources);}protected void configureEnvironment(ConfigurableEnvironment environment,String[] args) {//加载命令行属性configurePropertySources(environment, args);//获取 spring.profiles.active 的配置configureProfiles(environment, args);}@Overridepublic void postProcessEnvironment(ConfigurableEnvironment environment,SpringApplication application) {addPropertySources(environment, application.getResourceLoader());//加载配置configureIgnoreBeanInfo(environment);绑定资源bindToSpringApplication(environment, application);}protected ConfigurableApplicationContext createApplicationContext() {Class<?> contextClass = this.applicationContextClass;if (contextClass == null) {try { /** * web项目 初始化 org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext * java项目 初始化 org.springframework.context.annotation.AnnotationConfigApplicationContext **/contextClass = Class.forName(this.webEnvironment? DEFAULT_WEB_CONTEXT_CLASS : DEFAULT_CONTEXT_CLASS);}catch (ClassNotFoundException ex) {throw new IllegalStateException("Unable create a default ApplicationContext, "+ "please specify an ApplicationContextClass",ex);}}//初始化AnnotationConfigEmbeddedWebApplicationContext 注释Bean定义阅读器 类路径Bean定义扫描器return (ConfigurableApplicationContext) BeanUtils.instantiate(contextClass);}private void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {/*** 注释Bean定义阅读器* 类路径Bean定义扫描器 **/context.setEnvironment(environment);//上下文后处理postProcessApplicationContext(context);//初始化上下文applyInitializers(context);//上下文准备完成listeners.contextPrepared(context);if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}//添加特殊的beancontext.getBeanFactory().registerSingleton("springApplicationArguments",applicationArguments);if (printedBanner != null) {context.getBeanFactory().registerSingleton("springBootBanner", printedBanner);}// Load the sourcesSet<Object> sources = getSources();Assert.notEmpty(sources, "Sources must not be empty");//将bean加载到应用程序上下文中。load(context, sources.toArray(new Object[sources.size()]));//将context添加到监听中listeners.contextLoaded(context);}@Overridepublic void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {//准备刷新上下文prepareRefresh();//告诉子类刷新内部bean工厂ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// 准备在这个上下文中使用的bean工厂prepareBeanFactory(beanFactory);try {// 允许在上下文子类中对bean工厂进行后处理。postProcessBeanFactory(beanFactory);// 在上下文中调用在Bean中注册的工厂处理器invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();}}}protected void prepareRefresh() {this.startupDate = System.currentTimeMillis();this.closed.set(false);this.active.set(true);if (logger.isInfoEnabled()) {logger.info("Refreshing " + this);}// 在上下文环境中初始化任何占位符属性源initPropertySources();// 验证所有标记为必需的属性是可解析的getEnvironment().validateRequiredProperties();this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();}
阅读全文
0 0
- Spring Boot 源码分析
- spring boot 源码
- Spring Boot自动配置源码
- Spring-boot中ApplicationRunner源码
- spring boot banner 源码解析
- Spring boot源码分析-ConfigurationProperties
- [Spring Boot] 1. Spring Boot启动过程源码分析
- spring boot 源码分析(一) 案例
- 【Spring Boot】SpringBoot-自动配置源码解析
- spring boot 源码 ApplicationContext 上下文继承图
- spring boot -- 导入源码到eclipse
- Spring Boot启动过程源码分析
- Spring boot源码分析-环境搭建
- Spring boot源码分析-BeanDefinitionLoader(7)
- Spring boot源码分析-starter(10)
- Spring boot源码分析-Conditional(12)
- spring boot prometheus client 源码分析
- Spring-boot 集成 kakfa 源码分析
- SQL SERVER 获取数据库内存大小
- Minimum ASCII Delete Sum for Two Strings问题及解法
- Ubuntu Android/Sdk/build-tools/23.0.3/aapt": error=2, 没有那个文件或目录
- SQL Server 配置管理器无法打开
- 归并排序
- spring boot 源码
- JQ实现弹幕
- repo使用手册
- Word2013中如何合并多个文档将多篇内容放进一篇文档里
- TASKCTL中不使用代理,通过ssh免密连接执行远程脚本配置(SSH插件扩展)
- Fragment请求数据—+二维码
- 渲染管线-顶点变换
- C#通过app.manifest使程序以管理员身份运行
- Effective C++ 12. Copy all parts of an object