导图社区 Spring核心之 IOC容器
Spring核心之 IOC容器知识点归纳,未完待续。。
编辑于2020-10-23 16:38:43Spring Core
IOC容器
容器
定义:ApplicationContext接口
AnnotationConfigApplicationContext
FileSystemXmlApplicationContext
ClassPathXmlApplicationContext
注解文件路径下的XMLclasspath下的XML
作用:实例化,配置和组装 Bean
如何工作:读取配置元数据来获取指令
XML
Java注解
Java代码
配置元数据
Application相比于BeanFactory的其他功能
使用MessageSource 进行国际化
通过ResourceLoader接口访问资源(比如URL和文件)
通过ApplicationEventPublisher接口,可以支持时间发布(对应Bean需实现ApplicationListener接口)
通过HierarchicalBeanFactory接口来加载多个(层次化)context,允许每个context关注自己所在的层,比如应用的web层
Bean
简单的POJO对象
初始化和销毁方法
自定义init-method和destroy-method方法并在@Bean中配置
实现InitializingBean 和DisposableBean接口
使用JSR250注解@PostConstruct和@PreDestroy
BeanPostProcessor后置处理器
实例化Bean
构造函数
静态工厂方法
实例工厂方法
依赖注入
构造方法注入
setter注入
注入方式
XML配置
<property/>
<constructor-arg/>
注解配置
@Autowired注解
Spring自带注解,默认按照类型匹配的若按名称匹配,配合@Qualifier
@Inject
JSR330规范,默认按照类型匹配的若按名称匹配,需要配合@Name
@Resource
JSR250规范,默认按照名称匹配
懒加载
当容器请求Bean的时候再进行加载
XML方式:lazy-init=true
注解方式:@Lazy
Scope作用域
单例Bean使用原型Bean引用问题只创建一次Bean,返回的是单例Bean
查找方法注入
基于CGLib的动态代理
XML方式:lookup-method
注解作用在方法上:@Lookup( beanName)
方法注入
实现ApplicationContextAware接口,每次获取原型bean时,调用getBean()方法得到一个新的bean。
不再使用自动装配Bean 通过getObject方法获取
6种不同作用范围的Bean
singleton
prototype
常用
request
session
application
websocket
仅在WebApplication容器中使用
注解
@Bean
@Component
@Repository
@Service
@Controller
@Configuration
@Import
导入类
Spring 4.2之后,@Import可以直接指定实体类组件
@Configuration 注解的类
ImportSelector接口实现类
传入数组全类名批量导入
ImportBeanDefinitionRegistrar 的实现类
动态注册Bean
@Required
@Primary
@ComponentScan
使用过滤器来控制扫描范围
@Value
@ImportResource
注解配置类导入XML配置
@PropertySource
@Profile
Aware感知接口
实现了该接口的Bean可以操控容器获取自己需要的属性和依赖
ApplicationContextAware
BeanNameAware
BeanFactoryAware
Environment接口
profiles:偏好环境设置
@Profile
作用在配置类上
激活 Profile
spring.profiles.active
ctx.getEnvironment().setActiveProfiles("环境");
spring-test模块的@ActiveProfiles注解声明
properties:属性文件
@PropertySource
可扩展点
BeanPostProcessor接口
操作Bean
postProcessBeforeInitialization()Bean实例化完毕(注入完毕),afterPropertiesSet或自定义init方法执行之前
postProcessAfterInitialization()Bean实例化完毕(注入完毕), afterPropertiesSet或自定义init方法执行之后
InstantiationAwareBeanPostProcessor前面的子接口,Bean实例化时的后置处理器
Initialization表示初始化,对象已经生成Instantiation表示实例化,对象还未生成
postProcessBeforeInstantiation()Bean实例化之前调用
它在目标对象实例化之前调用,该方法的返回值类型是Object,我们可以返回任何类型的值。由于这个时候目标对象还未实例化,所以这个返回值可以用来代替原本该生成的目标对象的实例(比如代理对象)。如果该方法的返回值代替原本该生成的目标对象,后续只有postProcessAfterInitialization方法会调用,其它方法不再调用;否则按照正常的流程走
postProcessAfterInstantiation()Bean实例化之后调用
在目标对象实例化之后调用,这个时候对象已经被实例化,但是该实例的属性还未被设置,都是null。因为它的返回值是决定要不要调用postProcessPropertyValues方法的其中一个因素(因为还有一个因素是mbd.getDependencyCheck());如果该方法返回false,并且不需要check,那么postProcessPropertyValues就会被忽略不执行;如果返回true,postProcessPropertyValues就会被执行
postProcessPropertyValues()对属性值进行修改
如果postProcessAfterInstantiation方法返回false,该方法可能不会被调用。如果返回true,可以在该方法内对属性值进行修改
BeanFactoryPostProcessor
操作BeanDefinition
BeanDefinition加载完成之后,Bean实例化之前,对加载的BeanDefinition进行修改
FactoryBean
用于自定义bean的初始化,对bean的创建、初始化有完全的控制权用于创建复杂的Bean
不同于普通Bean的是:它是实现了FactoryBean<T>接口的Bean,根据该Bean的ID从BeanFactory中获取的实际上是FactoryBean的getObject()返回的对象,而不是FactoryBean本身,如果要获取FactoryBean对象,请在id前面加一个&符号来获取。
问题
IOC和DI
ApplicationContext和BeanFactory的区别?
如何解决循环依赖?
单例setter循环依赖
解决方式:Spring通过提前曝光机制,利用三级缓存解决循环依赖
构造器的循环依赖无法解决
spring的三级缓存解决的是实例化之后属性赋值的循环依赖,构造器被调用是在实例化之前,所以无法解决构造器的循环依赖
原型模式循环依赖无法解决
多例没有使用缓存
线程安全问题:单例Bean线程不安全
把不安全的变量封装进ThreadLocal,每个线程都保留一份独立的副本
不使用成员变量,方法是安全的,因为每个线程有独立的栈空间
使用原型Bean,每次调用都会生成一个新的Bean