Spring --- 容器与Bean

1、容器接口

1.1 BeanFactory 是什么?

  1. 它是 ApplicationContext 的父接口
  2. 它是 Spring 的核心容器,主要的 ApplicationContext 实现了【组合】了它的功能

1.2 BeanFactory 能干些什么?

  1. 从代码看表面上只有 getBean,看下图 BeanFactory 的所有方法
  2. 实际上控制反转,基本的依赖注入、Bean 的生命周期的各种功能,都由它的实现类 DefaultListableBeanFactory 提供

1.3 DefaultListableBeanFactory

DefaultListableBeanFactory 是 Spring 框架中的一个核心类,用于管理和配置 Bean 实例。它是 BeanFactory 接口的默认实现,提供了完整的 Bean 工厂功能,包括 Bean 的注册、依赖注入、生命周期管理等。

主要功能

DefaultListableBeanFactory 提供了以下主要功能:

  • Bean 注册:支持通过编程方式或配置文件注册 Bean 定义。
  • 依赖注入:自动解析 Bean 之间的依赖关系,并完成注入。
  • Bean 生命周期管理:管理 Bean 的初始化、销毁等生命周期回调。
  • Bean 查找:根据名称或类型查找 Bean 实例。
ConfigurableApplicationContext context = SpringApplication.run(A01Application.class, args);
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); 
System.out.println(beanFactory);

// 运行结果
org.springframework.beans.factory.support.DefaultListableBeanFactory@2a3591c5: defining beans ......................................

通过关系图可以看到大部分都是接口和抽象类,其中 DefaultSingletonBeanRegistry 就是存放单例对象的实现类

1.4 DefaultSingletonBeanRegistry

它是 SingletonBeanRegistry 接口的默认实现,提供了单例 Bean 的注册、获取、销毁等功能。

主要功能

DefaultSingletonBeanRegistry 提供了以下主要功能:

  • 注册单例 Bean:通过 registerSingleton 方法,可以将一个单例 Bean 注册到容器中。
  • 获取单例 Bean:通过 getSingleton 方法,可以根据 Bean 的名称获取已注册的单例 Bean。
  • 销毁单例 Bean:通过 destroySingleton 方法,可以销毁指定的单例 Bean。
  • 管理 Bean 的依赖关系:通过 registerDependentBean 和 getDependentBeans 方法,可以管理 Bean 之间的依赖关系。
Field singletonObjects = DefaultSingletonBeanRegistry.class.getDeclaredField("singletonObjects");
singletonObjects.setAccessible(true);
Map<String, Object> map = (Map<String, Object>) singletonObjects.get(beanFactory);
map.entrySet().stream().forEach(e -> System.out.println(e.getKey() + " = " + e.getValue()));

1.5 ApplicationContext 有哪些扩展功能?

1.5.1 国际化

System.out.println(context.getMessage("hi", null, Locale.CHINA));
System.out.println(context.getMessage("hi", null, Locale.ENGLISH));

1.5.2 获取资源

Resource resource = context.getResource("classpath:application.yml");
System.out.println(resource);

Resource[] resources = context.getResources("classpath*:META-INF/spring.factories");
Arrays.stream(resources).forEach(System.out::println);

1.5.3 获取环境变量

System.out.println(context.getEnvironment().getProperty("java_home"));
System.out.println(context.getEnvironment().getProperty("server.port"));

1.5.4 事件发布

import org.springframework.context.ApplicationEvent;

public class UserRegisteredEvent extends ApplicationEvent {
    public UserRegisteredEvent(Object source) {
        super(source);
    }
}
 // 事件发布
context.publishEvent(new UserRegisteredEvent(context));

2、容器实现

2.1 BeanFactory 实现

public class TestBeanFactory {

    @Configuration
    static class Config {

        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2() {
            return new Bean2();
        }
    }

    @Slf4j
    static class Bean1 {

        public Bean1() {
            log.debug("构造 Bean1()");
        }

        @Autowired
        private Bean2 bean2;

        public Bean2 getBean2() {
            return bean2;
        }
    }

    @Slf4j
    static class Bean2 {
        public Bean2() {
            log.debug("构造 Bean2()");
        }
    }
}

2.2 Bean 注册

DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// bean 的定义 (class, scope, 初始化方法, 销毁)
AbstractBeanDefinition beanDefinition =
                BeanDefinitionBuilder.genericBeanDefinition(Config.class).setScope(BeanDefinition.SCOPE_SINGLETON).getBeanDefinition();
        // 注册 beanDefinition
beanFactory.registerBeanDefinition("config", beanDefinition);
// 获取 beanDefinitionName
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
}



// 输出结果
config

2.3 BeanFactoryPostProcessor

这里有个疑问,Config 类已经加了  @Configuration 注解,按照以往使用 Spring 时,Bean1、Bean2 都应该注册到 BeanFactory,可是输出结果只有 config,这说明 BeanFactory 缺少解析 @Configuration 注解的能力,而是由 BeanFactory 添加的后处理器来解析

// 给 BeanFactory 添加一些常用的后处理器
AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
}


// 输出结果
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory

这里多了5个 bean,从名字就可以看出 org.springframework.context.annotation.internalConfigurationAnnotationProcessor,就是处理 @Configuration 注解的,而此时后处理器是没有工作的

我们先调用 BeanFactoryPostProcessor.postProcessBeanFactory(),来解析@Configuration

// BeanFactory 后处理器主要功能,补充了一些 bean 的定义
beanFactory.getBeansOfType(BeanFactoryPostProcessor.class).values()
               .forEach(beanFactoryPostProcessor -> beanFactoryPostProcessor.postProcessBeanFactory(beanFactory));
for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
    System.out.println(beanDefinitionName);
}


// 输出结果
config
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
bean1
bean2

可以看到这时 bean1 和 bean2 都已注册到 BeanFactory 中

internalConfigurationAnnotationProcessor  -->> ConfigurationClassPostProcessor

// 解析 @Configuration、@Bean 等配置类注解

