Spring bean基础

264 阅读9分钟

1. 定义 Spring Bean

BeanDefinition 是 Spring Framework 中定义 Bean 的配置元信息接口,包含:

  • Bean的类名
  • Bean行为配置元素,如作用域、自动绑定的模式,生命周期回调等
  • 其他Bean引用,又可称作合作者(collaborators)或者依赖(dependencies)
  • 配置设置,比如Bean属性(Properties)

说明:bean的类名包含包名,是全限定名称,且必须是实现类。

2. BeanDefinition 元信息

属性(Property)说明
ClassBean 全类名,必须是具体类,不能用抽象类或接口
NameBean 的名称或者ID
ScopeBean 的作用域(如:singleton、prototype 等)
Constructorarguments Bean 构造器参数(用于依赖注入)
PropertiesBean 属性设置(用于依赖注入)
Autowiring modeBean 自动绑定模式(如:通过名称byName)
Lazy initialization modeBean 延迟初始化模式(延迟和非延迟)
Initialization methodBean 初始化回调方法名称
Destruction methodBean 销毁回调方法名称

BeanDefinition 构建

  • BeanDefinitionBuilder
  • AbstractBeanDefinition 以及派生类
 // 1.通过 BeanDefinitionBuilder 构建
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(User.class);
        // 通过属性设置
        beanDefinitionBuilder
                .addPropertyValue("id", 1)
                .addPropertyValue("name", "张三");
        // 获取 BeanDefinition 实例
        BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
        // BeanDefinition 并非 Bean 终态,可以自定义修改
        
        
        // 2. 通过 AbstractBeanDefinition 以及派生类
        GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
        // 设置 Bean 类型
        genericBeanDefinition.setBeanClass(User.class);
        // 通过 MutablePropertyValues 批量操作属性
        MutablePropertyValues propertyValues = new MutablePropertyValues();
//        propertyValues.addPropertyValue("id", 1);
//        propertyValues.addPropertyValue("name", "张三");
        propertyValues
                .add("id", 1)
                .add("name", "张三");
        // 通过 set MutablePropertyValues 批量操作属性
        genericBeanDefinition.setPropertyValues(propertyValues);

3. 命名 Spring Bean

3.1 Bean 的名称

每个 Bean 拥有一个或多个标识符(identifiers),这些标识符在Bean所在的容器必须是唯一的。通常,一个Bean 仅有一个标识符,如果需要额外的,可考虑使用别名(Alias)来扩充。

在基于 XML 的配置元信息中,开发人员可用 id 或者 name 属性来规定 Bean 的标识符。通常 Bean 的标识符由字母组成,允许出现特殊字符。如果要想引入 Bean 的别名的话,可在 name 属性使用半角逗号(“,”)或分号(“;”) 来间隔。

Bean 的 id 或name 属性并非必须制定,如果留空的话,容器会为 Bean 自动生成一个唯一的名称。Bean 的命名尽管没有限制,不过官方建议采用驼峰的方式,更符合 Java 的命名约定。 Bean的名称是依赖查找和依赖注入所必须的。

3.2 Bean 名称生成器(BeanNameGenerator)

由 Spring Framework 2.0.3 引入,框架內建两种实现:

  • DefaultBeanNameGenerator:默认通用BeanNameGenerator 实现
  • AnnotationBeanNameGenerator:基于注解扫描的BeanNameGenerator 实现,起始于 Spring Framework 2.5,关联的官方文档:

4. Spring Bean 的别名

Bean 别名(Alias)的价值

  • 复用现有的 BeanDefinition
  • 更具有场景化的命名方法,比如:
<alias name="myApp-dataSource" alias="subsystemA-dataSource"/>

classpath:/META-INF/bean-definitions-context.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <import resource="dependency-lookup.xml"/>
    <alias name="user" alias="xiaomage"/>
</beans>

bean别名依赖查找

// 配置 XML 配置文件
// 启动 Spring 应用上下文
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-definitions-context.xml");
// 通过别名 xiaomage-user 获取曾用名 user 的 bean
User user = beanFactory.getBean("user", User.class);
User xiaomageUser = beanFactory.getBean("xiaomage", User.class);
System.out.println("xiaomage-user 是否与 user Bean 相同:" + (user == xiaomageUser));

// 输出 
xiaomage是否与 user Bean 相同:true

5. 注册Spring Bean

