SpringBean-生命周期

Spirng Bean 元信息配置阶段

1 面向资源

  • xml配置(很熟悉了不做讨论)
  • Properties配置
public class BeanMetaDemo {
    public static void main(String[] args) {
        DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
        PropertiesBeanDefinitionReader reader = new PropertiesBeanDefinitionReader(factory);
        Resource resource = new ClassPathResource("/meta-info/person.properties");
        // 解决乱码的问题
        EncodedResource encodedResource = new EncodedResource(resource, "UTF-8");
        int i = reader.loadBeanDefinitions(encodedResource);
        Object person = factory.getBean("person");
        System.out.println(person);
    }
}
person.(class)=pojo.Person
person.id=10010
person.name=李勇

2 面向注解
3 面向API

Bean 元信息解析

1 面向资源BeanDefiniton 解析

  • BeanDefinitonReader
  • xml 解析器 BeanDefinitionParser
    2 面向注解BeanDefiniton
  • AnnotatedBeanDefinitonReader
// 基于注解的APIBean注册
public class AnnotatedBeanDefinitionParsingDemo {
 public static void main(String[] args) {
     DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
     AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(beanFactory);
     int beforeCount = beanFactory.getBeanDefinitionCount();
     reader.register(AnnotatedBeanDefinitionParsingDemo.class);
     int afterCount = beanFactory.getBeanDefinitionCount();

     System.out.println(afterCount - beforeCount);
     AnnotatedBeanDefinitionParsingDemo bean = beanFactory.getBean(AnnotatedBeanDefinitionParsingDemo.class);
     System.out.println(bean);
 }

Bean注册阶段

BeanDefinitionregistery

@Override
	public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {
			try {
				((AbstractBeanDefinition) beanDefinition).validate();
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition existingDefinition = this.beanDefinitionMap.get(beanName);
		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);
		}
		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);
		}
	}

BeanDefinition 合并阶段

BeanDefinition#getParentName
在这里插入图片描述
在xml里面是通过这个属性来配置的,所以需要classloader的参与:
在这里插入图片描述

在注解其实本身就包含了继承关系,可以直接拿到父类信息。

1 没有父类了已经RootBeanDefinition 不需要合并
2 普通的BeanDefinition为GenericBeanDefinition需要合并
合并过程中GenericBeanDefinition->RootBeanDefinition
在这里插入图片描述

代码贴士:ConcurrentHashMap虽然是线程安全的但是只针对于单个操作,get和put,如果有多个get,put操作一起也不能保证是线程安全的。

Bean Class 加载

这里返回的是一个文本BeanDefinition#getBeanClassName
在这里插入图片描述AbstractAutowireCapableBeanFactory#createBean
在这里插入图片描述
org.springframework.beans.factory.support.AbstractBeanDefinition#resolveBeanClass

在这里插入图片描述

this.beanClass 之前是字符串类型,在处理完毕以后是Class类型。

Bean实例化前阶段

InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation
通常用于替换之前的实现类,绕开Spring的实例化。

public class BeanInstantiationLifeCycleDemo {

    @Bean
    public Person person() {
        Person person = new Person();
        person.setName("liyong");
        person.setId(11L);
        return person;
    }
    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
        context.register(BeanInstantiationLifeCycleDemo.class);
        DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) context.getBeanFactory();
        beanFactory.addBeanPostProcessor(new MyPostProcessBeforeInstantiation());
        context.refresh();
        Object person = context.getBean("person");
        System.out.println(person);
    }
    static class MyPostProcessBeforeInstantiation implements InstantiationAwareBeanPostProcessor {
        @Override
        public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException {
            // 实例化之前执行 如果说满足条件直接替换之前的实现
            if (ObjectUtils.nullSafeEquals("person", beanName) && Person.class.equals(beanClass)) {
                Person person = new Person();
                person.setId(11L);
                person.setName("person");
                return person;
            }
            return null;
        }
    }
}

在这里我们返回了我们创建的对象,所以后面的操作不再进行了:
在这里插入图片描述

Spring Bean 实例化阶段

实例化方式

  • 传统方式
  • 实例化策略InstantitaionStrategy
    构造器依赖注入

