文章目录
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去通过类名.属性去完成属性的赋值