1. 定义 Spring Bean
BeanDefinition 是 Spring Framework 中定义 Bean 的配置元信息接口,包含:
- Bean的类名
- Bean行为配置元素,如作用域、自动绑定的模式,生命周期回调等
- 其他Bean引用,又可称作合作者(collaborators)或者依赖(dependencies)
- 配置设置,比如Bean属性(Properties)
说明:bean的类名包含包名,是全限定名称,且必须是实现类。
2. BeanDefinition 元信息
| 属性(Property) | 说明 |
|---|---|
| Class | Bean 全类名,必须是具体类,不能用抽象类或接口 |
| Name | Bean 的名称或者ID |
| Scope | Bean 的作用域(如:singleton、prototype 等) |
| Constructor | arguments Bean 构造器参数(用于依赖注入) |
| Properties | Bean 属性设置(用于依赖注入) |
| Autowiring mode | Bean 自动绑定模式(如:通过名称byName) |
| Lazy initialization mode | Bean 延迟初始化模式(延迟和非延迟) |
| Initialization method | Bean 初始化回调方法名称 |
| Destruction method | Bean 销毁回调方法名称 |
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 生命周期等。
每天用心记录一点点。内容也许不重要,但习惯很重要!