internalAutowiredAnnotationProcessor -->> AutowiredAnnotationBeanPostProcessor

// 解析 @Autowired 注解

internalCommonAnnotationProcessor -->> CommonAnnotationBeanPostProcessor

// 解析 @Resource 注解

internalEventListenerProcessor -->>   EventListenerMethodProcessor

// 解析 @EventListener 注解

internalEventListenerFactory -->>DefaultEventListenerFactory

// 用于 创建事件监听器实例, 在 EventListenerMethodProcessor.processBean()调用了

获取 bean

Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println("获取bean2 >>" + bean1.getBean2());


// 输出结果
15:07:59.137 [main] DEBUG com.example.spring.a02.TestBeanFactory$Bean1 - 构造 Bean1()
获取bean2 >> null

2.4 BeanPostProcessor

日志发现 Bean1 实例化了,但是并没有注入 Bean2,也没有对 Bean2 实例化,这是因为 @Autowired和 @Resource 是由 BeanPostProcessor 处理的,也就是 AutowiredAnnotationBeanPostProcessor 和 CommonAnnotationBeanPostProcessor

// Bean 后处理器,针对 bean 的生命周期的各个阶段提供扩展,例如 @Autowired  @Resource
beanFactory.getBeansOfType(BeanPostProcessor.class).values()
       .forEach(beanFactory::addBeanPostProcessor);

Bean1 bean1 = beanFactory.getBean(Bean1.class);
System.out.println("获取bean2 >> " + bean1.getBean2());;


// 输出结果
15:52:36.665 [main] DEBUG com.example.spring.a02.TestBeanFactory$Bean1 - 构造 Bean1()
15:52:36.671 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'bean2'
15:52:36.671 [main] DEBUG com.example.spring.a02.TestBeanFactory$Bean2 - 构造 Bean2()
获取bean2 >> com.example.spring.a02.TestBeanFactory$Bean2@4461c7e3

2.5 主动实例化单例 Bean

这里又会发现,Bean 的实例化在 getBean 时才创建,并不是 BeanFactory 注册时创建的,形成了懒加载的现象,这是因为需要调用 beanFactory.preInstantiateSingletons() 提前实例化单例,如果加上了 @Lazy 注解的 bean 就不会实例化了

//         提前实例化 bean,如果比调用此方法,bean只有在首次调用 beanFactory.getBean() 才会实例化,除了有 @Lazy 的bean
 beanFactory.preInstantiateSingletons();

但是如果在 bean1 加上了 @Lazy 注解,就会发现只实例化了 bean2 

如果在 bean2 加上 @Lazy 注解,按理说 bean2 不会实例化,可是日志中却显示实例化了 bean2

哇哦!!!这是什么道理呢,刚才说了 beanFactory.preInstantiateSingletons() 不会实例化加上 @Lazy 注解的 bean ???

仔细用脚趾头想一下就明白了,这是因为在 Bean1 中需要注入 Bean2,所以就需要一起把 Bean2 实例化了呀

那不想 bean2 提前实例化,需要在注入 bean2 的地方也加上 @Lazy 注解

小总结:

BeanFactory 不会做的事情

  1. 不会主动调用 BeanFactory 后处理器
  2. 不会主动添加 Bean 后处理器
  3. 不会主动初始化单例
  4. 不会解析 beanFactory 还不会解析占位符( ${ } 与 #{ } )                

2.6 扩展:BeanPostProcessor 的执行顺序

引出问题

先抛出一个不可能使用的问题:如果一个注入既加了 @Autowired 也加了 @Resouce,那是 @Autowired 先注入,还是 @Resource 先注入???

先加些代码

这里在 Bean1 注入 Inter,但是 @Autowired 是通过类型注入的,Bean3 和 Bean4 都实现了 Inter,@Autowired 不知道该注入哪个 Bean,所以运行后会报错

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'bean1': Unsatisfied dependency expressed through field 'inter'; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.spring.a02.TestBeanFactory$Inter' available: expected single matching bean but found 2: bean3,bean4
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:660)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:640)
	at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:119)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:399)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1431)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:619)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:335)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:333)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:208)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:955)
	at com.example.spring.a02.TestBeanFactory.main(TestBeanFactory.java:61)
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.example.spring.a02.TestBeanFactory$Inter' available: expected single matching bean but found 2: bean3,bean4
	at org.springframework.beans.factory.config.DependencyDescriptor.resolveNotUnique(DependencyDescriptor.java:220)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1369)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1311)
	at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:657)
	... 12 more

可以将属性名改成 bean3,因为如果Bean的类型又多个,可以通过 bean 名称匹配

那加了@Resource(name = "bean4"),就会注入 Bean4

 

那我们回到上方引出的问题,既加了 @Autowired 也加了 @Resouce,到底是注入 Bean3 还是Bean4 呢?答案是 Bean3

所以是问题的答案是 @Autowired 先注入

问题分析

这是因为 BeanPostProcessor 是有执行顺序的,在上方代码中我手动调用了 BeanPostProcessor,顺序是由 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory) 注册的

先改一下代码,输出一下 BeanPostProcessor 的顺序

从日志可以看到,AutowiredAnnotationBeanPostProcessor 在 CommonAnnotationBeanPostProcessor前面

那顺序可以控制吗?答案是:可以的,加入比较器进行逆序添加,输出的顺序就改变了,而且注入的 Bean也变成了 bean4

那 beanFactory.getDependencyComparator() 这个比较器从哪来的呢?

我们看一下 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory);

可以看到是set了 AnnotationAwareOrderComparator 比较器,实现了 Comparator 接口,

AnnotationAwareOrderComparator 的 compare 方法是继承父类 OrderComparator

我们可以看到,最终是调用了 bean 对象的 getOrder() 方法,那我们分别看一下两个类的 order 

从代码可以看到,CommonAnnotationBeanPostProcessor的 Order 值更小,所所以 sorted(beanFactory.getDependencyComparator()) 进行排序后,CommonAnnotationBeanPostProcessor 排在了前面执行,所以就先注册了 bean4

Spring 内的执行顺序

