Spring 核心原理 IOC
一 IOC 控制反转
Spring 的核心之一IOC,全称为Inversion of Control,中文翻译过来也就是我们常说的控制反转
IOC对于Spring框架来说,就是由Spring来负责对象的创建、配置和管理,所以可以将IOC理解为一个对象的容器。
程序员不需要关心对象的创建和销毁,在需要使用时,只需要去IOC容器中取出来使用,降低代码的耦合,实现松耦合。
由IOC容器创建出来的对象就叫做Spring Bean。
IOC容器的三个阶段大致分为:生产、使用、销毁
生产
1 加载Bean定义(BeanDefinish)
通过loadBeanDefinitions方法,找到所有定义的Bean类,放入到beanDefinitionMap中
2 创建Bean
遍历步骤1生成的beanDefinitionMap,创建Bean对象
2.1 构造对象
2.1.1 推断构造方法
- 默认无参构造方法
- 多个构造方法的情况
- 有@Auwowired注解则采用注解所在的方法
- 多个构造方法上存在@Autowired注解则报错
- 多个有参构造、没有无参构造方法也会报错
- 有无参构造、多个无参构造,没有@Autowired注解则采用无参构造方法
2.1.2 准备参数
构造方法确认后、如果是无参构造则进行下一步。
有参构造则根据参数的类型和参数名称去单例池中查找,如果没有找到,则会报错。
2.1.3 创建Bean对象
通过反射创建Bean对象。
2.2 属性填充
- 在属性的set方法上加@Autowired注解
- 直接在属性上加@Autowired注解
以上两种Spring都会进行属性的填充。在属性进行填充时,也会先根据类型去单例池取,如果取到多个再根据属性名进行匹配。
2.3 初始化实例
2.3.1 各种Aware回调,如BeanNameAware、BeanFactory回调
2.3.2 执行BeanPostProcessop的postProcessBeforeInitialization前置处理
2.3.3 执行@PostConstruct注解的方法
2.3.4 如果实现了InitialiazingBean接口,则执行afterPropertiesSet方法
2.3.5 执行指定了initMethod的方法
2.3.6 执行BeanPostProcessop的postProcessBeforeInitialization后置处理
以上Bean的初始化就完成了,这时Bean才经过完整的生命周期,放入到单例池的一级缓存中。
2.4 注册销毁
对实现了DisposableBean的Bean进行销毁注册,后续在销毁时才会执行这个方法
使用
这个阶段就是程序员写的代码调用Bean对象的过程。
销毁
销毁前、执行销毁前处理器,也就是@PreDestroy注解所在方法
销毁时,执行destroy方法
SpringBean 生命周期

代码示例
BeanLifeCycle
public class BeanLifeCycle implements BeanNameAware, BeanFactoryAware, InitializingBean, ApplicationContextAware, DisposableBean { public static final Logger LOGGER = LoggerFactory.getLogger(BeanLifeCycle.class); private AService aService; public BeanLifeCycle() { LOGGER.info("=======>实例化"); } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { LOGGER.info("=======>setApplicationContext"); } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { LOGGER.info("=======>setBeanFactory"); } @PostConstruct public void post() { LOGGER.info("=======>@PostConstruct"); } @Override public void afterPropertiesSet() throws Exception { LOGGER.info("=======>afterPropertiesSet"); } @Override public void destroy() throws Exception { LOGGER.info("=======>destroy"); } @Override public void setBeanName(String s) { LOGGER.info("=======>setBeanName"); } @Autowired public void setaService(AService aService) { LOGGER.info("=======>属性填充" + aService); this.aService = aService; } public void initMethod() { LOGGER.info("=======>initMethod"); } @PreDestroy public void preDestroy() { LOGGER.info("=======>preDestroy"); } }MyBeanPostProcessor 自定义处理器
@Component public class MyBeanPostProcessor implements BeanPostProcessor { public static final Logger LOGGER = LoggerFactory.getLogger(MyBeanPostProcessor.class); @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if ("beanLifeCycle".equals(beanName)) { LOGGER.info("=======>postProcessBeforeInitialization"); } return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if ("beanLifeCycle".equals(beanName)) { LOGGER.info("=======>postProcessAfterInitialization"); } return bean; } }MyApplication
@SpringBootApplication public class MyApplication { public static void main(String[] args) { ConfigurableApplicationContext context = SpringApplication.run(MyApplication.class, args); context.close(); } @Bean(initMethod="initMethod") public BeanLifeCycle beanLifeCycle() { return new BeanLifeCycle(); } }启动后,控制台结果