InstantitaionStrategy有两种实现方法
1 传统的实现方法
AbstractAutowireCapableBeanFactory#createBeanInstance
在这里插入图片描述

2 特殊的实现方法

Spring Bean 实例化后阶段

这里控制了对象实例化以后是否对属性进行赋值:
InstantiationAwareBeanPostProcessor#postProcessAfterInstantiation

@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
   // 这里就可以注入我们自己的值,这里和前面before的区别就是 这里我们对象已经被创建了,我们是在已经创建好的对象给它改变属性值
   if (ObjectUtils.nullSafeEquals("person", beanName) && Person.class.equals(bean.getClass())) {
       Person person = (Person) bean; 
       person.setId(11L);
       person.setName("person");
       return false;
   }
   return true;
}

在这里插入图片描述
在这里我们返回了false,所以后面操作不会执行了,而后面的操作也就是赋值属性。

Spring Bean 属性赋值前阶段

Bean 属性值元信息

  • PropertyValues

Bean属性值前回调

  • InstantiationAwareBeanPostProcessor#postProcessPropertyValues 注意到在高版本的Spring 这个方法已经被打上了过时的标签
  • InstantiationAwareBeanPostProcessor#postProcessProperties (5.1及以后)

如果我们希望拦截属性赋值操作

@Override
public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) throws BeansException {
   // 这里就可以注入我们自己的值 需要注意如果我们postProcessAfterInstantiation 已经返回了false这里就不会执行
   if (ObjectUtils.nullSafeEquals("person", beanName) && Person.class.equals(bean.getClass())) {
       MutablePropertyValues propertyValues = new MutablePropertyValues();
       propertyValues.add("number", "1111");
       return propertyValues;
   }
   return pvs;
}

Spring 生命周期 Aware 接口的顺序

其实顺序就是下面这个顺序:
在这里插入图片描述
我们可以看到源码中的调用顺序:
在这里插入图片描述
EnvironmentAware 以及后面的接口都是属于ApplicationContext的生命周期,普通的BeanFactory 并不会回调这些Aware接口,在操作ApplicationContext的时候才会回调这些接口,因为在ApplicationContext初始化阶段,会添加一个AwarePostProcessor但是这个类是内置类,所以只有与ApplicationContext打交道才会有更多的Aware接口方法回调。

SpirngBean初始化 前阶段

在前面的讨论,已经完成了以下工作,这些工作也是属于前阶段
在这里插入图片描述
InstantiationAwareBeanPostProcessor#postProcessBeforeInitialization

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {

}

源码是在这里进行应用的:
在这里插入图片描述

AbstractApplicationContext#prepareBeanFactory
在这里插入图片描述

SpringBean 初始化阶段

他们的执行顺序就是下面的执行顺序
在这里插入图片描述
@PostConstruct 是依赖于注解驱动的,如果通过xml的方式是不会触发的,因为没有对应的PostProcessor。如果我们需要这个生效

beanFactory.addBeanPostProcessor(new CommonAnnotationPostProcessor());

自定义方法是通过xml init-method来进行配置。
AbstractAutowireCapableBeanFactory#initializeBean
实际上PostConstruct是在这个方法applyBeanPostProcessorsBeforeInitialization进行触发的
在这里插入图片描述

初始化后阶段

BeanPostProcessor#postProcessAfterInitialization

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
    return InstantiationAwareBeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
}

初始化完成阶段

通过下面这个接口来实现
在这里插入图片描述
preInstantiateSingletons在这个方法里面被调用,他通常需要在ApplicationContext来进行使用,需要显式的调用。确保Bean已经被完全初始化。
在这里插入图片描述

Spring Bean销毁阶段

在这里插入图片描述
DisposableBeanAdapter#destroy()
销毁前:
DestructionAwareBeanPostProcessor

@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
}
beanFactory.addBeanPostProcessor(new MyDestructionAwareBeanPostProcessor());
// 这个销毁是在容器中销毁 而不是在Java 中销毁
beanFactory.destoryBean("person", person);

Spring销毁阶段

有这样几种方式
在这里插入图片描述

Spirng Bean垃圾回收

在这里插入图片描述

  • 18
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值