首先告诉你结果,Spring 内部也是调用的 AnnotationConfigUtils.registerAnnotationConfigProcessors(beanFactory) 加入 BeanPostProcessor 的,但是 CommonAnnotationBeanPostProcessor 是先执行的,

那我们看一下源码

AbstractApplicationContext.refresh()


registerBeanPostProcessors(beanFactory); 很明显就是注册 BeanPostProcessor

public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {
    // 获取 bean 后处理器名字
    String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

    int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
    beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

    // 将实现PriorityOrdered、Ordered和其他功能的BeanPostProcessors分开。
    // 实现优先级排序的后处理器
    List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
    // 内部后处理器
    List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
    List<String> orderedPostProcessorNames = new ArrayList<>();
    List<String> nonOrderedPostProcessorNames = new ArrayList<>();
    for (String ppName : postProcessorNames) {
        if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
            BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
            priorityOrderedPostProcessors.add(pp);
            if (pp instanceof MergedBeanDefinitionPostProcessor) {
                internalPostProcessors.add(pp);
            }
        }
        else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
            orderedPostProcessorNames.add(ppName);
        }
        else {
            nonOrderedPostProcessorNames.add(ppName);
        }
    }

    // 首先注册实现优先级排序的后处理器
    sortPostProcessors(priorityOrderedPostProcessors, beanFactory); // 根据 order 排序
    // 注册,其实内部实现就是添加到 beanFactory 中的 Bean后处理器的列表 ( CopyOnWriteArrayList )
    registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); 

    // 再注册实现 Orderd 接口的后处理器
    List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
    for (String ppName : orderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        orderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    sortPostProcessors(orderedPostProcessors, beanFactory);
    // 注册,其实内部实现就是添加到 beanFactory 中的 Bean后处理器的列表 ( CopyOnWriteArrayList )
    registerBeanPostProcessors(beanFactory, orderedPostProcessors);

    // 注册所有常规后处理器
    List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
    for (String ppName : nonOrderedPostProcessorNames) {
        BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
        nonOrderedPostProcessors.add(pp);
        if (pp instanceof MergedBeanDefinitionPostProcessor) {
            internalPostProcessors.add(pp);
        }
    }
    registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

    // 最后,重新注册所有内部后处理器
    sortPostProcessors(internalPostProcessors, beanFactory);
    registerBeanPostProcessors(beanFactory, internalPostProcessors);

    // 添加 识别并注册ApplicationListener 的后处理器
    beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
}

来看一下排序的方法

排序之前的顺序 

排序之后的顺序

我们可以看到,排序之后 CommonAnnotationBeanPostProcessor 在 AutowiredAnnotationBeanPostProcessor 之前

那 Spring 内部的执行逻辑就已经很明了了,CommonAnnotationBeanPostProcessor 先执行,所以注入的是 Bean4

2.2 ApplicationContext 实现

2.2.1 ClassPathXmlApplicationContext

2.2.2 FileSystemXmlApplicationContext

2.2.3 AnnotationConfigApplicationContext

2.2.4 AnnotationConfigServletWebServerApplicationContext

3、Bean 的生命周期

3.1 Spring Bean 生命周期各个阶段

@Component
@Slf4j
public class LifeCycleBean {

    public LifeCycleBean() {
        log.debug("构造 LifeCycleBean");
    }

    @Autowired
    public void autowire(@Value("${JAVA_HOME}") String home) {
        log.debug("依赖注入:{}", home);
    }

    @PostConstruct
    public void init() {
        log.debug("初始化");
    }

    @PreDestroy
    public void destroy() {
        log.debug("销毁");
    }
}
@Component
@Slf4j
public class MyBeanPostProcessor implements InstantiationAwareBeanPostProcessor, DestructionAwareBeanPostProcessor {
    @Override
    public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<<<<<< 销毁之前执行,如 @PreDestroy ");
        }
    }

    @Override
    public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<<<<<< 实例化之前执行,这里返回的对象会替换掉原本的 bean ");
        }
        return null;
    }

    @Override
    public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<<<<<< 实例化之后执行,如果返回false 会跳过依赖注入阶段 ");
        }
        return true;
    }

    @Override
    public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<<<<<< 依赖注入阶段执行,如 @Autowired、@Value、@Resource ");
        }
        return pvs;
    }

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<<<<<< 初始化之前执行,这里返回的对象会替换掉原本的 bean, 如 @PostConstruct、@ConfigurationProperties ");
        }
        return bean;
    }
    
    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        if (beanName.equals("lifeCycleBean")) {
            log.debug("<<<<<<<<<<<< 初始化之后执行,这里返回的对象会替换掉原本的 bean, 如 代理增强 ");
        }
        return bean;
    }
}

@SpringBootApplication
public class A03Application {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(A03Application.class, args);
        context.close();
    }
}

3.2 模板方法

提高扩展性

public class TestMethodTemplate {

    public static void main(String[] args) {
        MyBeanFactory beanFactory = new MyBeanFactory();
        beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Autowired"));
        beanFactory.addBeanPostProcessor(bean -> System.out.println("解析 @Resource"));
        beanFactory.getBean();
    }

    static class MyBeanFactory {
        public Object getBean() {
            Object bean = new Object();
            System.out.println("构造 " + bean);
            System.out.println("依赖注入 " + bean);
            for (BeanPostProcessor processor : processors) {
                processor.inject(bean);
            }
            System.out.println("初始化 " + bean);

            return bean;
        }

        private List<BeanPostProcessor> processors = new ArrayList<>();

        public void addBeanPostProcessor(BeanPostProcessor beanPostProcessor) {
            processors.add(beanPostProcessor);
        }
    }

    static interface BeanPostProcessor {
        // 对依赖注入阶段的扩展
        public void inject(Object bean);

    }
}

4、Bean 后处理器

4.1 Bean 后处理器的作用

为 Bean 生命周期各个阶段提供扩展

  • AutowiredAnnotationBeanPostProcessor  // 解析 @Autowired @Value

  • CommonAnnotationBeanPostProcessor    // 解析 @Resource @PostConstruct @PreDestroy

  • ConfigurationPropertiesBindingPostProcessor  // 解析 @ConfigurationProperties

