Spring Bean 生命周期

  • Spring Bean 元信息配置阶段
  • Spring Bean 元信息解析阶段
  • Spring Bean 注册阶段
  • Spring BeanDefinition 合并阶段
  • Spring Bean Class 加载阶段
  • Spring Bean 实例化前阶段
  • Spring Bean 实例化阶段
  • Spring Bean 实例化后阶段
  • Spring Bean 属性赋值前阶段
  • Spring Bean Aware接口回调阶段
  • Spring Bean 初始化前阶段
  • Spring Bean 初始化阶段
  • Spring Bean 初始化后阶段
  • Spring Bean 初始化阶段完成阶段
  • Spring Bean 销毁前阶段
  • Spring Bean 销毁阶段
  • Spring Bean 垃圾收集
  • 面试题

Spring Bean元信息配置,解析阶段

BeanDefinition XML,properties配置以及解析

  • 面向资源配置
    • XML配置
    • Properties资源配置
  • 面向注解
  • 面向API
	public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        /* Xml配置读取 */
//        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
//        String xmlPath = "";
//        reader.loadBeanDefinitions(xmlPath);
        PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(beanFactory);
        String location = "META-INF/user.properties";
        ClassPathResource resource = new ClassPathResource(location);
        EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
        int i = reader.loadBeanDefinitions(encodedResource);
        System.out.println("已加载数量" + i);

//        String[] beanDefinitionNames = beanFactory.getBeanDefinitionNames();
//        BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanDefinitionNames[0]);
//        System.out.println(beanDefinitionNames);
        System.out.println(beanFactory.getBean( User.class));
    }

如果在properties文件中进行注册Bean,需要注意,注册class的时候需要注意 .(class)

user.(class) = edu.ahau.thinking.in.spring.ioc.overview.domain.User

properties文件使用中文可能会出现乱码,因此需要使用EncodedResource进行转码;

注解配置以及解析

public class AnnotatedBeanDefinitionParsingDemo {
    public static void main(String[] args) {
        DefaultListableBeanFactory registry = new DefaultListableBeanFactory();

        // 基于java注解的 BeanDefinitionReader
        AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(registry);
        // 对BeanNameGenerator重新实现,并且重新注入
        MyBeanNameGenerator myBeanNameGenerator = new MyBeanNameGenerator();
        reader.setBeanNameGenerator(myBeanNameGenerator);
        int beanNumberNumsBefore = registry.getBeanDefinitionCount();
        // 注册当前类(非component)
        reader.register(AnnotatedBeanDefinitionParsingDemo.class);
        int beanNumberNumsAfter = registry.getBeanDefinitionCount();
        System.out.println("已加载BeanDefinition数量: "+(beanNumberNumsAfter - beanNumberNumsBefore));
        // 普通的class作为Component注册到SpringIoC容器后,通常Bean名称为小驼峰
        // AnnotationBeanNameGenerator对BeanName的构造


        System.out.println(registry.getBean("haha"));

    }
}

在上面代码自定义实现了BeanNameGenerator,因此没有使用小驼峰BeanName获取Bean,而是自定义的"haha
"

public class MyBeanNameGenerator implements BeanNameGenerator {
    @Override
    public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
        return "haha";
    }
}

Spring Bean 注册阶段

