spring4 IOC的init-method源码

2020-09-03  本文已影响0人  sunpy

init-method的例子

public class User {
    
    public User() {
        System.out.println("User实例已经创建!");
    }

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
    public void initUser() {
        System.out.println("Bean初始化执行的方法");
    }
}
<beans:bean id="user" class="cn.spy.spring.source.code.User" init-method="initUser">
        <beans:property name="name" value="zhangsan"></beans:property>
</beans:bean>

public static void main(String[] args) {
     ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
}

结果:



为什么没有获取bean,就已经加载bean了?
由于在spring ioc初始化阶段,实例化非懒加载方式的一些单例。而这些bean被实例化之后,其init-method字段配置的方法名称作为bean的属性(注意:记住的是方法名称),被检查到如果存在,则回调该方法,回调方式只是通过方法名称进行反射而已。

读取bean配置的init-method标签

读取init-method标签是伴随着读取bean标签是一样的,只是作为bean标签的子节点而已。使用Dom技术读取XML文档(ResouceLoader读取),得到Resouce对象,将Resouce对象转化为Document对象。获取Document中的Element元素对象都封装为BeanDefinition,将BeanDefinition添加到BeanDefinitionMap集合映射中,最终添加到Spring IOC的管理容器BeanFactory(具体是DefaultListBeanFactory)。


处理给定的Bean标签的方法processBeanDefinition

执行init-method配置的方法

执行init-method配置的方法已经在beanFactory的BeanDefinitionMap中。



执行init-method配置的方法的流程:


4.png

从refresh方法开始,finishBeanFactoryInitialization方法; 预先加载bean,从BeanDefinitionMap中加载bean名称集合,遍历集合,调用getBean方法先生成bean,最后委派到doCreateBean方法:createBeanInstance创建bean实例,populateBean方法为实例属性填充,之后初始化方法initializeBean:检查bean是否注册了init-method,如果注册了,那么执行回调,调用init-method注册的方法,只是采用反射的方式来执行该方法。

protected void invokeInitMethods(String beanName, final Object bean, RootBeanDefinition mbd)
            throws Throwable {
    // 判断传入的bean是否为InitializingBean类型的实例
    boolean isInitializingBean = (bean instanceof InitializingBean);
    if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
        if (logger.isDebugEnabled()) {
            logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
        }
        // 传入的bean如果实现了InitializingBean接口
        // 那么可以执行afterPropertiesSet方法
        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) bean).afterPropertiesSet();
        }
    }

    if (mbd != null) {
        // 获取init-method指定方法的名称
        String initMethodName = mbd.getInitMethodName();
        if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
                !mbd.isExternallyManagedInitMethod(initMethodName)) {
            // 反射方式执行该方法
            invokeCustomInitMethod(beanName, bean, mbd);
        }
    }
}

// 使用jdk反射方式调用bean指定的init-method方法
protected void invokeCustomInitMethod(String beanName, final Object bean, RootBeanDefinition mbd) throws Throwable {
    String initMethodName = mbd.getInitMethodName();
    final Method initMethod = (mbd.isNonPublicAccessAllowed() ?
            BeanUtils.findMethod(bean.getClass(), initMethodName) :
            ClassUtils.getMethodIfAvailable(bean.getClass(), initMethodName));
    if (initMethod == null) {
        if (mbd.isEnforceInitMethod()) {
            throw new BeanDefinitionValidationException("Couldn't find an init method named '" +
                    initMethodName + "' on bean with name '" + beanName + "'");
        }
        else {
            if (logger.isDebugEnabled()) {
                logger.debug("No default init method named '" + initMethodName +
                        "' found on bean with name '" + beanName + "'");
            }
            // Ignore non-existent default lifecycle methods.
            return;
        }
    }

    if (logger.isDebugEnabled()) {
        logger.debug("Invoking init method  '" + initMethodName + "' on bean with name '" + beanName + "'");
    }

    if (System.getSecurityManager() != null) {
        AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
            @Override
            public Object run() throws Exception {
                ReflectionUtils.makeAccessible(initMethod);
                return null;
            }
        });
        try {
            AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
                @Override
                public Object run() throws Exception {
                    initMethod.invoke(bean);
                    return null;
                }
            }, getAccessControlContext());
        }
        catch (PrivilegedActionException pae) {
            InvocationTargetException ex = (InvocationTargetException) pae.getException();
            throw ex.getTargetException();
        }
    }
    else {
        try {
            ReflectionUtils.makeAccessible(initMethod);
            initMethod.invoke(bean);
        }
        catch (InvocationTargetException ex) {
            throw ex.getTargetException();
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读