4.2 AutowiredAnnotationBeanPostProcessor 运行分析

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) {
    // 获取 Bean 加了 @Autowired @Value 的成员变量、方法参数信息
    InjectionMetadata metadata = findAutowiringMetadata(beanName, bean.getClass(), pvs);
    try {
        // 调用 InjectionMetadata 来进行依赖注入,注入时按类型查找值
        metadata.inject(bean, beanName, pvs);
    }
    catch (BeanCreationException ex) {
        throw ex;
    }
    catch (Throwable ex) {
        throw new BeanCreationException(beanName, "Injection of autowired dependencies failed", ex);
    }
    return pvs;
}
public class InjectionMetadata {
    public void inject(Object target, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
        Collection<InjectedElement> checkedElements = this.checkedElements;
        Collection<InjectedElement> elementsToIterate =
                (checkedElements != null ? checkedElements : this.injectedElements);
        if (!elementsToIterate.isEmpty()) {
            // 遍历获取到的要注入的元素
            for (InjectedElement element : elementsToIterate) {
                element.inject(target, beanName, pvs);
            }
        }
    }
}

InjectedElement有两个实现类

  • AutowiredFieldElement      // 通过属性注入

  • AutowiredMethodElement   //  通过方法注入

public class AutowiredAnnotationBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor, MergedBeanDefinitionPostProcessor, PriorityOrdered, BeanFactoryAware { 
    private class AutowiredFieldElement extends InjectionMetadata.InjectedElement {
        @Override
        protected void inject(Object bean, @Nullable String beanName, @Nullable PropertyValues pvs) throws Throwable {
            Field field = (Field) this.member;
            Object value;
            if (this.cached) {
                try {
                    value = resolvedCachedArgument(beanName, this.cachedFieldValue);
                }
                catch (NoSuchBeanDefinitionException ex) {
                    // Unexpected removal of target bean for cached argument -> re-resolve
                    value = resolveFieldValue(field, bean, beanName);
                }
            }
            else {
                // 解析属性值
                value = resolveFieldValue(field, bean, beanName);
            }
            if (value != null) {
                // 通过反射set属性值
                ReflectionUtils.makeAccessible(field);
                field.set(bean, value);
            }
        }

        @Nullable
        private Object resolveFieldValue(Field field, Object bean, @Nullable String beanName) {
            // 将属性封装成即将将注入的特定依赖项的描述符。包装构造函数参数、方法参数或字段,允许统一访问其元数据
            DependencyDescriptor desc = new DependencyDescriptor(field, this.required);
            desc.setContainingClass(bean.getClass());
            Set<String> autowiredBeanNames = new LinkedHashSet<>(1);
            Assert.state(beanFactory != null, "No BeanFactory available");
            // 获取类型转换器
            TypeConverter typeConverter = beanFactory.getTypeConverter();
            Object value;
            try {
                // beanFactory 解析依赖,获取需要的注入值
                value = beanFactory.resolveDependency(desc, beanName, autowiredBeanNames, typeConverter);
            }
            catch (BeansException ex) {
                throw new UnsatisfiedDependencyException(null, beanName, new InjectionPoint(field), ex);
            }
            synchronized (this) {
                if (!this.cached) {
                    Object cachedFieldValue = null;
                    if (value != null || this.required) {
                        cachedFieldValue = desc;
                        registerDependentBeans(beanName, autowiredBeanNames);
                        if (autowiredBeanNames.size() == 1) {
                            String autowiredBeanName = autowiredBeanNames.iterator().next();
                            if (beanFactory.containsBean(autowiredBeanName) &&
                                    beanFactory.isTypeMatch(autowiredBeanName, field.getType())) {
                                cachedFieldValue = new ShortcutDependencyDescriptor(
                                        desc, autowiredBeanName, field.getType());
                            }
                        }
                    }
                    this.cachedFieldValue = cachedFieldValue;
                    this.cached = true;
                }
            }
            return value;
        }
    }
}
public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFactory implements ConfigurableListableBeanFactory, BeanDefinitionRegistry, Serializable {
    @Override
    @Nullable
    public Object resolveDependency(DependencyDescriptor descriptor, @Nullable String requestingBeanName,
            @Nullable Set<String> autowiredBeanNames, @Nullable TypeConverter typeConverter) throws BeansException {

        descriptor.initParameterNameDiscovery(getParameterNameDiscoverer());
        if (Optional.class == descriptor.getDependencyType()) {
            return createOptionalDependency(descriptor, requestingBeanName);
        }
        else if (ObjectFactory.class == descriptor.getDependencyType() ||
                ObjectProvider.class == descriptor.getDependencyType()) {
            return new DependencyObjectProvider(descriptor, requestingBeanName);
        }
        else if (javaxInjectProviderClass == descriptor.getDependencyType()) {
            return new Jsr330Factory().createDependencyProvider(descriptor, requestingBeanName);
        }
        else {
            Object result = getAutowireCandidateResolver().getLazyResolutionProxyIfNecessary(
                    descriptor, requestingBeanName);
            if (result == null) {
                // 这里做解析依赖
                result = doResolveDependency(descriptor, requestingBeanName, autowiredBeanNames, typeConverter);
            }
            return result;
        }
    }
}

由于源码太多,这里就不继续深扒了,我们知道了最后是调用 DefaultListableBeanFactory.doResolveDependency 获取注入值

我们将代码简化处理,逻辑就简单清晰了,

// 按属性名注入
Field bean3Field = Bean1.class.getDeclaredField("bean3");
DependencyDescriptor dd1 = new DependencyDescriptor(bean3Field, true);
Object bea3 = beanFactory.doResolveDependency(dd1, null, null, null);
System.out.println(bea3);
ReflectionUtils.makeAccessible(bean3Field);
bean3Field.set(bean1, bea3);

