Phân tích phương thức finishBeanFactoryInitialization trong Spring

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ác ObjectFactory dù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.

Thẻ: Spring BeanFactory FactoryBean DependencyInjection AOP

Đăng vào ngày 27 tháng 6 lúc 23:23