diff --git "a/springboot-source-code-analysis/(11)351円200円232円350円277円207円Java351円205円215円347円275円256円Bean347円232円204円345円207円240円347円247円215円346円226円271円345円274円217円.md" "b/springboot-source-code-analysis/(11)351円200円232円350円277円207円Java351円205円215円347円275円256円Bean347円232円204円345円207円240円347円247円215円346円226円271円345円274円217円.md" index e69de29..98ea91c 100644 --- "a/springboot-source-code-analysis/(11)351円200円232円350円277円207円Java351円205円215円347円275円256円Bean347円232円204円345円207円240円347円247円215円346円226円271円345円274円217円.md" +++ "b/springboot-source-code-analysis/(11)351円200円232円350円277円207円Java351円205円215円347円275円256円Bean347円232円204円345円207円240円347円247円215円346円226円271円345円274円217円.md" @@ -0,0 +1,98 @@ +### 通过Java配置Bean的几种方式 + +#### 1.通过@Configuration注解注入Bean的方式 + +```java +@Configuration +public class MyBeanConfiguration { + + /** + * 通过 @Configuration注解 注入一个Bean + */ + @Bean("dog") + public Animal getDog() { + return new Dog(); + } + +} +``` + + + +#### 2.通过实现FactoryBean接口的方式注入Bean + +```java +@Component +public class MyFactoryBean implements FactoryBean { + + /** + * 返回要注入的类 + */ + @Override + public Animal getObject() throws Exception { + return new Cat(); + } + + /** + * 获取要注入类的类型 + */ + @Override + public Class getObjectType() { + return Animal.class; + } + + @Override + public boolean isSingleton() { + return FactoryBean.super.isSingleton(); + } + +} +``` + + + +#### 3.通过实现BeanDefinitionRegistryPostProcessor接口的方式注入Bean + +```java +@Component +public class MyBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor { + + /** + * 通过BeanDefinitionRegistryPostProcessor + */ + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); + rootBeanDefinition.setBeanClass(Monkey.class); + beanDefinitionRegistry.registerBeanDefinition("monkey", rootBeanDefinition); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { + + } +} +``` + + + +#### 4.通过实现ImportBeanDefinitionRegistrar接口的方式注入Bean + +```java +public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { + + /** + * 通过ImportBeanDefinitionRegistrar注入Bean + */ + @Override + public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); + rootBeanDefinition.setBeanClass(Bird.class); + registry.registerBeanDefinition("bird", rootBeanDefinition); + } +} + +``` + +> 使用时:用 @Import(MyImportBeanDefinitionRegistrar.class) 进行注入 + diff --git "a/springboot-source-code-analysis/(12)346円241円206円346円236円266円Refresh346円226円271円346円263円225円350円247円243円346円236円220円344円270円200円.md" "b/springboot-source-code-analysis/(12)346円241円206円346円236円266円Refresh346円226円271円346円263円225円350円247円243円346円236円220円344円270円200円.md" new file mode 100644 index 0000000..d1c35e0 --- /dev/null +++ "b/springboot-source-code-analysis/(12)346円241円206円346円236円266円Refresh346円226円271円346円263円225円350円247円243円346円236円220円344円270円200円.md" @@ -0,0 +1,276 @@ + + +### 框架Refresh方法解析一 + + + +#### 1.Refresh方法简介 + +- Bean配置读取加载入口 +- Spring框架的启动流程 + + + +#### 2.Refresh方法的执行步骤 + +image-20211017144834689 + +```java + @Override + public void refresh() throws BeansException, IllegalStateException { + synchronized (this.startupShutdownMonitor) { + // Prepare this context for refreshing. + // 准备此上下文 + prepareRefresh(); + + // Tell the subclass to refresh the internal bean factory. + // 获取BeanFacotry + ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); + + // Prepare the bean factory for use in this context. + // 准备此类上下文中使用的Bean工厂 + prepareBeanFactory(beanFactory); + + try { + // Allows post-processing of the bean factory in context subclasses. + // 允许在上下文子类中对Bean工厂进行后处理 + postProcessBeanFactory(beanFactory); + + // Invoke factory processors registered as beans in the context. + // 调用在上下文中注册为Bean的工厂处理器 + invokeBeanFactoryPostProcessors(beanFactory); + + // Register bean processors that intercept bean creation. + // 注册拦截Bean创建的Bean处理器 + registerBeanPostProcessors(beanFactory); + + // Initialize message source for this context. + // 为此上下文初始化消息源 + initMessageSource(); + + // Initialize event multicaster for this context. + // 为此上下文初始化事件广播器 + initApplicationEventMulticaster(); + + // Initialize other special beans in specific context subclasses. + // 初始化特定上下文子类中的其他特殊Bean + 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. + // 重置active标志 + 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... + // 重置 Spring 核心中的常见内省缓存,因为我们可能不再需要单例 bean 的元数据... + resetCommonCaches(); + } + } + } +``` + + + +#### 3.准备上下文:prepareRefersh#方法 + +- prepareRefersh#方法简介 + - 清除本地元数据缓存 + - 准备框架上下文 + - 设置框架启动时间 + - 设置框架 active 启动状态为true + - 如果是Debug模式打印Debug日志 + - 初始化环境配置 + - 获取当前环境配置 + - 如果是Web环境,配置ServletContext 和 ServletConfig + - 检查环境配置中的必备属性是否存在 + - 如果没有早期的事件监听器,就注册应用监听器:applicationListeners + +- prepareRefresh#方法 + +```java + @Override + protected void prepareRefresh() { + // 清除元数据缓存 + this.scanner.clearCache(); + // 准备上下文 + super.prepareRefresh(); + } +``` + +- clearCache#方法 + +```java + /** + * Clear the local metadata cache, if any, removing all cached class metadata. + * 清除本地元数据缓存(如果有),删除所有缓存的类元数据。 + */ + public void clearCache() { + if (this.metadataReaderFactory instanceof CachingMetadataReaderFactory) { + // Clear cache in externally provided MetadataReaderFactory; this is a no-op + // for a shared cache since it'll be cleared by the ApplicationContext. + // 清除外部提供的 MetadataReaderFactory 中的缓存;这是一个无操作用于共享缓存,因为它将被 ApplicationContext 清除。 + ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache(); + } + } +``` + +- super.prepareRefresh方法 + +```java + /** + * Prepare this context for refreshing, setting its startup date and + * active flag as well as performing any initialization of property sources. + * 准备此上下文以进行刷新、设置其启动日期和* active 标志以及执行属性源的任何初始化 + */ + protected void prepareRefresh() { + // Switch to active. + // 设置启动时间 + this.startupDate = System.currentTimeMillis(); + this.closed.set(false); + // 设置 active 标志状态为 true + this.active.set(true); + + // 如果当前日志状态是Debug模式的话,会打印一段话 + if (logger.isDebugEnabled()) { + if (logger.isTraceEnabled()) { + logger.trace("Refreshing " + this); + } + else { + logger.debug("Refreshing " + getDisplayName()); + } + } + + // Initialize any placeholder property sources in the context environment. + // 初始化环境配置 + initPropertySources(); + + // Validate that all properties marked as required are resolvable: + // see ConfigurablePropertyResolver#setRequiredProperties + // 检查环境属性中必备的环境数据,如果没有就 throw MissingRequiredPropertiesException 异常 + getEnvironment().validateRequiredProperties(); + + // Store pre-refresh ApplicationListeners... + // 将系统的事件监听器进行注册 + if (this.earlyApplicationListeners == null) { + this.earlyApplicationListeners = new LinkedHashSet(this.applicationListeners); + } + else { + // Reset local application listeners to pre-refresh state. + this.applicationListeners.clear(); + this.applicationListeners.addAll(this.earlyApplicationListeners); + } + + // Allow for the collection of early ApplicationEvents, + // to be published once the multicaster is available... + this.earlyApplicationEvents = new LinkedHashSet(); + } + +``` + +- initPropertySources#方法 + +```java + protected void initPropertySources() { + // 获取环境配置上下文 + ConfigurableEnvironment env = this.getEnvironment(); + // 如果当前环境是Web环境,将servletContext 和 ServletConfig 加载到环境配置上下文中 + if (env instanceof ConfigurableWebEnvironment) { + ((ConfigurableWebEnvironment)env).initPropertySources(this.servletContext, (ServletConfig)null); + } + } +``` + + + + + +#### 获取新的Bean工厂:obtainFreshBeanFacotry#方法 + +- obtainFreshBeanFacotry#方法简介 + - 设置当前上下文刷新状态为true + - 这是BeanFactory序列化ID(默认是application) + - 返回BeanFacotry + +- obtainFreshBeanFactory#方法 + +```java + /** + * Tell the subclass to refresh the internal bean factory. + * 告诉子类刷新内部 bean 工厂 + * @return the fresh BeanFactory instance + * @see #refreshBeanFactory() + * @see #getBeanFactory() + */ + protected ConfigurableListableBeanFactory obtainFreshBeanFactory() { + // 设置上下文刷新状态和Beanfacotory的序列化ID + refreshBeanFactory(); + // 获取BeanFactory(默认是DefaultListableBeanFacotry) + return getBeanFactory(); + } + +``` + +- refreshBeanFacoty#方法 + +```java + /** + * Do nothing: We hold a single internal BeanFactory and rely on callers + * to register beans through our public methods (or the BeanFactory's). + * @see #registerBeanDefinition + */ + @Override + protected final void refreshBeanFactory() throws IllegalStateException { + // 设置当前上下文刷新状态:true + if (!this.refreshed.compareAndSet(false, true)) { + throw new IllegalStateException( + "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once"); + } + // 设置BeanFacotry序列化ID:默认是application + this.beanFactory.setSerializationId(getId()); + } +``` + +- getBeanFacotory#方法 + +```java +/** + * Return the single internal BeanFactory held by this context + * (as ConfigurableListableBeanFactory). + */ + @Override + public final ConfigurableListableBeanFactory getBeanFactory() { + // 返回默认的 DefaultListableBeanFacotry + return this.beanFactory; + } +``` + + + diff --git "a/springboot-source-code-analysis/(13)346円241円206円346円236円266円Refresh346円226円271円346円263円225円350円247円243円346円236円220円344円272円214円.md" "b/springboot-source-code-analysis/(13)346円241円206円346円236円266円Refresh346円226円271円346円263円225円350円247円243円346円236円220円344円272円214円.md" new file mode 100644 index 0000000..c3b2180 --- /dev/null +++ "b/springboot-source-code-analysis/(13)346円241円206円346円236円266円Refresh346円226円271円346円263円225円350円247円243円346円236円220円344円272円214円.md" @@ -0,0 +1,390 @@ +### 框架Refresh方法解析二 + + + +#### 1.配置工厂标准上下文特征:prepareBeanFacotry() + +- 作用 + - 设置beanFacotry一些属性 + - 添加后置处理器 + - 设置忽略的自动装配接口 + - 注册一些组件 + +```java + /** + * Configure the factory's standard context characteristics, + * such as the context's ClassLoader and post-processors. + * @param beanFactory the BeanFactory to configure + * 配置工厂的标准上下文特征,比如上下文的ClassLoader和post-processors + */ + protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) { + // Tell the internal bean factory to use the context's class loader etc. + // 告知内部的Bean工厂,使用上下文的类加载器 + beanFactory.setBeanClassLoader(getClassLoader()); + + // 设置Bean表达式解析器 + // 默认是spring el 表达式 + beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader())); + + // 注册上下文enviroment配置的引用 + // 用于做属性转换 + beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment())); + + // Configure the bean factory with context callbacks. + // 使用上下文回调配置 Bean 工厂 + // 在工厂的 beanPostProcessor 属性中添加Bean的后置处理器,beanPostProcessor是一个ArrayList + beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this)); + // 在工厂的忽略依赖接口ignoreDependencyInterface列表中添加Aware系列的接口 + // 以下Aware接口由 ApplicationContextAwareProcessor 后置处理器处理 + beanFactory.ignoreDependencyInterface(EnvironmentAware.class); + beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class); + beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class); + beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class); + beanFactory.ignoreDependencyInterface(MessageSourceAware.class); + beanFactory.ignoreDependencyInterface(ApplicationContextAware.class); + + // BeanFactory interface not registered as resolvable type in a plain factory. + // MessageSource registered (and found for autowiring) as a bean. + // 在普通的工厂中,BeanFactory接口并没有按照resolvable类型进行注册 + // MessageSource被注册成一个Bean(并被自动注入) + + //BeanFactory.class为key,beanFactory为value放入到了beanFactory的resolvableDependencies属性中 + //resolvableDependencies是一个ConcurrentHashMap,映射依赖类型和对应的被注入的value + //这样的话BeanFactory/ApplicationContext虽然没有以bean的方式被定义在工厂中, + //但是也能够支持自动注入,因为他处于resolvableDependencies属性中 + + // 向BeanFacotry添加一些依赖,需要解析依赖的时候指向自身 + beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory); + // 再将上下文的一些接口与上下文本身做映射,一一放入到resolvableDependencies中 + beanFactory.registerResolvableDependency(ResourceLoader.class, this); + beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this); + beanFactory.registerResolvableDependency(ApplicationContext.class, this); + + // Register early post-processor for detecting inner beans as ApplicationListeners. + // 将用于检测内部 bean 的早期后处理器注册为 ApplicationListeners + beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this)); + + // Detect a LoadTimeWeaver and prepare for weaving, if found. + // 检测LoadTimeWeaver,如果有就准备织入 + if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) { + // 如果有LoadTimeWeaver,加入bean后处理器 + beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory)); + // Set a temporary ClassLoader for type matching. + // 为匹配类型设置一个临时的ClassLoader + beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader())); + } + + // Register default environment beans. + // 注册默认的environment beans + if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) { + //虽然XmlWebApplicationContext中持有默认实现的StandardServletEnvironment + //但是没有注册到beanFactory中,通过getEnvironment方法拿到持有的引用 + //2.注册environment单例 + beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment()); + } + if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) { + //注册systemProperties单例 + beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties()); + } + if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) { + ///注册systemEnvironment单例 + beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment()); + } + } +``` + + + +#### 2.重写BeanFactory,在BeanFactory创建后进一步设置:postProcessBeanFactory() + +- 作用是 + - 留给开发者的扩展点,通过子类重写,在BeanFactory完成创建后做进一步设置 + - 如添加WebApplicationContextServletContextAwareProcessor后置处理器,给Web环境下的Servlet作用域进行设置:Request、Session + +- postProcessBeanFacotory()方法 + +```java + protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { + // 调用父类的GenericWebApplicationContext#postProcessBeanFacotory方法 + super.postProcessBeanFactory(beanFactory); + if (!ObjectUtils.isEmpty(this.basePackages)) { + this.scanner.scan(this.basePackages); + } + + if (!this.annotatedClasses.isEmpty()) { + this.reader.register(ClassUtils.toClassArray(this.annotatedClasses)); + } + + } +``` + +- 在Web环境下注册WebApplicationContextServletContextAwareProcessor后置处理器 + +```java + /** + * Register ServletContextAwareProcessor. + * @see ServletContextAwareProcessor + */ + @Override + protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { + // 添加WebApplicationContextServletContextAwareProcessor后置处理器 + beanFactory.addBeanPostProcessor(new WebApplicationContextServletContextAwareProcessor(this)); + // 忽略ServletContextAware + beanFactory.ignoreDependencyInterface(ServletContextAware.class); + // 定义Web环境下的Servlet作用域,比如:Request、Session + registerWebApplicationScopes(); + } + +``` + + + + + +#### 3.调用所有注册的BeanFactoryPostProcessor的Bean + +- 作用 + + - 框架自身的BeanFactoryPostProcessor或BeanDefinitionRegistoryPostProcessor初始化Bean的定义或属性 + + - 调用BeanDefinitionRegistryPostProcessor实现向容器内添加Bean的定义 + + - ```java + // 调用时机:在BeanFactory标准初始化之后调用,这时所有的Bean定义已经保存加载到BeanFactory,但是Bean的实例还未创建 + // 作用:来定制和修改BeanFactory内容,如添加一个Bean + @Component + public class MyBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor { + + /** + * 通过BeanDefinitionRegistryPostProcessor + */ + @Override + public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { + RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); + rootBeanDefinition.setBeanClass(Monkey.class); + beanDefinitionRegistry.registerBeanDefinition("monkey", rootBeanDefinition); + } + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { + + } + } + ``` + + - 调用BeanFacotryPostProcessor实现容器内Bean的定义添加属性 + + - ```java + // 调用时机:在BeanFactory标准初始化之后调用,这时所有的Bean定义已经保存加载到BeanFactory,但是Bean的实例还未创建 + // 作用:来定制和修改BeanFactory内容,如覆盖或添加属性 + @Component + public class MyBeanFacotoryPostProcessor implements BeanFactoryPostProcessor { + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { + // 给DemoBean添加属性 + BeanDefinition beanDemo = configurableListableBeanFactory.getBeanDefinition("demoBean"); + MutablePropertyValues propertyValues = beanDemo.getPropertyValues(); + propertyValues.addPropertyValue("name", "ipman"); + } + } + ``` + +- 步骤 + + - 步骤一 + + image-20211017195022460 + + + + - 步骤二 + + image-20211017195333372 + + + + - 步骤三 + + image-20211017195520176 + + + + - 步骤四 + + [画像:image-20211017195711612] + +- invokeBeanFacotoryPostProcessors()方法 + +```java +public static void invokeBeanFactoryPostProcessors( + ConfigurableListableBeanFactory beanFactory, List beanFactoryPostProcessors) { + + // 保存所有调用过的PostProcessor的beanName + Set processedBeans = new HashSet(); + + if (beanFactory instanceof BeanDefinitionRegistry) { + BeanDefinitionRegistry registry = (BeanDefinitionRegistry) beanFactory; + // 这两个list主要用来分别收集BeanFactoryPostProcessor和BeanDefinitionRegistryPostProcessor + List regularPostProcessors = new ArrayList(); + List registryProcessors = new ArrayList(); + + for (BeanFactoryPostProcessor postProcessor : beanFactoryPostProcessors) { + // 对已注册在DefaultListBeanFactory的BeanFactoryPostProcessor进行分类 + if (postProcessor instanceof BeanDefinitionRegistryPostProcessor) { + BeanDefinitionRegistryPostProcessor registryProcessor = + (BeanDefinitionRegistryPostProcessor) postProcessor; + // 已注册在DefaultListBeanFactory的BeanDefinitionRegistryPostProcessor优先级最高 + // 如果postProcessor是BeanDefinitionRegistryPostProcessor的实例 + // 执行postProcessor的postProcessBeanDefinitionRegistry + // 为什么执行完之后还要保存到List中呢? + // 因为这里只是执行完了BeanDefinitionRegistryPostProcessor的回调 + // 父类BeanFactoryPostProcessor的方法还没有进行回调 + registryProcessor.postProcessBeanDefinitionRegistry(registry); + registryProcessors.add(registryProcessor); + } + else { + // 如果不是BeanDefinitionRegistryPostProcessor的实例 + // 则是BeanFactoryPostProcessor的实例,存放在List中,后面会进行回调 + regularPostProcessors.add(postProcessor); + } + } + + // 定义了一个集合来存放当前需要执行的BeanDefinitionRegistryPostProcessor + List currentRegistryProcessors = new ArrayList(); + + // 首先执行实现了PriorityOrdered的BeanDefinitionRegistryPostProcessor + // 这里只能获取到Spring内部注册的BeanDefinitionRegistryPostProcessor,因为到这里spring还没有去扫描Bean,获取不到我们 // 通过@Component标志的自定义的BeanDefinitionRegistryPostProcessor + // 一般默认情况下,这里只有一个beanName, + // org.springframework.context.annotation.internalConfigurationAnnotationProcessor + // 对应的BeanClass:ConfigurationClassPostProcessor + String[] postProcessorNames = + beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); + for (String ppName : postProcessorNames) { + if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { + currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); + // 保存调用过的beanName + processedBeans.add(ppName); + } + } + // 排序 + sortPostProcessors(currentRegistryProcessors, beanFactory); + // registryProcessors存放的是BeanDefinitionRegistryPostProcessor + registryProcessors.addAll(currentRegistryProcessors); + // 执行BeanDefinitionRegistryPostProcessor,一般默认情况下,只有ConfigurationClassPostProcessor + // ConfigurationClassPostProcessor的具体作用后面再讲,这里先认为它执行完扫描,并且注册BeanDefinition + invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); + // 清空临时变量,后面再使用 + currentRegistryProcessors.clear(); + + // 第二步执行实现了Ordered的BeanDefinitionRegistryPostProcessor + // 这里为什么要再一次从beanFactory中获取所有的BeanDefinitionRegistryPostProcessor,是因为上面的操作有可能注册了 + // 新的BeanDefinitionRegistryPostProcessor,所以再获取一次 + postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); + for (String ppName : postProcessorNames) { + if (!processedBeans.contains(ppName) && beanFactory.isTypeMatch(ppName, Ordered.class)) { + currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); + // 保存调用过的beanName + processedBeans.add(ppName); + } + } + sortPostProcessors(currentRegistryProcessors, beanFactory); + registryProcessors.addAll(currentRegistryProcessors); + invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); + currentRegistryProcessors.clear(); + + + // 上面两步的套路是一模一样的,唯一不一样的地方是第一步执行的是实现了PriorityOrdered的 + // BeanDefinitionRegistryPostProcessor,第二步是执行的是实现了Ordered的 + // BeanDefinitionRegistryPostProcessor + + + // 最后一步,执行没有实现PriorityOrdered或者Ordered的BeanDefinitionRegistryPostProcessor + // 比较不一样的是,这里有个while循环,是因为在实现BeanDefinitionRegistryPostProcessor的方法的过程中有可能会注册新的 + // BeanDefinitionRegistryPostProcessor,所以需要处理,直到不会出现新的BeanDefinitionRegistryPostProcessor为止 + boolean reiterate = true; + while (reiterate) { + reiterate = false; + postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); + for (String ppName : postProcessorNames) { + if (!processedBeans.contains(ppName)) { + // 发现还有未处理过的BeanDefinitionRegistryPostProcessor,按照套路放进list中 + // reiterate标记为true,后面还要再执行一次这个循环,因为执行新的BeanDefinitionRegistryPostProcessor有可能会 + // 注册新的BeanDefinitionRegistryPostProcessor + currentRegistryProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class)); + processedBeans.add(ppName); + reiterate = true; + } + } + sortPostProcessors(currentRegistryProcessors, beanFactory); + registryProcessors.addAll(currentRegistryProcessors); + invokeBeanDefinitionRegistryPostProcessors(currentRegistryProcessors, registry); + currentRegistryProcessors.clear(); + } + // 方法开头前几行分类的两个list就是在这里调用 + // BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor + // 刚刚执行了BeanDefinitionRegistryPostProcessor的方法 + // 现在要执行父类BeanFactoryPostProcessor的方法 + invokeBeanFactoryPostProcessors(registryProcessors, beanFactory); + invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); + } + + else { + // Invoke factory processors registered with the context instance. + invokeBeanFactoryPostProcessors(beanFactoryPostProcessors, beanFactory); + } + + + // 上面BeanFactoryPostProcessor的回调可能又注册了一些类,下面需要再走一遍之前的逻辑 + String[] postProcessorNames = + beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false); + + // 根据不同的优先级,分成三类 + List priorityOrderedPostProcessors = new ArrayList(); + List orderedPostProcessorNames = new ArrayList(); + List nonOrderedPostProcessorNames = new ArrayList(); + for (String ppName : postProcessorNames) { + // 上面处理BeanDefinitionRegistryPostProcessor的时候已经处理过,这里不再重复处理 + // 因为BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor + if (processedBeans.contains(ppName)) { + // skip - already processed in first phase above + } + else if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { + priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanFactoryPostProcessor.class)); + } + else if (beanFactory.isTypeMatch(ppName, Ordered.class)) { + orderedPostProcessorNames.add(ppName); + } + else { + nonOrderedPostProcessorNames.add(ppName); + } + } + + // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered. + // 下面的逻辑跟上面是一致的,先处理实现了PriorityOrdered接口的 + // 再处理实现了Ordered接口的 + // 最后处理普通的BeanFactoryPostProcessor + sortPostProcessors(priorityOrderedPostProcessors, beanFactory); + invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); + + // Next, invoke the BeanFactoryPostProcessors that implement Ordered. + List orderedPostProcessors = new ArrayList(); + for (String postProcessorName : orderedPostProcessorNames) { + orderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); + } + sortPostProcessors(orderedPostProcessors, beanFactory); + invokeBeanFactoryPostProcessors(orderedPostProcessors, beanFactory); + + // Finally, invoke all other BeanFactoryPostProcessors. + List nonOrderedPostProcessors = new ArrayList(); + for (String postProcessorName : nonOrderedPostProcessorNames) { + nonOrderedPostProcessors.add(beanFactory.getBean(postProcessorName, BeanFactoryPostProcessor.class)); + } + invokeBeanFactoryPostProcessors(nonOrderedPostProcessors, beanFactory); + + // 因为各种BeanFactoryPostProcessor可能修改了BeanDefinition + // 所以这里需要清除缓存,需要的时候再通过merge的方式获取 + beanFactory.clearMetadataCache(); +} +``` + diff --git "a/springboot-source-code-analysis/(3)345円267円245円345円216円202円345円212円240円350円275円275円346円234円272円345円210円266円350円247円243円346円236円220円.md" "b/springboot-source-code-analysis/(3)345円267円245円345円216円202円345円212円240円350円275円275円346円234円272円345円210円266円350円247円243円346円236円220円.md" index cd2d8b8..9dc5a54 100644 --- "a/springboot-source-code-analysis/(3)345円267円245円345円216円202円345円212円240円350円275円275円346円234円272円345円210円266円350円247円243円346円236円220円.md" +++ "b/springboot-source-code-analysis/(3)345円267円245円345円216円202円345円212円240円350円275円275円346円234円272円345円210円266円350円247円243円346円236円220円.md" @@ -69,7 +69,7 @@ public final class SpringFactoriesLoader { ClassLoader classLoader = getClassLoader(); // 通过这个SpringFactoriesLoader#loadFactoryNames方法获取Spring中所有系统初始化器实现的全路径名 Set names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader)); - // 通过createSpringFactoriesInstances#()创建它们的实例 + // #()创建它们的实例 List instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); // 通过注解@Order进行排序 AnnotationAwareOrderComparator.sort(instances); diff --git a/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/initializer/FirstInitializer.java b/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/initializer/FirstInitializer.java index 6cc9d1d..38edbf3 100644 --- a/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/initializer/FirstInitializer.java +++ b/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/initializer/FirstInitializer.java @@ -30,6 +30,9 @@ public void initialize(ConfigurableApplicationContext configurableApplicationCon ConfigurableEnvironment environment = configurableApplicationContext.getEnvironment(); + // 设置必填属性 + environment.setRequiredProperties("app.enviroment"); + // 设置自定义属性 Map attributeMap = new HashMap(); attributeMap.put("firstKey", "firstValue"); diff --git a/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/ann/MyBeanDefinitionRegistry.java b/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/ann/MyBeanDefinitionRegistry.java index aa51f86..ab84f26 100644 --- a/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/ann/MyBeanDefinitionRegistry.java +++ b/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/ann/MyBeanDefinitionRegistry.java @@ -7,6 +7,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; /** * Created by ipipman on 2021年10月16日. diff --git a/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/ann/MyBeanFacotoryPostProcessor.java b/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/ann/MyBeanFacotoryPostProcessor.java new file mode 100644 index 0000000..a08d25e --- /dev/null +++ b/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/ann/MyBeanFacotoryPostProcessor.java @@ -0,0 +1,32 @@ +package com.example.springboot.source.code.analysis.ioc.ann; + +import org.springframework.beans.BeansException; +import org.springframework.beans.MutablePropertyValues; +import org.springframework.beans.factory.config.BeanDefinition; +import org.springframework.beans.factory.config.BeanFactoryPostProcessor; +import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; +import org.springframework.beans.factory.support.RootBeanDefinition; +import org.springframework.stereotype.Component; + +/** + * Created by ipipman on 2021年10月17日. + * + * @version V1.0 + * @Package com.example.springboot.source.code.analysis.ioc.ann + * @Description: (用一句话描述该文件做什么) + * @date 2021年10月17日 6:47 下午 + */ + +// 调用时机:在BeanFactory标准初始化之后调用,这时所有的Bean定义已经保存加载到BeanFactory,但是Bean的实例还未创建 +// 作用:来定制和修改BeanFactory内容,如覆盖或添加属性 +@Component +public class MyBeanFacotoryPostProcessor implements BeanFactoryPostProcessor { + + @Override + public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { + // 给DemoBean添加属性 + BeanDefinition beanDemo = configurableListableBeanFactory.getBeanDefinition("demoBean"); + MutablePropertyValues propertyValues = beanDemo.getPropertyValues(); + propertyValues.addPropertyValue("name", "ipman"); + } +} diff --git a/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/pojo/DemoBean.java b/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/pojo/DemoBean.java new file mode 100644 index 0000000..72f65ee --- /dev/null +++ b/springboot-source-code-analysis/src/main/java/com/example/springboot/source/code/analysis/ioc/pojo/DemoBean.java @@ -0,0 +1,27 @@ +package com.example.springboot.source.code.analysis.ioc.pojo; + +import org.springframework.stereotype.Component; + +/** + * Created by ipipman on 2021年10月17日. + * + * @version V1.0 + * @Package com.example.springboot.source.code.analysis.ioc.pojo + * @Description: (用一句话描述该文件做什么) + * @date 2021年10月17日 6:53 下午 + */ +@Component +public class DemoBean { + + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + +} diff --git a/springboot-source-code-analysis/src/main/resources/application.properties b/springboot-source-code-analysis/src/main/resources/application.properties index 82918ee..856742a 100644 --- a/springboot-source-code-analysis/src/main/resources/application.properties +++ b/springboot-source-code-analysis/src/main/resources/application.properties @@ -5,4 +5,8 @@ context.initializer.classes=\ # 通过系统事件监听器,监听事件 context.listener.classes=\ com.example.springboot.source.code.analysis.listener.ThirdListener,\ - com.example.springboot.source.code.analysis.listener.FourthListener \ No newline at end of file + com.example.springboot.source.code.analysis.listener.FourthListener + + +# 通过ConfigurableEnviroment.requiredProperty()方法设置的必填属性 +app.enviroment=ipman \ No newline at end of file diff --git a/springboot-source-code-analysis/src/test/java/com/example/springboot/source/code/analysis/SpringbootSourceCodeAnalysisApplicationTests.java b/springboot-source-code-analysis/src/test/java/com/example/springboot/source/code/analysis/SpringbootSourceCodeAnalysisApplicationTests.java index 56bd22c..b78658e 100644 --- a/springboot-source-code-analysis/src/test/java/com/example/springboot/source/code/analysis/SpringbootSourceCodeAnalysisApplicationTests.java +++ b/springboot-source-code-analysis/src/test/java/com/example/springboot/source/code/analysis/SpringbootSourceCodeAnalysisApplicationTests.java @@ -3,6 +3,7 @@ import com.example.springboot.source.code.analysis.event.RainListener; import com.example.springboot.source.code.analysis.event.WeatherRunListener; import com.example.springboot.source.code.analysis.ioc.ann.MyImportBeanDefinitionRegistrar; +import com.example.springboot.source.code.analysis.ioc.pojo.DemoBean; import com.example.springboot.source.code.analysis.ioc.service.HelloService; import com.example.springboot.source.code.analysis.listener.ApplicationContextContainer; import org.junit.Test; @@ -55,4 +56,13 @@ public void contextLoads() { } + @Autowired + DemoBean demoBean; + + @Test + public void sayDemoBean(){ + System.out.println(demoBean.getName()); + } + + } diff --git "a/springboot-source-code-analysis/351円200円232円350円277円207円Java351円205円215円347円275円256円Bean347円232円204円345円207円240円347円247円215円346円226円271円345円274円217円.md" "b/springboot-source-code-analysis/351円200円232円350円277円207円Java351円205円215円347円275円256円Bean347円232円204円345円207円240円347円247円215円346円226円271円345円274円217円.md" deleted file mode 100644 index 98ea91c..0000000 --- "a/springboot-source-code-analysis/351円200円232円350円277円207円Java351円205円215円347円275円256円Bean347円232円204円345円207円240円347円247円215円346円226円271円345円274円217円.md" +++ /dev/null @@ -1,98 +0,0 @@ -### 通过Java配置Bean的几种方式 - -#### 1.通过@Configuration注解注入Bean的方式 - -```java -@Configuration -public class MyBeanConfiguration { - - /** - * 通过 @Configuration注解 注入一个Bean - */ - @Bean("dog") - public Animal getDog() { - return new Dog(); - } - -} -``` - - - -#### 2.通过实现FactoryBean接口的方式注入Bean - -```java -@Component -public class MyFactoryBean implements FactoryBean { - - /** - * 返回要注入的类 - */ - @Override - public Animal getObject() throws Exception { - return new Cat(); - } - - /** - * 获取要注入类的类型 - */ - @Override - public Class getObjectType() { - return Animal.class; - } - - @Override - public boolean isSingleton() { - return FactoryBean.super.isSingleton(); - } - -} -``` - - - -#### 3.通过实现BeanDefinitionRegistryPostProcessor接口的方式注入Bean - -```java -@Component -public class MyBeanDefinitionRegistry implements BeanDefinitionRegistryPostProcessor { - - /** - * 通过BeanDefinitionRegistryPostProcessor - */ - @Override - public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException { - RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); - rootBeanDefinition.setBeanClass(Monkey.class); - beanDefinitionRegistry.registerBeanDefinition("monkey", rootBeanDefinition); - } - - @Override - public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException { - - } -} -``` - - - -#### 4.通过实现ImportBeanDefinitionRegistrar接口的方式注入Bean - -```java -public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { - - /** - * 通过ImportBeanDefinitionRegistrar注入Bean - */ - @Override - public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { - RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(); - rootBeanDefinition.setBeanClass(Bird.class); - registry.registerBeanDefinition("bird", rootBeanDefinition); - } -} - -``` - -> 使用时:用 @Import(MyImportBeanDefinitionRegistrar.class) 进行注入 -

AltStyle によって変換されたページ (->オリジナル) /