// 按方法注入
Method setBean2 = Bean1.class.getDeclaredMethod("setBean2", Bean2.class);
DependencyDescriptor dd2 = new DependencyDescriptor(new MethodParameter(setBean2, 0), true);
Object bean2 = beanFactory.doResolveDependency(dd2, null, null, null);
ReflectionUtils.makeAccessible(setBean2);
setBean2.invoke(bean1, bean2);

// @Value注入
Method setHome = Bean1.class.getDeclaredMethod("setHome", String.class);
DependencyDescriptor dd3 = new DependencyDescriptor(new MethodParameter(setHome, 0), true);
Object home = beanFactory.doResolveDependency(dd3, null, null, null);
ReflectionUtils.makeAccessible(setHome);
setHome.invoke(bean1, home);

5、BeanFactory 后处理器

5.1 BeanFactory 后处理器的作用

为BeanFactory 提供扩展

5.2 常见的 BeanFactory 后处理器

BeanFactoryPostProcessor 作用

ConfigurationClassPostProcessor

解析  

@ComponentScan @Bean @Import @ImportResource

MapperScannerConfigurer

@MapperScanner  mybatis扫描 mapper

5.3 ConfigurationClassPostProcessor 源码解析

ConfigurationClassPostProcessor实现了BeanDefinitionRegistryPostProcessor ,而BeanDefinitionRegistryPostProcessor 继承了BeanFactoryPostProcessor ,按照之前分析过的容器刷新流程,ConfigurationClassPostProcessor 会先执行postProcessBeanDefinitionRegistry,再处理postProcessBeanFactory方法

5.3.1 postProcessBeanDefinitionRegistry

ConfigurationClassPostProcessor先执行postProcessBeanDefinitionRegistry:

public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
		int registryId = System.identityHashCode(registry);
		if (this.registriesPostProcessed.contains(registryId)) {
			// throw ...
		}
		if (this.factoriesPostProcessed.contains(registryId)) {
			// throw new ...
		}
		this.registriesPostProcessed.add(registryId);

		processConfigBeanDefinitions(registry);
	}

重点在最后一行 processConfigBeanDefinitions,它会过滤出所有配置类,然后循环解析每个配置类并注册配置类的bean定义。总览 processConfigBeanDefinitions 源码:

public void processConfigBeanDefinitions(BeanDefinitionRegistry registry) {
    List<BeanDefinitionHolder> configCandidates = new ArrayList<>();
    //从BeanDefinitionRegistry中取注册的全部bean名
    String[] candidateNames = registry.getBeanDefinitionNames();

    for (String beanName : candidateNames) {
        BeanDefinition beanDef = registry.getBeanDefinition(beanName);
        if (beanDef.getAttribute(ConfigurationClassUtils.CONFIGURATION_CLASS_ATTRIBUTE) != null) {
            if (logger.isDebugEnabled()) {
                logger.debug("Bean definition has already been processed as a configuration class: " + beanDef);
            }
        }
        // checkConfigurationClassCandidate判断一个类是否配置类,并为BeanDefinition设置属性lite或full
        else if (ConfigurationClassUtils.checkConfigurationClassCandidate(beanDef, this.metadataReaderFactory)) {
            configCandidates.add(new BeanDefinitionHolder(beanDef, beanName));
        }
    }

    // Return immediately if no @Configuration classes were found
    if (configCandidates.isEmpty()) {
        return;
    }

    // Sort by previously determined @Order value, if applicable
    // 按照 Order 值排序
    configCandidates.sort((bd1, bd2) -> {
        int i1 = ConfigurationClassUtils.getOrder(bd1.getBeanDefinition());
        int i2 = ConfigurationClassUtils.getOrder(bd2.getBeanDefinition());
        return Integer.compare(i1, i2);
    });

    // 设置 beanName 生成器
    SingletonBeanRegistry sbr = null;
    if (registry instanceof SingletonBeanRegistry) {
        sbr = (SingletonBeanRegistry) registry;
        // 没有手动设置 beanName 生成器
        if (!this.localBeanNameGeneratorSet) {
            // 从单例获取 beanName 生成器,默认是没有的,返回null
            BeanNameGenerator generator = (BeanNameGenerator) sbr.getSingleton(
                    AnnotationConfigUtils.CONFIGURATION_BEAN_NAME_GENERATOR);
            if (generator != null) {
                this.componentScanBeanNameGenerator = generator;
                this.importBeanNameGenerator = generator;
            }
        }
    }

    if (this.environment == null) {
        this.environment = new StandardEnvironment();
    }

    // Parse each @Configuration class
    // 创建配置类解析器
    ConfigurationClassParser parser = new ConfigurationClassParser(
            this.metadataReaderFactory, this.problemReporter, this.environment,
            this.resourceLoader, this.componentScanBeanNameGenerator, registry);

    Set<BeanDefinitionHolder> candidates = new LinkedHashSet<>(configCandidates);
    Set<ConfigurationClass> alreadyParsed = new HashSet<>(configCandidates.size());
    do {
        StartupStep processConfig = this.applicationStartup.start("spring.context.config-classes.parse");
        //配置类解析,在此处会解析配置类上的注解(ComponentScan扫描出的类,@Import注册的类,以及@Bean方法定义的类)
        parser.parse(candidates);
        parser.validate();

        Set<ConfigurationClass> configClasses = new LinkedHashSet<>(parser.getConfigurationClasses());
        configClasses.removeAll(alreadyParsed);

        // Read the model and create bean definitions based on its content
        if (this.reader == null) {
            this.reader = new ConfigurationClassBeanDefinitionReader(
                    registry, this.sourceExtractor, this.resourceLoader, this.environment,
                    this.importBeanNameGenerator, parser.getImportRegistry());
        }
        //Bean定义注册
        this.reader.loadBeanDefinitions(configClasses);
        alreadyParsed.addAll(configClasses);
        processConfig.tag("classCount", () -> String.valueOf(configClasses.size())).end();

        candidates.clear();

        // 判断reader.loadBeanDefinitions(configClasses)有没有添加新的anDefinition
        // 若有,则nDefinitionCount()大于candidateNames.length
        //则需要把新加入的还没有被解析过的bean重新加入到candidates变量中,重新执行一遍配置类解析和Bean定义注册
        if (registry.getBeanDefinitionCount() > candidateNames.length) {
            String[] newCandidateNames = registry.getBeanDefinitionNames();
            Set<String> oldCandidateNames = new HashSet<>(Arrays.asList(candidateNames));
            Set<String> alreadyParsedClasses = new HashSet<>();
            for (ConfigurationClass configurationClass : alreadyParsed) {
                alreadyParsedClasses.add(configurationClass.getMetadata().getClassName());
            }
            // 未解析的类添加到candidates中,就会进入到下一次的while的循环
            for (String candidateName : newCandidateNames) {
                if (!oldCandidateNames.contains(candidateName)) {
                    BeanDefinition bd = registry.getBeanDefinition(candidateName);
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bd, this.metadataReaderFactory) &&
                            !alreadyParsedClasses.contains(bd.getBeanClassName())) {
                        candidates.add(new BeanDefinitionHolder(bd, candidateName));
                    }
                }
            }
            candidateNames = newCandidateNames;
        }
    }
    while (!candidates.isEmpty());

    // Register the ImportRegistry as a bean in order to support ImportAware @Configuration classes
    if (sbr != null && !sbr.containsSingleton(IMPORT_REGISTRY_BEAN_NAME)) {
        sbr.registerSingleton(IMPORT_REGISTRY_BEAN_NAME, parser.getImportRegistry());
    }

    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.
        ((CachingMetadataReaderFactory) this.metadataReaderFactory).clearCache();
    }
}

