spring初始化bean時執行某些方法完成特定的初始化操作


在項目中經常會在容器啟動時,完成特定的初始化操作,如資源文件的加載等。

一 實現的方式有三種:

1.使用@PostConstruct注解,該注解作用於void方法上

2.在配置文件中配置init-method方法

<bean id="student" class="com.demo.spring.entity.Student" init-method="init2">
        <property name="name" value="景甜"></property>
        <property name="age" value="28"></property>
        <property name="school" ref="school"></property>
</bean> 

3.將類實現InitializingBean接口

package com.demo.spring.entity;

import javax.annotation.PostConstruct;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;

/**
 * @author chenyk
 * @date 2018年5月8日
 */
@Component("student")
public class Student implements InitializingBean{
    private String name;
    private int age;
    
    private School school;
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public School getSchool() {
        return school;
    }
    public void setSchool(School school) {
        this.school = school;
    }
    
    //1.使用postconstrtct注解
    @PostConstruct
    public void init(){
        System.out.println("執行 init方法");
    }
     
    //2.在xml配置文件中配置init-method方法
    public void init2(){
        System.out.println("執行init2方法 ");
    }
    
    //3.實現InitializingBean接口
    public void afterPropertiesSet() throws Exception {
        System.out.println("執行init3方法");
    }
    
}

執行結果:

執行 init方法
2018-06-11 10:09:16,195 DEBUG [AbstractAutowireCapableBeanFactory.java:1671] : Invoking afterPropertiesSet() on bean with name 'student'
執行init3方法
2018-06-11 10:09:36,459 DEBUG [AbstractAutowireCapableBeanFactory.java:1731] : Invoking init method 'init2' on bean with name 'student'
執行init2 方法

二 實現原理:

由以上執行結果可知:先執行@PostConstruct注解的方法,然后是實現了InitializingBean接口的afterPropertiesSet方法,最后執行在配置文件中配置的init-method方法。至於為什么是這個順序,可以看源碼:

在 AbstractAutowireCapableBeanFactory 類中

    protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
        if (System.getSecurityManager() != null) {
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                @Override
                public Object run() {
                    invokeAwareMethods(beanName, bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        else {
            invokeAwareMethods(beanName, bean);
        }

        Object wrappedBean = bean;
        if (mbd == null || !mbd.isSynthetic()) {
            wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
        }

        try {
       //調用初始化方法 invokeInitMethods(beanName, wrappedBean, mbd); }
catch (Throwable ex) { throw new BeanCreationException( (mbd != null ? mbd.getResourceDescription() : null), beanName, "Invocation of init method failed", ex); } if (mbd == null || !mbd.isSynthetic()) { wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName); } return wrappedBean; }

然后進入到 invokeInitMethods 方法中 

    protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {

        boolean isInitializingBean = (bean instanceof InitializingBean);
        if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
            if (logger.isDebugEnabled()) {
                logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
            }
            if (System.getSecurityManager() != null) {
                try {
                    AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                        @Override
                        public Object run() throws Exception {
                            ((InitializingBean) bean).afterPropertiesSet();
                            return null;
                        }
                    }, getAccessControlContext());
                }
                catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
            }
            else {
          //直接調用 InitializingBean 接口中的 afterPropertiesSet 方法 ((InitializingBean) bean).afterPropertiesSet(); } }
if (mbd != null) { String initMethodName = mbd.getInitMethodName(); if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) && !mbd.isExternallyManagedInitMethod(initMethodName)) {
          //進入該方法可知通過反射的方式調用init-method方法 invokeCustomInitMethod(beanName, bean, mbd); } } }

所以,初始化方法的執行順序 afterPropertiesSet() > init-method()

博客園的第一篇文章。感覺博客園很干凈,文章排版特別是插入代碼格式看起來很舒服。就不吐槽csdn了。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM