Phiên bản mã nguồn Spring được phân tích: 5.0.5
Tổng quan
Phương thức này chịu trách nhiệm khởi tạo tất cả các bean singleton không lazy-load còn lại. Các bean nội bộ, bean triển khai BeanFactoryPostProcessor, hoặc bean triển khai BeanPostProcessor sẽ được xử lý riêng. Toàn bộ các bean singleton không lazy-load khác đều được khởi tạo tại đây, đồng thời các BeanPostProcessor cũng được kích hoạt trong quá trình này.
Chi tiết thực thi
Bắt đầu từ phương thức refresh() trong AbstractApplicationContext, ta tìm đến lời gọi finishBeanFactoryInitialization(beanFactory):
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory factory) {
// 1. Thiết lập dịch vụ chuyển đổi nếu tồn tại
if (factory.containsBean("conversionService") &&
factory.isTypeMatch("conversionService", ConversionService.class)) {
factory.setConversionService(factory.getBean("conversionService", ConversionService.class));
}
// 2. Đăng ký bộ phân giải giá trị nhúng mặc định nếu chưa có
if (!factory.hasEmbeddedValueResolver()) {
factory.addEmbeddedValueResolver(value -> getEnvironment().resolvePlaceholders(value));
}
// 3. Khởi tạo trước các bean hỗ trợ LoadTimeWeaver
String[] loaderAwareBeans = factory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);
for (String name : loaderAwareBeans) {
getBean(name);
}
// 4. Ngừng sử dụng ClassLoader tạm và đóng băng cấu hình
factory.setTempClassLoader(null);
factory.freezeConfiguration();
// 5. Khởi tạo tất cả singleton không lazy-load còn lại
factory.preInstantiateSingletons();
}
Tiếp tục theo dõi vào DefaultListableBeanFactory#preInstantiateSingletons:
public void preInstantiateSingletons() throws BeansException {
List<String> names = new ArrayList<>(this.beanDefinitionNames);
for (String id : names) {
RootBeanDefinition def = getMergedLocalBeanDefinition(id);
if (!def.isAbstract() && def.isSingleton() && !def.isLazyInit()) {
if (isFactoryBean(id)) {
Object candidate = getBean("&" + id);
if (candidate instanceof FactoryBean) {
FactoryBean<?> fb = (FactoryBean<?>) candidate;
boolean shouldInitEagerly = (fb instanceof SmartFactoryBean smart && smart.isEagerInit());
if (shouldInitEagerly) {
getBean(id);
}
}
} else {
getBean(id); // Khởi tạo bean thông thường
}
}
}
}
Khác biệt giữa FactoryBean và Bean thông thường
Spring thường khởi tạo bean thông qua reflection dựa trên thuộc tính class. Tuy nhiên, FactoryBean là một loại bean đặc biệt — nó đóng vai trò như một nhà máy, tự quyết định cách tạo ra đối tượng thông qua phương thức getObject(). Nhiều thư viện bên thứ ba tận dụng cơ chế này để mở rộng Spring.
Các bộ đệm quan trọng
mergedBeanDefinitions: Lưu trữ định nghĩa bean đã được hợp nhất.beanDefinitionMap: Ánh xạ tên bean → định nghĩa bean.singletonObjects: Lưu trữ các bean singleton đã hoàn chỉnh.earlySingletonObjects: Lưu trữ phiên bản sơ khai của bean (chưa inject thuộc tính).singletonFactories: Lưu trữ cácObjectFactorydùng để tạo bean.singletonsCurrentlyInCreation: Tập hợp các bean đang trong quá trình khởi tạo.
Quá trình lấy bean — doGetBean
protected <T> T doGetBean(String identifier, @Nullable Class<T> type,
@Nullable Object[] params, boolean checkOnly) throws BeansException {
String actualName = transformedBeanName(identifier);
Object instance;
// Kiểm tra cache trước
Object cached = getSingleton(actualName);
if (cached != null && params == null) {
instance = getObjectForBeanInstance(cached, identifier, actualName, null);
} else {
// Kiểm tra vòng lặp với prototype
if (isPrototypeCurrentlyInCreation(actualName)) {
throw new BeanCurrentlyInCreationException(actualName);
}
// Kiểm tra parent factory nếu cần
BeanFactory parent = getParentBeanFactory();
if (parent != null && !containsBeanDefinition(actualName)) {
String lookupName = originalBeanName(identifier);
return parent.getBean(lookupName, type);
}
if (!checkOnly) markBeanAsCreated(actualName);
try {
RootBeanDefinition beanDef = getMergedLocalBeanDefinition(actualName);
String[] dependencies = beanDef.getDependsOn();
if (dependencies != null) {
for (String dep : dependencies) {
registerDependentBean(dep, actualName);
getBean(dep); // Đảm bảo khởi tạo trước
}
}
if (beanDef.isSingleton()) {
instance = getSingleton(actualName, () -> createBean(actualName, beanDef, params));
instance = getObjectForBeanInstance(instance, identifier, actualName, beanDef);
}
} catch (BeansException ex) {
cleanupAfterBeanCreationFailure(actualName);
throw ex;
}
}
return (T) instance;
}
Tạo singleton — getSingleton
public Object getSingleton(String name, ObjectFactory<?> factory) {
synchronized (this.singletonObjects) {
Object existing = this.singletonObjects.get(name);
if (existing == null) {
beforeSingletonCreation(name); // Ghi nhận bean đang tạo
try {
existing = factory.getObject(); // Gọi createBean
addSingleton(name, existing); // Thêm vào cache sau khi tạo xong
} finally {
afterSingletonCreation(name); // Xóa khỏi danh sách đang tạo
}
}
return existing;
}
}
Quy trình tạo bean — createBean
protected Object createBean(String name, RootBeanDefinition def, @Nullable Object[] args) {
def.prepareMethodOverrides(); // Chuẩn bị ghi đè phương thức
// Cho phép BeanPostProcessor can thiệp trước khi khởi tạo
Object shortcut = resolveBeforeInstantiation(name, def);
if (shortcut != null) return shortcut;
// Tạo bean thật sự
return doCreateBean(name, def, args);
}
Thực thi tạo bean — doCreateBean
protected Object doCreateBean(String name, RootBeanDefinition def, @Nullable Object[] args) {
BeanWrapper wrapper = createBeanInstance(name, def, args);
Object rawBean = wrapper.getWrappedInstance();
// Xử lý tham chiếu vòng: đăng ký ObjectFactory sớm
boolean exposeEarly = (def.isSingleton() && this.allowCircularReferences && isSingletonCurrentlyInCreation(name));
if (exposeEarly) {
addSingletonFactory(name, () -> getEarlyBeanReference(name, def, rawBean));
}
Object processedBean = rawBean;
try {
populateBean(name, def, wrapper); // Inject thuộc tính
processedBean = initializeBean(name, processedBean, def); // Gọi BeanPostProcessor, AOP...
} catch (Throwable ex) {
// Xử lý ngoại lệ...
}
return processedBean;
}
Quá trình createBeanInstance lựa chọn chiến lược khởi tạo phù hợp: sử dụng constructor, factory method, hoặc khởi tạo mặc định — tùy thuộc vào cách cấu hình của lập trình viên.