5.3.2 判断候选配置类

checkConfigurationClassCandidate 方法判断一个类是否配置类,并为BeanDefinition设置属性lite或full。Spring 文档说明了 @Configuration 的 lite 模式或 full 模式。简单说就是 @Bean 方法的返回值会注入到容器中,如果 @Bean 方法所在的类被 @Configuration 标注,就是full模式,这种模式会给配置类通过 CGLIB 生成一个代理,所有 @Bean 标注的方法都是通过代理进行的;如果 @Bean 方法所在类被 @Configuration 以外注解如 @Component 标注,或被 Configuration 标注,但它的属性 proxyBeanMethods 是false,就是 lite 模式,这种模式不会生成代理,某个 @Bean 方法中如果需要其他 @Bean 方法返回的对象,就要从容器中取出一个新对象了。

abstract class ConfigurationClassUtils {

    public static final String CONFIGURATION_CLASS_FULL = "full";
    public static final String CONFIGURATION_CLASS_LITE = "lite";
    public static final String CONFIGURATION_CLASS_ATTRIBUTE = Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "configurationClass");
    private static final String ORDER_ATTRIBUTE = Conventions.getQualifiedAttributeName(ConfigurationClassPostProcessor.class, "order");
    private static final Set<String> candidateIndicators = new HashSet<>(8);
    static {
        candidateIndicators.add(Component.class.getName());
        candidateIndicators.add(ComponentScan.class.getName());
        candidateIndicators.add(Import.class.getName());
        candidateIndicators.add(ImportResource.class.getName());
    }

    public static boolean checkConfigurationClassCandidate(BeanDefinition beanDef, MetadataReaderFactory metadataReaderFactory) {
        String className = beanDef.getBeanClassName();
        if (className == null || beanDef.getFactoryMethodName() != null) {
            return false;
        }
        AnnotationMetadata metadata;
        // if ...else if...else 解析元数据,具体请看源代码
        Map<String, Object> config = metadata.getAnnotationAttributes(Configuration.class.getName());
        // full 模式:类上有 @Configuration 注解,并且 proxyBeanMethods 字段为 true
        if (config != null && !Boolean.FALSE.equals(config.get("proxyBeanMethods"))) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_FULL);
        }
        // lite 模式: 类上有 @Configuration 且 proxyBeanMethods 为 false 或者 类上有 @Component、@ComponentScan、@Import、@ImportResource
        else if (config != null || isConfigurationCandidate(metadata)) {
            beanDef.setAttribute(CONFIGURATION_CLASS_ATTRIBUTE, CONFIGURATION_CLASS_LITE);
        }
        else {
            return false;
        }

        // 设置排序属性
        Integer order = getOrder(metadata);
        if (order != null) {
            beanDef.setAttribute(ORDER_ATTRIBUTE, order);
        }
        return true;
    }

  
    public static boolean isConfigurationCandidate(AnnotationMetadata metadata) {
        // 不处理接口或注解
        if (metadata.isInterface()) {
            return false;
        }
        // 判断类上是否有 @Component、@ComponentScan、@Import、@ImportResource
        for (String indicator : candidateIndicators) {
            if (metadata.isAnnotated(indicator)) {
                return true;
            }
        }
        // 判断类中是否有 @Bean 注解的方法
        return hasBeanMethods(metadata);
    }

    static boolean hasBeanMethods(AnnotationMetadata metadata) {
        try {
            return metadata.hasAnnotatedMethods(Bean.class.getName());
        }
        catch (Throwable ex) {
            log.....
            return false;
        }
    }
   
    @Nullable
    public static Integer getOrder(AnnotationMetadata metadata) {
        Map<String, Object> orderAttributes = metadata.getAnnotationAttributes(Order.class.getName());
        return (orderAttributes != null ? ((Integer) orderAttributes.get(AnnotationUtils.VALUE)) : null);
    }

    public static int getOrder(BeanDefinition beanDef) {
        Integer order = (Integer) beanDef.getAttribute(ORDER_ATTRIBUTE);
        return (order != null ? order : Ordered.LOWEST_PRECEDENCE);
    }

}

5.3.3 配置类解析

ConfigurationClassParser 的 parse 分两步,重载的parse方法解析配置类、解析 DeferredImportSelector 指定的类

class ConfigurationClassParser {

    private final DeferredImportSelectorHandler deferredImportSelectorHandler = new DeferredImportSelectorHandler();

