Spring IOC容器启动和Bean的生命周期

IOC容器启动流程图解

在这里插入图片描述


IOC容器启动源码解读

@Configuration
@ComponentScan("cn.edu.guet.pojo")
public class MyConfig {
    @Bean
    public Admin registerAdmin() {
        return new Admin();
    }
}
// 启动IOC容器,断点调试进去,进到构造方法
ApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);

单例默认情况下是在容器被加载的时候就会初始化

this()构造阶段

  • AnnotationConfigApplicationContext的构造方法
// 调试再进入this(),也就是调用无参构造
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    this.register(annotatedClasses);
    this.refresh();
}
// 由于AnnotationConfigApplicationContext继承了GenericApplicationContext,所以会先调用GenericApplicationContext的无参构造
public class AnnotationConfigApplicationContext extends GenericApplicationContext implements AnnotationConfigRegistry {}
  • 先调用父类的GenericApplicationContext的无参构造
public GenericApplicationContext() {
    this.customClassLoader = false;
    this.refreshed = new AtomicBoolean();
    // 完成DefaultListableBeanFactory的创建
    this.beanFactory = new DefaultListableBeanFactory();
}
  • 再走子类自己的构造方法
/* this()后进入无参构造,
创建一个AnnotatedBeanDefinitionReader对象并注入到当前AnnotationConfigApplicationContext的成员属性中
*/
public AnnotationConfigApplicationContext() {
	// 基于注解方式读取到IOC容器中
    this.reader = new AnnotatedBeanDefinitionReader(this);
    // 基于扫包的形式读取到IOC容器,比如Mapper层可以扫包而不加@Mapper
    this.scanner = new ClassPathBeanDefinitionScanner(this);
}

this.register()注册阶段

只注入配置启动类

// 执行完this()后,执行this.register(annotatedClasses)
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    this.register(annotatedClasses);
    this.refresh();
}
// 其实该方法调用的是reader(AnnotatedBeanDefinitionReader)的register
public void register(Class<?>... annotatedClasses) {
    Assert.notEmpty(annotatedClasses, "At least one annotated class must be specified");
    this.reader.register(annotatedClasses);
}
// AnnotatedBeanDefinitionReader的register主要是下面两行代码
// 封装扫描到的启动配置信息
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
// 使用BeanDefinitionHolder包装Beanname,原来的beanDefinition并没有beanname这个属性
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
// 将封装好的definitionHolder对象进行注册
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
  • 包装beanDefinition和beanName封装到BeanDefinitionHolder对象中
// 把beanDefinition和beanName封装到BeanDefinitionHolder对象中
public BeanDefinitionHolder(BeanDefinition beanDefinition, String beanName, String[] aliases) {
    Assert.notNull(beanDefinition, "BeanDefinition must not be null");
    Assert.notNull(beanName, "Bean name must not be null");
    this.beanDefinition = beanDefinition;
    this.beanName = beanName;
    this.aliases = aliases;
}
  • BeanDefinitionReaderUtils.registerBeanDefinition()
public static void registerBeanDefinition(BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) throws BeanDefinitionStoreException {
    String beanName = definitionHolder.getBeanName();
    // 此时registry引用指向的DefaultListableBeanFactory
    registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
}

其实就是调用的是BeanDefinitionRegistry的registerBeanDefinition()方法

// DefaultListableBeanFactory的成员属性,保证了线程安全
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap(256);
// 往容器里面放入beanName和beanDefinition
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws BeanDefinitionStoreException {
	// 最后注册的还是beanDefinition
	this.beanDefinitionMap.put(beanName, beanDefinition);
}
  • BeanFactoryPostProcessor

在完成了beanDefinitionMap的装载后,其实还可以通过实现BeanFactoryPostProcessor接口,去拿到beanDefinition,然后去修改里面的东西,如class,lazy等bean描述属性,这也是一个后置处理器(在实例化之前,BeanPostProcessor是实例化之后)


this.refresh()阶段

完成bean的创建和初始化

// 执行完this.register(annotatedClasses)后,执行this.refresh();
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
    this();
    this.register(annotatedClasses);
    this.refresh();
}

Spring生命周期图解

在这里插入图片描述

  • ApplicationContextAware接口(其中一个Aware接口)

可以拿到ApplicationContext上下文对象,Aware就是"意识到",实现接口后方法都带有Set前缀,也就是说如果你实现了ApplicationContextAware接口,它就会在bean的生命周期中给你注入ApplicationContext,你可以通过自己直接拿到该上下文对象。通过我们通过一个工具类实现该接口,然后拿到该上下文对象,进而赋值给一个静态变量,通过该工具类提供一些静态泛型方法去方便外部手动获取bean对象

  • InitializingBean接口

可以自定义初始化逻辑

  • BeanPostProess接口(后置处理器)

可以对bean的初始化进行增强

  • DisposableBean

可以定义销毁逻辑


Spring Bean生命周期源码解读

紧接上面的refresh()方法,就是生命周期的创建和初始化过程,而销毁过程则交给IOC 容器关闭时同时对bean进行销毁

  • refresh()
