欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-10-20 10:36:54
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了。

上一篇: JUC——线程池

下一篇: 听力不太好