    public void parse(Set<BeanDefinitionHolder> configCandidates) {
        for (BeanDefinitionHolder holder : configCandidates) {
            BeanDefinition bd = holder.getBeanDefinition();
            try {
                // 1、解析配置类,根据 Bean 定义类型,调用重载的 parse 方法
                if (bd instanceof AnnotatedBeanDefinition) {
                    parse(((AnnotatedBeanDefinition) bd).getMetadata(), holder.getBeanName());
                }
                else if (bd instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) bd).hasBeanClass()) {
                    parse(((AbstractBeanDefinition) bd).getBeanClass(), holder.getBeanName());
                }
                else {
                    parse(bd.getBeanClassName(), holder.getBeanName());
                }
            }
            catch (BeanDefinitionStoreException ex) {
                throw ex;
            }
            catch (Throwable ex) {
                throw new BeanDefinitionStoreException("Failed to parse configuration class [" + bd.getBeanClassName() + "]", ex);
            }
        }
        // 2. 解析 DeferredImportSelectorHandler 指定的类
        this.deferredImportSelectorHandler.process();
    }
}

重载的 parse方法会解析配置类上的注解(@ComponentScan,@Import,@Bean等等),解析完以后把结果放入到parse的缓存configurationClasses中去。每个重载的parse方法,如下面的,先把入参封装成ConfigurationClass,然后调processConfigurationClass。

   protected final void parse(@Nullable String className, String beanName) throws IOException {
        Assert.notNull(className, "No bean class name for configuration class bean definition");
        MetadataReader reader = this.metadataReaderFactory.getMetadataReader(className);
        processConfigurationClass(new ConfigurationClass(reader, beanName), DEFAULT_EXCLUSION_FILTER);
    }

    protected final void parse(Class<?> clazz, String beanName) throws IOException {
        processConfigurationClass(new ConfigurationClass(clazz, beanName), DEFAULT_EXCLUSION_FILTER);
    }

    protected final void parse(AnnotationMetadata metadata, String beanName) throws IOException {
        processConfigurationClass(new ConfigurationClass(metadata, beanName), DEFAULT_EXCLUSION_FILTER);
    }

ConfigurationClass是配置类的一种模型,为了解析配置类上加的注解,它设计了几种属性:

final class ConfigurationClass {

	private final AnnotationMetadata metadata;

	private final Resource resource;

	@Nullable
	private String beanName;
    //@Import相关
	private final Set<ConfigurationClass> importedBy = new LinkedHashSet<>(1); 
    //@Bean
	private final Set<BeanMethod> beanMethods = new LinkedHashSet<>();
    //@ImportResource相关
	private final Map<String, Class<? extends BeanDefinitionReader>> importedResources = new LinkedHashMap<>(); 
    //@Import导入的ImportBeanDefinitionRegistrar
	private final Map<ImportBeanDefinitionRegistrar, AnnotationMetadata> importBeanDefinitionRegistrars = new LinkedHashMap<>();

	final Set<String> skippedBeanMethods = new HashSet<>();
    
    //...
}
5.3.3.1 processConfigurationClass

每个配置类的解析都会执行processConfigurationClass,解析完放到缓存configurationClasses中。配置类如果有父类,就循环解析。其中SourceClass是对ConfigClass这个模型的简单包装,是为了以统一的方式处理配置类,而不管它是如何加载。

//缓存
    private final Map<ConfigurationClass, ConfigurationClass> configurationClasses = new LinkedHashMap<>();

    protected void processConfigurationClass(ConfigurationClass configClass, Predicate<String> filter) throws IOException {
        // @Condition 注解逻辑判断,如果有 @Condition 条件不满足,就不解析了
        if (this.conditionEvaluator.shouldSkip(configClass.getMetadata(), ConfigurationPhase.PARSE_CONFIGURATION)) {
            return;
        }

        ConfigurationClass existingClass = this.configurationClasses.get(configClass);
        if (existingClass != null) {
            if (configClass.isImported()) {
                if (existingClass.isImported()) {
                    existingClass.mergeImportedBy(configClass);
                }
                // Otherwise ignore new imported config class; existing non-imported class overrides it.
                return;
            }
            else {
                // Explicit bean definition found, probably replacing an import.
                // Let's remove the old one and go with the new one.
                this.configurationClasses.remove(configClass);
                this.knownSuperclasses.values().removeIf(configClass::equals);
            }
        }

        // 配置类可能有父类,循环处理,doProcessConfigurationClass会返回父类
        SourceClass sourceClass = asSourceClass(configClass, filter);
        do {
            // 真正解析配置类的方法
            sourceClass = doProcessConfigurationClass(configClass, sourceClass, filter);
        }
        while (sourceClass != null);
        // 放入缓存
        this.configurationClasses.put(configClass, configClass);
    }
5.3.3.2 doProcessConfigurationClass

doProcessConfigurationClass 具体做了以下8种处理工作:

  1. 处理配置类的内部类
  2. 处理配置类上的 @PropertySource 注解
  3. 解析配置类的 @ComponentScan 和 @ComponentScans 注解,然后根据这2种注解配置的包扫描路径,利用 ASM 技术扫描出所有需要注入的类。如果扫描出的类也加了 @ComponentScan 和 @ComponentScans,就递归扫描,直到所有加了这两个注解的类都被解析。
  4. 处理@Import注解,具体有三种解析方式。
  5. 处理@ImportResource注解。
  6. 处理配置类中标注@Bean的方法。
  7. 处理接口默认方法加@Bean的情况。
  8. 解析配置类的父类。
