系統啓動時,直接加載類和方法

一.在web.xml中配置spring監聽器

<!-- Spring容器啓動監聽器配置 -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>com.test.util.LoadSystemArgsListener</listener-class>
</listener>

缺點:

mvc-dispatcher-servlet.xml配置需要拆分成spring-config.xml和mvc-config.xml,否則系統報錯

因爲<bean/>放到mvc裏了,所以在spring啓動的時候找不到對應的bean報錯
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'authController': Injection of resource dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userService': Error setting property values; nested exception is org.springframework.beans.PropertyBatchUpdateException; nested PropertyAccessExceptions (1) are:
PropertyAccessException 1: org.springframework.beans.MethodInvocationException: Property 'alias' threw exception; 

二.實現InitializingBean接口

1.重寫方法afterPropertiesSet()即可

2.增加初始方法配置bean

<bean id="testInitializingBean" class="com.TestInitializingBean" init-method="testInit"></bean>

類AbstractAutowiredCapableBeanFactory的invokeInitMethods()源碼如下:

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
    //判斷該bean是否實現了實現了InitializingBean接口,如果實現了InitializingBean接口,則只掉調用bean的afterPropertiesSet方法
    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>() {
                    public Object run() throws Exception {
                        //直接調用afterPropertiesSet
                        ((InitializingBean) bean).afterPropertiesSet();
                        return null;
                    }
                },getAccessControlContext());
            } catch (PrivilegedActionException pae) {
                throw pae.getException();
            }
        }                
        else {
            //直接調用afterPropertiesSet
            ((InitializingBean) bean).afterPropertiesSet();
        }
    }
    if (mbd != null) {
        String initMethodName = mbd.getInitMethodName();
        //判斷是否指定了init-method方法,如果指定了init-method方法,則再調用制定的init-method
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            //進一步查看該方法的源碼,可以發現init-method方法中指定的方法是通過反射實現
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

總結:
1、實現InitializingBean接口是直接調用afterPropertiesSet方法,比通過反射調用init-method指定的方法效率要高一點,但是init-method方式消除了對spring的依賴。

2、如果調用afterPropertiesSet方法時出錯,則不調用init-method指定的方法。

三個方法的順序:

1.ContextLoaderListener監聽器

2. afterPropertieSet()方法,

3. init-method中指定的方法

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章