5.1 BeanDefinition 注册

  • XML 配置元信息

    <bean name=”...” />
    
  • Java 注解配置元信息

    • @Bean
    • @Component
    • @Import
  • Java API 配置元信息

    • 命名方式:

      BeanDefinitionRegistry#registerBeanDefinition(String, BeanDefinition)
      
    • 非命名方式:

      BeanDefinitionReaderUtils#registerWithGeneratedName(AbstractBeanDefinition, BeanDefinitionRegistry)
      
    • 配置类方式:

      AnnotatedBeanDefinitionReader#register(Class...)
      

相关代码示例

package bean;

import ioc.User;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import static org.springframework.beans.factory.support.BeanDefinitionBuilder.genericBeanDefinition;

/**
 * 注解 BeanDefinition 示例
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
// 3. 通过 @Import 来进行导入
@Import(AnnotationBeanDefinitionDemo.Config.class)
public class AnnotationBeanDefinitionDemo {

    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类)
        applicationContext.register(AnnotationBeanDefinitionDemo.class);

        // 通过 BeanDefinition 注册 API 实现
        // 1.命名 Bean 的注册方式
        registerUserBeanDefinition(applicationContext, "mercyblitz-user");
        // 2. 非命名 Bean 的注册方法
        registerUserBeanDefinition(applicationContext);

        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 按照类型依赖查找
        System.out.println("Config 类型的所有 Beans" + applicationContext.getBeansOfType(Config.class));
        System.out.println("User 类型的所有 Beans" + applicationContext.getBeansOfType(User.class));
        // 显示地关闭 Spring 应用上下文
        applicationContext.close();
    }
    // 2. 通过 @Component 方式
    @Component // 定义当前类作为 Spring Bean(组件)
    public static class Config {

        // 1. 通过 @Bean 方式定义
        /**
         * 通过 Java 注解的方式,定义了一个 Bean
         */
        @Bean(name = {"user", "xiaomage-user"})
        public User user() {
            User user = new User();
            user.setId(1L);
            user.setName("小马哥");
            return user;
        }
    }
    public static void registerUserBeanDefinition(BeanDefinitionRegistry registry, String beanName) {
        BeanDefinitionBuilder beanDefinitionBuilder = genericBeanDefinition(User.class);
        beanDefinitionBuilder
                .addPropertyValue("id", 1L)
                .addPropertyValue("name", "小马哥");

        // 判断如果 beanName 参数存在时
        if (StringUtils.hasText(beanName)) {
            // 注册 BeanDefinition
            registry.registerBeanDefinition(beanName, beanDefinitionBuilder.getBeanDefinition());
        } else {
            // 非命名 Bean 注册方法
            BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinitionBuilder.getBeanDefinition(), registry);
        }
    }

    public static void registerUserBeanDefinition(BeanDefinitionRegistry registry) {
        registerUserBeanDefinition(registry, null);
    }
}

5.2 外部单例对象注册

  • Java API 配置元信息

    SingletonBeanRegistry#registerSingleton
    

6. 实例化 Spring Bean

Bean 实例化(Instantiation)

  • 常规方式

    • 通过构造器(配置元信息:XML、Java 注解和 Java API )
    • 通过静态工厂方法(配置元信息:XML 和 Java API )
    • 通过 Bean 工厂方法(配置元信息:XML 和 Java API )
    • 通过 FactoryBean(配置元信息:XML、Java 注解和 Java API )

通过静态方法创建bean代码示例

<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
    <bean id="user-by-static-method" class="ioc.User"
          factory-method="createUser"/>

</beans>
package bean;

import ioc.User;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * Bean 实例化示例
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public class BeanInstantiationDemo {

    public static void main(String[] args) {
        // 配置 XML 配置文件
        // 启动 Spring 应用上下文
        BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath:/META-INF/bean-create-context.xml");
        User user = beanFactory.getBean("user-by-static-method", User.class);
        User userByStaticMethod = beanFactory.getBean("user-by-static-method", User.class);
        System.out.println(userByStaticMethod);
    }
}
// 输出 User{id=1, name='xiaomage'}
// User POJO类中添加静态方法
public static User createUser() {
    User user = new User();
    user.setId(1L);
    user.setName("xiaomage");
    return user;
}

通过实例方法实例化

package bean.factory;

import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

