当前位置: 代码迷 >> 综合 >> spring启动流程探索六、refresh()(5)invokeBeanFactoryPostProcessors
  详细解决方案

spring启动流程探索六、refresh()(5)invokeBeanFactoryPostProcessors

热度:89   发布时间:2023-11-26 12:04:39.0

spring探索第六节

  • invokeBeanFactoryPostProcessors

invokeBeanFactoryPostProcessors

这个也是影响spring容器生命周期非常重要的方法,他第一次执行和后面的执行也是后面的执行是不同的。因为他第一次会去调用ConfigurationClassPostProcessor的实现。我们开始上代码把

/*** Prepare the Configuration classes for servicing bean requests at runtime* by replacing them with CGLIB-enhanced subclasses.*/@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    int factoryId = System.identityHashCode(beanFactory);if (this.factoriesPostProcessed.contains(factoryId)) {
    throw new IllegalStateException("postProcessBeanFactory already called on this post-processor against " + beanFactory);}this.factoriesPostProcessed.add(factoryId);if (!this.registriesPostProcessed.contains(factoryId)) {
    // BeanDefinitionRegistryPostProcessor hook apparently not supported...// Simply call processConfigurationClasses lazily at this point then.processConfigBeanDefinitions((BeanDefinitionRegistry) beanFactory);}// 这个是关键enhanceConfigurationClasses(beanFactory);beanFactory.addBeanPostProcessor(new ImportAwareBeanPostProcessor(beanFactory));}
	public void enhanceConfigurationClasses(ConfigurableListableBeanFactory beanFactory) {
    Map<String, AbstractBeanDefinition> configBeanDefs = new LinkedHashMap<>();for (String beanName : beanFactory.getBeanDefinitionNames()) {
    BeanDefinition beanDef = beanFactory.getBeanDefinition(beanName);// 在前面我们读取configuration属性的时候,会set一个//ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE属性Object configClassAttr = beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE);MethodMetadata methodMetadata = null;// 检测是不是注解bean定义if (beanDef instanceof AnnotatedBeanDefinition) {
    methodMetadata = ((AnnotatedBeanDefinition) beanDef).getFactoryMethodMetadata();}if ((configClassAttr != null || methodMetadata != null) && beanDef instanceof AbstractBeanDefinition) {
    // Configuration class (full or lite) or a configuration-derived @Bean method// -> resolve bean class at this point...AbstractBeanDefinition abd = (AbstractBeanDefinition) beanDef;if (!abd.hasBeanClass()) {
    try {
    abd.resolveBeanClass(this.beanClassLoader);}catch (Throwable ex) {
    throw new IllegalStateException("Cannot load configuration class: " + beanDef.getBeanClassName(), ex);}}}if (ConfigurationClassUtils.CONFIGURATION_CLASS_FULL.equals(configClassAttr)) {
    if (!(beanDef instanceof AbstractBeanDefinition)) {
    throw new BeanDefinitionStoreException("Cannot enhance @Configuration bean definition '" +beanName + "' since it is not stored in an AbstractBeanDefinition subclass");}else if (logger.isInfoEnabled() && beanFactory.containsSingleton(beanName)) {
    logger.info("Cannot enhance @Configuration bean definition '" + beanName +"' since its singleton instance has been created too early. The typical cause " +"is a non-static @Bean method with a BeanDefinitionRegistryPostProcessor " +"return type: Consider declaring such methods as 'static'.");}//这里会存取你的配置类configBeanDefs.put(beanName, (AbstractBeanDefinition) beanDef);}}if (configBeanDefs.isEmpty()) {
    // nothing to enhance -> return immediatelyreturn;}ConfigurationClassEnhancer enhancer = new ConfigurationClassEnhancer();for (Map.Entry<String, AbstractBeanDefinition> entry : configBeanDefs.entrySet()) {
    AbstractBeanDefinition beanDef = entry.getValue();// If a @Configuration class gets proxied, always proxy the target classbeanDef.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE);// Set enhanced subclass of the user-specified bean classClass<?> configClass = beanDef.getBeanClass();// 使用代理类来增强Class<?> enhancedClass = enhancer.enhance(configClass, this.beanClassLoader);if (configClass != enhancedClass) {
    if (logger.isTraceEnabled()) {
    logger.trace(String.format("Replacing bean definition '%s' existing class '%s' with " +"enhanced class '%s'", entry.getKey(), configClass.getName(), enhancedClass.getName()));}beanDef.setBeanClass(enhancedClass);}}}

这个方法我在看的时候其实很简单就看出来这个是用来干嘛的,其实就是用来生成Cglib代理类的,
这个代理类主要是代理配置类里面的@Bean注释的方法。而是否生成代理类就是根据proxyBeanMethods属性来决定的(true代表增强,false表示不增强)

  相关解决方案