protected final SourceClass doProcessConfigurationClass(ConfigurationClass configClass, SourceClass sourceClass, Predicate<String> filter) throws IOException {
        // 1. @Component标注的类,其内部类也是属于配置类
        if (configClass.getMetadata().isAnnotated(Component.class.getName())) {
            // 解析内部配置类,递归处理
            processMemberClasses(configClass, sourceClass, filter);
        }

        // 2. 处理加了@PropertySource的配置类
        for (AnnotationAttributes propertySource : AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), PropertySources.class,
                org.springframework.context.annotation.PropertySource.class)) {
            if (this.environment instanceof ConfigurableEnvironment) {
                processPropertySource(propertySource);
            }
            else {
                logger.info("Ignoring @PropertySource annotation on [" + sourceClass.getMetadata().getClassName() +
                        "]. Reason: Environment must implement ConfigurableEnvironment");
            }
        }

        // 3. 处理@ComponentScan或者@ComponentScans注解
        Set<AnnotationAttributes> componentScans = AnnotationConfigUtils.attributesForRepeatable(
                sourceClass.getMetadata(), ComponentScans.class, ComponentScan.class);
        if (!componentScans.isEmpty() &&
                !this.conditionEvaluator.shouldSkip(sourceClass.getMetadata(), ConfigurationPhase.REGISTER_BEAN)) {
            for (AnnotationAttributes componentScan : componentScans) {
                // @ComponentScan和@ComponentScans指明的的扫描的包里面的类
                Set<BeanDefinitionHolder> scannedBeanDefinitions =
                        this.componentScanParser.parse(componentScan, sourceClass.getMetadata().getClassName());
                // 扫面出来的bean如果也有这2种注解,用parse递归解析
                for (BeanDefinitionHolder holder : scannedBeanDefinitions) {
                    BeanDefinition bdCand = holder.getBeanDefinition().getOriginatingBeanDefinition();
                    if (bdCand == null) {
                        bdCand = holder.getBeanDefinition();
                    }
                    if (ConfigurationClassUtils.checkConfigurationClassCandidate(bdCand, this.metadataReaderFactory)) {
                        parse(bdCand.getBeanClassName(), holder.getBeanName());
                    }
                }
            }
        }

        // 4. 处理@Import注解
        processImports(configClass, sourceClass, getImports(sourceClass), filter, true);

        // 5. 处理@ImportResource注解
        AnnotationAttributes importResource =
                AnnotationConfigUtils.attributesFor(sourceClass.getMetadata(), ImportResource.class);
        if (importResource != null) {
            String[] resources = importResource.getStringArray("locations");
            Class<? extends BeanDefinitionReader> readerClass = importResource.getClass("reader");
            for (String resource : resources) {
                // 解析出locations属性指定的文件
                String resolvedResource = this.environment.resolveRequiredPlaceholders(resource);
                configClass.addImportedResource(resolvedResource, readerClass);
            }
        }

        // 6. 处理@Bean标注的方法
        Set<MethodMetadata> beanMethods = retrieveBeanMethodMetadata(sourceClass);
        for (MethodMetadata methodMetadata : beanMethods) {
            configClass.addBeanMethod(new BeanMethod(methodMetadata, configClass));
        }

        // 7. 处理接口默认方法加@Bean
        // JDK8,接口有默认方法,默认方法有@Bean的处理
        processInterfaces(configClass, sourceClass);

        // 8. 解析父类
        if (sourceClass.getMetadata().hasSuperClass()) {
            String superclass = sourceClass.getMetadata().getSuperClassName();
            if (superclass != null && !superclass.startsWith("java") &&
                    !this.knownSuperclasses.containsKey(superclass)) {
                this.knownSuperclasses.put(superclass, configClass);
                // 有父类就返回父类
                return sourceClass.getSuperClass();
            }
        }

        // 没有父类返回null
        return null;
    }

目前我们就先分析到这,再详细的分析可以看https://juejin.cn/post/7448889636338696211

6、Aware 接口

1. Aware 接口用于注入一些与容器相关信息,例如
    a. BeanNameAware 注入 bean 的名字
    b. BeanFactoryAware 注入 BeanFactory 容器
    c. ApplicationContextAware 注入 ApplicationContext 容器
    d. EmbeddedValueResolverAware ${}

2、上述的 b、c、d 的功能用 @Autowired 就能实现,为啥还要用 Aware 接口呢:

简单的说:
    a. @Autowired 的解析需要用到 bean 后处理器,属于扩展功能
    b. 而 Aware 接口属于内置功能,不加任何扩展,Spring 就能识别

3、配置类@Autowired失效分析

输出显示,@Autowired 和 @PostConstruct 失效了,未输出日志

问题分析:

Java 类不包含 BeanPostProcessor 的情况:

java配置类包含BeanFactoryPostProcessor的情况,因此要创建其中的BeanFactoryPostProcessor必须提前创建Java配置类,而此时BeanPostProcessor还没准备好,也就导致@Autowired等注解失效

7、初始化与销毁

Spring 提供的初始化和销毁方式都是三种

  • 初始化(执行顺序如下)
    • @PostConstruct
    • 实现 InitializingBean
    • @Bean(initMethod = "init")
  • 销毁(执行顺序如下)
    • @PreDestroy
    • 实现 DisposableBean
    • @Bean(destroyMethod = "destory")

代码示例

 

8、Scope

Scope 类型有哪些

  • singleton:默认作用域,每个Spring 容器种只有一个实例,适用于无状态Bean,如工具类、配置类。
  • prototype:每次请求都会创建一个实例,适用于有状态的Bean,如用户会话、请求处理类。
  • request:每个 Http 请求创建一个实例,仅在Web应用中有效,适用于请求级别的数据,如表单提交。
  • session:每个 Http 绘画创建一个实例,仅在Web应用中有效。适用于用户会话数据,如登录信息。
  • application:每个 ServletContext 创建要给实例,仅在Web应用中有效。适用于全局共享数据,如应用配置。

scope 失效分析

singletonBean注入prototypeBean,在获取prototypeBean时,发现时同一个对象

解决方法:

  1. 注入prototypeBean 加上 @Lazy
  2. prototypeBean的类上 @Scope(value = "request", proxyMode = ScopedProxyMode.TARGET_CLASS)
  3. 注入prototypeBean 使用 ObjectFactory<Bean> bean
  4. 注入 ApplicationContext,用ApplicationContext.getBean(class)

1 和 2 是使用代理,3 和 4 没有使用代理

解决方法虽有不同,但理念上殊途同归,都是推迟其他 scope bean 的获取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值