/**
 * 默认 {@link UserFactory} 实现
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public class DefaultUserFactory implements UserFactory, InitializingBean, DisposableBean {

    // 1. 基于 @PostConstruct 注解
    @PostConstruct
    public void init() {
        System.out.println("@PostConstruct : UserFactory 初始化中...");
    }

    public void initUserFactory() {
        System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中...");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中...");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("@PreDestroy : UserFactory 销毁中...");
    }

    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean#destroy() : UserFactory 销毁中...");
    }

    public void doDestroy() {
        System.out.println("自定义销毁方法 doDestroy() : UserFactory 销毁中...");
    }

    @Override
    public void finalize() throws Throwable {
        System.out.println("当前 DefaultUserFactory 对象正在被垃圾回收...");
    }
}
package bean.factory;


import ioc.User;

/**
 * {@link User} 工厂类
 *
 * @author <a href="mailto:mercyblitz@gmail.com">Mercy</a>
 * @since
 */
public interface UserFactory {

    default User createUser() {
        return User.createUser();
    }
}
<!-- 通过实例方法实例化 -->
<bean id="user-by-instance-method" factory-bean="userFactory" factory-method="createUser"/>
<bean id="userFactory" class="bean.factory.DefaultUserFactory"/>

User userByInstanceMethod = beanFactory.getBean("user-by-instance-method", User.class);
System.out.println(userByInstanceMethod);
  • 特殊方式

    • 通过 ServiceLoaderFactoryBean(配置元信息:XML、Java 注解和Java API )
    • 通过 AutowireCapableBeanFactory#createBean(java.lang.Class, int, boolean)
    • 通过 BeanDefinitionRegistry#registerBeanDefinition(String,BeanDefinition)

通过ServiceLoader 和 AutowireCapableBeanFactory 实例化的例子

package bean;

import bean.factory.DefaultUserFactory;
import bean.factory.UserFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.Iterator;
import java.util.ServiceLoader;
import static java.util.ServiceLoader.load;
/*<?xml version="1.0" encoding="UTF-8"?>
<beans
        xmlns="http://www.springframework.org/schema/beans"
                xmlns:context="http://www.springframework.org/schema/context"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                xsi:schemaLocation="http://www.springframework.org/schema/beans
                https://www.springframework.org/schema/beans/spring-beans.xsd
                http://www.springframework.org/schema/context
                https://www.springframework.org/schema/context/spring-context.xsd">

<bean id="userFactoryServiceLoader" class="org.springframework.beans.factory.serviceloader.ServiceLoaderFactoryBean">
<property name="serviceType" value="bean.factory.UserFactory"/>
</bean>
</beans>*/
/**
 * 特殊的 Bean 实例化示例
 * @since
 */
public class SpecialBeanInstantiationDemo {

    public static void main(String[] args) {
        // 配置 XML 配置文件
        // 启动 Spring 应用上下文
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:/META-INF/special-bean-instantiation-context.xml");
        // 通过 ApplicationContext 获取 AutowireCapableBeanFactory
        AutowireCapableBeanFactory beanFactory = applicationContext.getAutowireCapableBeanFactory();

        ServiceLoader<UserFactory> serviceLoader = beanFactory.getBean("userFactoryServiceLoader", ServiceLoader.class);
        displayServiceLoader(serviceLoader);

        // 创建 UserFactory 对象,通过 AutowireCapableBeanFactory
        UserFactory userFactory = beanFactory.createBean(DefaultUserFactory.class);
        System.out.println(userFactory.createUser());

    }

    public static void demoServiceLoader() {
        ServiceLoader<UserFactory> serviceLoader = load(UserFactory.class, Thread.currentThread().getContextClassLoader());
        displayServiceLoader(serviceLoader);
    }

    private static void displayServiceLoader(ServiceLoader<UserFactory> serviceLoader) {
        Iterator<UserFactory> iterator = serviceLoader.iterator();
        while (iterator.hasNext()) {
            UserFactory userFactory = iterator.next();
            System.out.println(userFactory.createUser());
        }
    }
}

7. 初始化 Spring Bean

Bean 初始化(Initialization)

  • @PostConstruct 标注方法

  • 实现InitializingBean 接口的afterPropertiesSet() 方法

  • 自定义初始化方法

    • XML 配置:<bean init-method=”init” ... />
    • Java 注解:@Bean(initMethod=”init”)
    • Java API:AbstractBeanDefinition#setInitMethodName(String)