注册过程在org.springframework.beans.factory.support.DefaultListableBeanFactory#registerBeanDefinition中;
源码查看,并分析:

	// 存储beanDefinition
	private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
	// 保证创建Bean的顺序
	private volatile List<String> beanDefinitionNames = new ArrayList<>(256);
	@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {
		/* 对beanName和beanDefinition进行空判断 */
		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");
		/* 校验Bean的定义 */
		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}
		// 获取已经存在的beanDefinition
		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		/* bean的覆盖 */
		if (existingDefinition != null) {
			if (!isAllowBeanDefinitionOverriding()) {
				throw new BeanDefinitionOverrideException(beanName, beanDefinition, existingDefinition);
			}
			else if (existingDefinition.getRole() < beanDefinition.getRole()) {
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (logger.isInfoEnabled()) {
					logger.info("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							existingDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(existingDefinition)) {
				if (logger.isDebugEnabled()) {
					logger.debug("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (logger.isTraceEnabled()) {
					logger.trace("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + existingDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);
		}
		/* 创建Bean */
		else {
			if (hasBeanCreationStarted()) {
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {
					this.beanDefinitionMap.put(beanName, beanDefinition);
					List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
					updatedDefinitions.addAll(this.beanDefinitionNames);
					updatedDefinitions.add(beanName);
					this.beanDefinitionNames = updatedDefinitions;
					removeManualSingletonName(beanName);
				}
			}
			else {
				// Still in startup registration phase
				this.beanDefinitionMap.put(beanName, beanDefinition);
				this.beanDefinitionNames.add(beanName);
				removeManualSingletonName(beanName);
			}
			this.frozenBeanDefinitionNames = null;
		}

		if (existingDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

Spring BeanDefinition 合并阶段

先看xml

 <!-- RootBeanDefinition ,不需要进行合并 -->
<bean id="user" class="edu.ahau.thinking.in.spring.ioc.overview.domain.User">
    <property name="age" value="12"/>
    <property name="workCities" value="BEIJING,HANGZHOU"/>
    <property name="cityList" value="BEIJING,SHANGHAI"/>
  </bean>

<!-- 普通BeanDefinition定义,GenericBeanDefinition -->
  <bean id="superUser" class="edu.ahau.thinking.in.spring.ioc.overview.domain.SuperUser" primary="true" parent="user">
    <property name="address" value="anhui"/>
  </bean>

在BeanDefinition中存在String getParentName();获取的值就是<bean>标签里面的parent;

user是使用RootBeanDefinition进行定义的,所以不存在parent,但是依然需要使用GenericBeanDefinition进行定义

superUser就是使用GenericBeanDefinition进行定义,使用org.springframework.beans.factory.support.BeanDefinitionBuilder#genericBeanDefinition(java.lang.String)构建出一个BeanDefinition;

<bean>标签里面写上parent,就会把parentBean注入到当前Bean中,就如上述user的信息放入superUser中;

根据依赖查找的Demo

public class MergedBeanDefinitionDemo {

    public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();

        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);

        reader.loadBeanDefinitions("classpath:\\META-INF/dependency-looKup-context.xml");

        User user = beanFactory.getBean("user", User.class);
        System.out.println(user);
        SuperUser superUser = beanFactory.getBean("superUser", SuperUser.class);
        System.out.println(superUser);
    }
}

output: superUser里面包含着user的信息
User{name=‘null’, age=12, beanName=‘user’, workCities=[BEIJING, HANGZHOU], cityList=[BEIJING, SHANGHAI]}
SuperUser{address=‘anhui’}User{name=‘null’, age=12, beanName=‘superUser’, workCities=[BEIJING, HANGZHOU], cityList=[BEIJING, SHANGHAI]}

跟着Debug一步一步的来
User:

  1. org.springframework.beans.factory.support.AbstractBeanFactory#getMergedBeanDefinition(java.lang.String, org.springframework.beans.factory.config.BeanDefinition, org.springframework.beans.factory.config.BeanDefinition)

入的Bean是user,因为Demo里是依赖查找是按照顺序的;在这里插入图片描述
GenericBeanDefinition转换成RootBeanDefinition
在这里插入图片描述

superUser:
如果存在,存在了user这个Bean,通过一系列操作到达这一步,overrideFrom()是对parent里面属性进行覆盖或者添加到superUser这个Bean;最后还是转换成RootBeanDefinition.
在这里插入图片描述

Spring Bean Class 加载阶段

  • ClassLoader类加载
  • Java Security 安全控制
  • ConfigurableBeanFactory临时ClassLoader

String类型的BeanName转换为Class对象的阶段

Spring Bean 实例化前阶段

public static void main(String[] args) {
        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
        beanFactory.addBeanPostProcessor(new MyInstantiationAwareBeanPostProcessor());

        XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);

        reader.loadBeanDefinitions("classpath:\\META-INF/dependency-looKup-context.xml");
        System.out.println(beanFactory.getBean("superUser"));  //SuperUser{address='null'}User{name='null', age=0, beanName='null', workCities=null, cityList=null} 被拦截

    }

    static class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            // 拦截superUser
            if (ObjectUtils.nullSafeEquals("superUser", beanName) && SuperUser.class.equals(beanClass)) {
                return new SuperUser();
            }
            return null;
        }
    }

postProcessBeforeInstantiation —> applyBeanPostProcessorsBeforeInstantiation —> 、

Spring Bean 实例化阶段

  • 传统实例化方式
    • 实例化策略 - InstantiationStrategy
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值