二 Spring 的依赖注入
1 依赖注入的几种方式
属性上加@Autowired注解或者@Resource注解
@Service public class AService { @Autowired BService bService; }构造方法
Spring 是默认无参构造的,如果存在无参构造,需要在有参构造上加上Autowired注解
@Service public class AService implements AInterface { BService bService; public AService() { } @Autowired public AService(BService bService) { this.bService = bService; } }只有一个有参构造时无需加Autowired注解
@Service public class AService implements AInterface { BService bService; public AService(BService bService) { this.bService = bService; } }如果存在多个有参构造,需要加上Autowired注解
@Service public class AService implements AInterface { BService bService; CService cService; @Autowired public AService(BService bService,CService cService) { this.bService = bService; this.cService = cService; } public AService(BService bService) { this.bService = bService; } }
set方法
在对象属性的set方法上加上@Autowired注解
@Service public class AService { public static final Logger LOGGER = LoggerFactory.getLogger(AService.class); BService bService; @Autowired public void setbService(BService bService) { LOGGER.info("调用了set方法,bservice=" + bService); this.bService = bService; } }
2 产生循环的依赖的场景
两个bean对象或者多个bean对象的属性依赖出现了闭环,则产生了循环依赖。
例:AService依赖了BService,BService依赖了AService,则产生了循环依赖。
@Service
public class BService {
@Autowired
AService aService;
}
@Service
public class AService {
@Autowired
BService bService;
}3 spring是怎样打破循环依赖的
一级缓存(singletonObjects):存放已经创建好的单例对象,供其他bean引用。二级缓存(earlySingletonObjects):存放原始的bean对象,即已经填充了属性(依赖注入完成)但尚未经过初始化(调用afterPropertiesSet方法)的bean对象。三级缓存(singletonFactories):存放bean工厂对象(BeanFactoryObjectProvider),用于解决循环依赖。当Spring容器创建bean时,如果检测到循环依赖,它会将bean的早期引用(early reference)存入三级缓存中。
具体步骤如下:
创建Bean:当Spring容器创建一个bean时,首先会检查该bean是否已经存在于一级缓存中。如果存在,则直接使用;如果不存在,则继续创建。注册Bean:在bean创建过程中,Spring会将bean的早期引用(未初始化的bean对象)注册到二级缓存中。处理循环依赖:如果bean A依赖于bean B,而bean B又依赖于bean A,当Spring容器创建bean A时,会尝试创建bean B。此时,如果bean B尚未完全创建,Spring容器会从二级缓存中获取bean B的早期引用,并将其注入到bean A中。使用三级缓存:在bean B的创建过程中,如果检测到对bean A的依赖,Spring容器会从三级缓存中获取bean A的早期引用,并将其注入到bean B中。这样,即使bean A尚未完全创建,bean B也可以继续创建。初始化Bean:当所有依赖都注入完成后,Spring容器会调用bean的afterPropertiesSet方法进行初始化,并将bean从二级缓存移动到一级缓存中。完成创建:此时,bean A和bean B都已完成创建,并且相互引用,循环依赖问题得到解决。
4 什么场景会报循环依赖的错误
构造方法上互相依赖的会报错(Spring无法解决构造方法循环依赖)
@Service public class AService { BService bService; public AService(BService bService) { this.bService = bService; } } @Service public class BService { AService aService; // 创建Bservice时,去容器拿AService、但发现AService正在创建中、无法提供AService的实例 public BService(AService aService) { this.aService = aService; } }
在循环依赖的组件上加入了@Async注解
@Service public class AService { @Autowired BService bService; } @Service // 加上Async注解后、Spring将不能对Bean对象进行AOP处理 @Async public class BService { @Autowired AService aService; }