思考:假设以上三种方式均在同一 Bean 中定义,那么这些方法的执行顺序是怎样?

package bean.initialization;

import ioc.User;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
import javax.annotation.PostConstruct;

/**
 * Bean 初始化 Demo
 * @since
 */
@Configuration // Configuration Class
public class BeanInitializationDemo {

    public  interface UserFactory {
        default User createUser() {
            return User.createUser();
        }
    }
    public static class DefaultUserFactory implements UserFactory, InitializingBean {
        // 1. 基于 @PostConstruct 注解
        @PostConstruct
        public void init() {
            System.out.println("@PostConstruct : UserFactory 初始化中...");
        }
        @Override
        public void afterPropertiesSet() throws Exception {
            System.out.println("InitializingBean#afterPropertiesSet() : UserFactory 初始化中...");
        }
        public void initUserFactory() {
            System.out.println("自定义初始化方法 initUserFactory() : UserFactory 初始化中...");
        }
    }


    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类)
        applicationContext.register(BeanInitializationDemo.class);
        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 非延迟初始化在 Spring 应用上下文启动完成后,被初始化
        System.out.println("Spring 应用上下文已启动...");
        // 依赖查找 UserFactory
        UserFactory userFactory = applicationContext.getBean(UserFactory.class);
        //System.out.println(userFactory);
        System.out.println("Spring 应用上下文准备关闭...");
        // 关闭 Spring 应用上下文
        applicationContext.close();
        System.out.println("Spring 应用上下文已关闭...");
    }

    @Bean(initMethod = "initUserFactory")
    @Lazy(value = false)
    public DefaultUserFactory userFactory() {
        return new DefaultUserFactory();
    }
}

执行顺序

@PostConstruct : UserFactory 初始化中...
InitializingBean#afterPropertiesSet() : UserFactory 初始化中...
自定义初始化方法 initUserFactory() : UserFactory 初始化中...

8. 延迟初始化 Spring Bean

Bean 延迟初始化(Lazy Initialization)

  • XML 配置:<bean lazy-init=”true” ... />
  • Java 注解:@Lazy(true)

思考:当某个 Bean 定义为延迟初始化,那么,Spring 容器返回的对象与非延迟的对象存在怎样的差异?

非延迟初始化,初始化方法在spring上下文之前执行。上面代码

@Bean(initMethod = "initUserFactory")
@Lazy(value = false)
public DefaultUserFactory userFactory() {
    return new DefaultUserFactory();
}
@PostConstruct : UserFactory 初始化中...
InitializingBean#afterPropertiesSet() : UserFactory 初始化中...
自定义初始化方法 initUserFactory() : UserFactory 初始化中...
Spring 应用上下文已启动...

延迟初始化,初始化方法在spring上下文之后执行

@Bean(initMethod = "initUserFactory")
@Lazy
public DefaultUserFactory userFactory() {
    return new DefaultUserFactory();
}
Spring 应用上下文已启动...
@PostConstruct : UserFactory 初始化中...
InitializingBean#afterPropertiesSet() : UserFactory 初始化中...
自定义初始化方法 initUserFactory() : UserFactory 初始化中...

9. 销毁 Spring Bean

Bean 销毁(Destroy)

  • @PreDestroy 标注方法

  • 实现 DisposableBean 接口的 destroy() 方法

  • 自定义销毁方法

    • XML 配置:<bean destroy=”destroy” ... />
    • Java 注解:@Bean(destroy=”destroy”)
    • Java API:AbstractBeanDefinition#setDestroyMethodName(String)

思考:假设以上三种方式均在同一Bean 中定义,那么这些方法的执行顺序是怎样?

package bean.initialization;

import ioc.User;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Lazy;
import javax.annotation.PreDestroy;
/**
 * 延迟初始化例子
 */
public class BeanDestroyInitializationDemo {
    public  interface UserFactory {
        default User createUser() {
            return User.createUser();
        }
    }
    public static class DefaultUserFactory implements UserFactory, DisposableBean {
        // bean 销毁的方法
        // 1. 基于 @PreDestroy 注解
        @PreDestroy
        public void preDestroy() {
            System.out.println("@PreDestroy : UserFactory 销毁中...");
        }
        // 2. DisposableBean#destroy()
        @Override
        public void destroy() throws Exception {
            System.out.println("DisposableBean#destroy() : UserFactory 销毁中...");
        }
        // 3. 自定义销毁方法
        public void doDestroy() throws Exception {
            System.out.println("DisposableBean#destroy() : UserFactory 销毁中...");
        }
    }


