Spring原理

Spring Bean 生命周期与扩展机制

不错的文章

bean生命周期过程中扩展(Aware族和BeanProcessor系列):spring有哪些非常有用扩展点?
ApplicationListener 、ApplicationContextAware 扩展:聊一聊 Spring 中的扩展机制(一)
NamespaceHandler:聊一聊 Spring 中的扩展机制(二) - NamespaceHandler
InitialingBean和DisposableBean:Spring8:一些常用的Spring Bean扩展接口

另外还可以了解一下java体系中的SPI扩展机制:

//代理模式
public class Proxy implements Subject{

       private Subject subject;
       public Proxy(){
             //关系在编译时确定
            subject = new RealSubject();
       }
       public void doAction(){
             ….
             subject.doAction();
             ….
       }
}
//装饰器模式
public class Decorator implements Component{
        private Component component;
        public Decorator(Component component){
            this.component = component
        }
       public void operation(){
            ….
            component.operation();
            ….
       }
}

面试题

Bean⽣命周期

  • 单例对象: singleton
    总结:单例对象的⽣命周期和容器相同
  • 多例对象: prototype
    出⽣:使⽤对象时spring框架为我们创建
    活着:对象只要是在使⽤过程中就⼀直活着
    死亡:当对象⻓时间不⽤且没有其它对象引⽤时,由java的垃圾回收机制回收
    在这里插入图片描述
    IOC容器初始化加载Bean流程:
@Override
public void refresh() throws BeansException, IllegalStateException { 
	synchronized (this.startupShutdownMonitor) { 
		// 第⼀步:刷新前的预处理 
		prepareRefresh(); 
		//第⼆步: 获取BeanFactory并注册到 BeanDefitionRegistry 
		ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory(); 
		// 第三步:加载BeanFactory的预准备⼯作(BeanFactory进⾏⼀些设置,⽐如context的类加载器等)
	 	prepareBeanFactory(beanFactory); 
	 	try { 
		 	// 第四步:完成BeanFactory准备⼯作后的前置处理⼯作 
		 	postProcessBeanFactory(beanFactory); 
		 	// 第五步:实例化BeanFactoryPostProcessor接⼝的Bean 
		 	invokeBeanFactoryPostProcessors(beanFactory); 
		 	// 第六步:注册BeanPostProcessor后置处理器,在创建bean的后执⾏ 
		 	registerBeanPostProcessors(beanFactory); 
			// 第七步:初始化MessageSource组件(做国际化功能;消息绑定,消息解析); 
			initMessageSource(); 
			// 第⼋步:注册初始化事件派发器 
			initApplicationEventMulticaster(); 
			// 第九步:⼦类重写这个⽅法,在容器刷新的时候可以⾃定义逻辑 
			onRefresh(); 
			// 第⼗步:注册应⽤的监听器。就是注册实现了ApplicationListener接⼝的监听器 
			registerListeners(); 
			//第⼗⼀步:初始化所有剩下的⾮懒加载的单例bean 初始化创建⾮懒加载⽅式的单例Bean实例(未设置属性) 
			finishBeanFactoryInitialization(beanFactory); 
			//第⼗⼆步: 完成context的刷新。主要是调⽤LifecycleProcessor的onRefresh()⽅法,完成创建 
			finishRefresh(); 
		}
	 ……
 }
  • 总结:
    • 四个阶段
      • 实例化 Instantiation
      • 属性赋值 Populate
      • 初始化 Initialization
      • 销毁 Destruction
  • 多个扩展点
    • 影响多个Bean
      • BeanPostProcessor
      • InstantiationAwareBeanPostProcessor
    • 影响单个Bean
      • Aware
      • 注解@PostConstruct 、@PreDestroy
  • 完整流程
    • 实例化⼀个Bean,也就是我们常说的new;
    • 按照Spring上下⽂对实例化的Bean进⾏配置,也就是IOC注⼊;
    • 如果这个Bean已经实现了BeanNameAware接⼝,会调⽤它实现的setBeanName(String)⽅法,也就是根据就是Spring配置⽂件中Bean的id和name进⾏传递
    • 如果这个Bean已经实现了BeanFactoryAware接⼝,会调⽤它实现setBeanFactory(BeanFactory),也就是Spring配置⽂件配置的Spring⼯⼚⾃身进⾏传递;
    • 如果这个Bean已经实现了ApplicationContextAware接⼝,会调⽤setApplicationContext(ApplicationContext)⽅法,和4传递的信息⼀样但是因为ApplicationContext是BeanFactory的⼦接⼝,所以更加灵活
    • 如果这个Bean关联了BeanPostProcessor接⼝,将会调⽤postProcessBeforeInitialization()⽅法,BeanPostProcessor经常被⽤作是Bean内容的更改,由于这个是在Bean初始化结束时调⽤那个的⽅法,也可以被应⽤于内存或缓存技术
    • 如果Bean在Spring配置⽂件中配置了init-method属性会⾃动调⽤其配置的初始化⽅法。
    • 如果这个Bean关联了BeanPostProcessor接⼝,将会调⽤postProcessAfterInitialization(),打印⽇志或者三级缓存技术⾥⾯的bean升级
    • 以上⼯作完成以后就可以应⽤这个Bean了,那这个Bean是⼀个Singleton的,所以⼀般情况下我们调⽤同⼀个id的Bean会是在内容地址相同的实例,当然在Spring配置⽂件中也可以配置⾮Singleton,这⾥我们不做赘述。
    • 当Bean不再需要时,会经过清理阶段,如果Bean实现了DisposableBean这个接⼝,或者根据spring配置的destroy-method属性,调⽤实现的destroy()⽅法

保障线程安全⽅法

  • 在Bean对象中尽量避免定义可变的成员变量(不太现实)。
  • 在类中定义⼀个ThreadLocal成员变量,将需要的可变成员变量保存在 ThreadLocal 中

循环依赖问题

循环依赖其实就是循环引⽤,也就是两个或者两个以上的 Bean 互相持有对⽅,最终形成闭环。⽐如:A 依赖于B,B⼜依赖于A

  • Spring中循环依赖场景有:
    • prototype 原型 bean循环依赖
    • 构造器的循环依赖(构造器注⼊)
    • Field 属性的循环依赖(set注⼊)其中,构造器的循环依赖问题⽆法解决,在解决属性循环依赖时,可以使⽤懒加载,spring采⽤的是提前暴露对象的⽅法。
  • 解决方案
    • 懒加载@Lazy解决循环依赖问题
      Spring 启动的时候会把所有bean信息(包括XML和注解)解析转化成Spring能够识别的BeanDefinition并存到Hashmap⾥供下⾯的初始化时⽤,然后对每个 BeanDefinition 进⾏处理。普通 Bean 的初始化是在容器启动初始化阶段执⾏的,⽽被lazy-init=true修饰的 bean 则是在从容器⾥第⼀次进⾏context.getBean() 时进⾏触发。
    • 三级缓存解决循环依赖问题

Spring Bean 的自动装配

自动装配有哪些局限性

Qualifier

当我们注入的依赖存在多个候选者,我们得使用一些方法来筛选出唯一候选者,否则就会抛出异常。
在这里插入图片描述
解决方法

  • 在WhiteCar或者RedCar所在的类上加@Primary注解
  • 将private Car car改成private Car redCar
  • 使用@Qualifier注解
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值