public void refresh() throws BeansException, IllegalStateException {
	// Prepare this context for refreshing.
	prepareRefresh();

	// Tell the subclass to refresh the internal bean factory.
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

	// Prepare the bean factory for use in this context.
	prepareBeanFactory(beanFactory);

	try {
		// Allows post-processing of the bean factory in context subclasses.
		postProcessBeanFactory(beanFactory);

		// Invoke factory processors registered as beans in the context.
		invokeBeanFactoryPostProcessors(beanFactory);

		// Register bean processors that intercept bean creation.
		registerBeanPostProcessors(beanFactory);

		// 国际化操作
		initMessageSource();

		// Initialize event multicaster for this context.
		initApplicationEventMulticaster();

		// Initialize other special beans in specific context subclasses.
		onRefresh();

		// Check for listener beans and register them.
		registerListeners();

		// 完成实例化所有的bean单例对象
		finishBeanFactoryInitialization(beanFactory);

		// Last step: publish corresponding event.
		finishRefresh();
		}
}
  • finishBeanFactoryInitialization(beanFactory)
protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {
    beanFactory.setTempClassLoader((ClassLoader)null);
    beanFactory.freezeConfiguration();
   	// 初始化所有的单例对象
    beanFactory.preInstantiateSingletons();
}
  • preInstantiateSingletons()
@Override
public void preInstantiateSingletons() throws BeansException {
	// 拿到beanName,还没有创建
	List<String> beanNames = new ArrayList<String>(this.beanDefinitionNames);
	// 执行getBean
	getBean(beanName);
}
  • getBean()
@Override
public Object getBean(String name) throws BeansException {
	return doGetBean(name, null, null, false);
}
  • doGetBean()
protected <T> T doGetBean(
			final String name, final Class<T> requiredType, final Object[] args, boolean typeCheckOnly)
			throws BeansException {
	// Create bean instance.
	if (mbd.isSingleton()) {
		sharedInstance = getSingleton(beanName, new ObjectFactory<Object>() {
			@Override
			public Object getObject() throws BeansException {
				try {
					return createBean(beanName, mbd, args);
				}
				catch (BeansException ex) {
					// Explicitly remove instance from singleton cache: It might have been put there
					// eagerly by the creation process, to allow for circular reference resolution.
					// Also remove any beans that received a temporary reference to the bean.
					destroySingleton(beanName);
					throw ex;
				}
			}
		});
}
  • createBean(beanName, mbd, args)
@Override
protected Object createBean(String beanName, RootBeanDefinition mbd, Object[] args) throws BeanCreationException {
	Object beanInstance = doCreateBean(beanName, mbdToUse, args);
}
  • doCreateBean(beanName, mbdToUse, args)
// 实际创建指定的bean。预创建处理此时已经发生,区分默认 bean 实例化、使用工厂方法和自动装配构造函数。
protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args){
	// 创建bean
	instanceWrapper = createBeanInstance(beanName, mbd, args);
	// 为属性设值
	populateBean(beanName, mbd, instanceWrapper);
	if (exposedObject != null) {
		// 初始化bean
		exposedObject = initializeBean(beanName, exposedObject, mbd);
	}
}
  • initializeBean(beanName, exposedObject, mbd)
protected Object initializeBean(final String beanName, final Object bean, RootBeanDefinition mbd) {
	// 判断bean是否实现了Aware接口,有则执行相关方法
	invokeAwareMethods(beanName, bean);
	// 初始化前增强,通过实现BeanPostProess接口重写方法实现
	if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
		}
	// 然后执行初始化方法
	invokeInitMethods(beanName, wrappedBean, mbd);
	// 初始化后增强
	if (mbd == null || !mbd.isSynthetic()) {
			wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
		}
}	

整个bean的生命周期就体现在了上述的源码调试中


测试

package cn.edu.guet.config;

import org.springframework.stereotype.Component;

/**
 * @author pangjian
 * @ClassName Boy
 * @Description TODO
 * @date 2021/8/31 9:13
 */
@Component
public class Boy {

    public Boy() {
        System.out.println("boy实例化");
    }
}
package cn.edu.guet.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

/**
 * @author pangjian
 * @ClassName MyBeanPostProcess
 * @Description TODO
 * @date 2021/8/30 21:18
 */
@Component
public class MyBeanPostProcess implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("4. 初始化之前postProcess增强-----" + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("6. 初始化之后postProcess增强-----" + beanName);
        return bean;
    }

}

实现了该接口的类和关联类都会执行后置处理器的两个方法

package cn.edu.guet.config;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author pangjian
 * @ClassName MyApplicationContext
 * @Description TODO
 * @date 2021/8/30 13:21
 */
@Component
public class MyBean implements ApplicationContextAware, InitializingBean {

    private static ApplicationContext applicationContext;

    @Autowired
    private Boy boy;

    public MyBean() {
        System.out.println("1.对象实例化");
    }

    public Boy getBoy() {
        return boy;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        MyBean myBean = applicationContext.getBean("myBean", MyBean.class);
        Boy boy = myBean.getBoy();
        // 如果boy 也不为空,则证明了boy类属性赋值是在Aware方法之前就已经完成了
        if (myBean != null && boy != null) {
            System.out.println("2.赋值完成" + boy);
        }

        MyBean.applicationContext = applicationContext;
        System.out.println("3.Aware 接口方法执行");
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("5.自定义初始化方法执行");
    }

    @Override
    public String toString() {
        return "MyBean{" +
                "boy=" + boy +
                '}';
    }
}
  • 配置类,导入各个Bean
@Configuration
@Import({MyBeanPostProcess.class, Boy.class})
public class MyConfig {

    @Bean
    public MyBean myBean(){
        return new MyBean();
    }

}

在这里插入图片描述

现在Spring版本高以后,@Autowired注入是不会调用set方法进行注入的,而是反射通过破坏修饰词private去通过类名.属性去完成属性的赋值

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值