    public static void main(String[] args) {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类)
        applicationContext.register(BeanDestroyInitializationDemo.class);
        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 非延迟初始化在 Spring 应用上下文启动完成后,被初始化
        System.out.println("Spring 应用上下文已启动...");
        // 依赖查找 UserFactory
        UserFactory userFactory = applicationContext.getBean(UserFactory.class);
        System.out.println(userFactory);
        System.out.println("Spring 应用上下文准备关闭...");
        // 关闭 Spring 应用上下文
        applicationContext.close();
        System.out.println("Spring 应用上下文已关闭...");
    }

    @Bean(destroyMethod = "doDestroy")
    public DefaultUserFactory userFactory() {
        return new DefaultUserFactory();
    }
}

从输出可以看出是 applicationContext.close(); 触发了bean的销毁动作

Spring 应用上下文准备关闭...
@PreDestroy : UserFactory 销毁中...
DisposableBean#destroy() : UserFactory 销毁中...
DisposableBean#destroy() : UserFactory 销毁中...
Spring 应用上下文已关闭...

10. 垃圾回收 Spring Bean

Bean 垃圾回收(GC)

  • 关闭 Spring 容器(应用上下文)
  • 执行 GC
  • Spring Bean 覆盖的 finalize() 方法被回调

垃圾回收的例子

package bean.initialization;

import ioc.User;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;

import javax.annotation.PreDestroy;

/**
 *  bean 垃圾回收
 */
public class BeanGCDemo {
    public  interface UserFactory {
        default User createUser() {
            return User.createUser();
        }
    }
    public static class DefaultUserFactory implements UserFactory {
        @Override
        public void finalize() throws Throwable {
            System.out.println("当前 DefaultUserFactory 对象正在被垃圾回收...");
        }
    }


    public static void main(String[] args) throws Exception{
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 注册 Configuration Class(配置类)
        applicationContext.register(BeanGCDemo.class);
        // 启动 Spring 应用上下文
        applicationContext.refresh();
        // 关闭 Spring 应用上下文
        applicationContext.close();
        Thread.sleep(5000);  
        System.gc();
        Thread.sleep(5000);
    }
    @Bean()
    public DefaultUserFactory userFactory() {
        return new DefaultUserFactory();
    }
}
// 输出
当前 DefaultUserFactory 对象正在被垃圾回收...

11. 面试题精选

问题1:如何注册一个 Spring Bean?

答:通过 BeanDefinition 和外部单体对象来注册。

package bean.register;

import ioc.User;
import org.springframework.beans.factory.config.SingletonBeanRegistry;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

/**
 * 外部单体 Bean 注册实例
 * @since
 */
public class SingletonBeanRegistrationDemo {

    public  interface UserFactory {
        default User createUser() {
            return User.createUser();
        }
    }
    public static class DefaultUserFactory  implements  UserFactory{
        @Override
        public void finalize() throws Throwable {
            System.out.println("当前 DefaultUserFactory 对象正在被垃圾回收...");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        // 创建 BeanFactory 容器
        AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext();
        // 创建一个外部 UserFactory 对象
        UserFactory userFactory = new DefaultUserFactory();
        SingletonBeanRegistry singletonBeanRegistry = applicationContext.getBeanFactory();
        // 注册外部单例对象
        singletonBeanRegistry.registerSingleton("userFactory", userFactory);
        // 启动 Spring 应用上下文
        applicationContext.refresh();

        // 通过依赖查找的方式来获取 UserFactory
        UserFactory userFactoryByLookup = applicationContext.getBean("userFactory", UserFactory.class);
        System.out.println("userFactory  == userFactoryByLookup : " + (userFactory == userFactoryByLookup));

        // 关闭 Spring 应用上下文
        applicationContext.close();
    }

}
// 输出 userFactory  == userFactoryByLookup : true

问题2:什么是 Spring BeanDefinition?

答:回顾 "定义 Spring Bean" 和 "BeanDefinition 元信息”。

问题3:Spring 容器是怎样管理注册 Bean?

答:答案将在后续专题章节详细讨论,如:IoC 配置元信息读取和解析、依赖查找和注入以及 Bean 生命周期等。


每天用心记录一点点。内容也许不重要,但习惯很重要!