Spring的IOC常用注解(含源码)
一、容器中注入组件
1,包扫描 + 组件标注注解
a)组件标注
- @Controller
- @Service
- @Repository
- @Component
b)包扫描@ComponentScan
@ComponentScan中主要值的解释
- value:扫描的包路径(数组)
- excludeFilters:指定扫描的时候按照什么规则排除那些组件(@ComponentScan.Filter)includeFilters:指定扫描的时候只需要包含哪些组件。使用同excludeFilter。
- FilterType.ANNOTATION:按照注解
- FilterType.ASSIGNABLE_TYPE:按照给定的类型
- FilterType.ASPECTJ:使用ASPECTJ表达式
- FilterType.REGEX:使用正则指定
- FilterType.CUSTOM:使用自定义规则
- useDefaultFilters:是否使用默认的扫描机制。默认按照a)中组件标注扫描
2,使用@Bean导入
a)@Scope作用域
- prototype:多实例的:ioc容器启动并不会去调用方法创建对象放在容器中。每次获取的时候才会调用方法创建对象;
- singleton:单实例的(默认值):ioc容器启动会调用方法创建对象放到ioc容器中。以后每次获取就是直接从容器(map.get())中拿,
- request:同一次请求创建一个实例
- session:同一个session创建一个实例
b)@Lazy
单实例bean:默认在容器启动的时候创建对象;
懒加载:容器启动不创建对象。第一次使用(获取)Bean创建对象,并初始化。
c)@Conditional
@Bean上加改注解,按照一定的条件进行判断,满足条件给容器中注册bean;如在类上加改注解,这个类中配置的所有bean注册才能生效。
- @ConditionalOnClass 表示如果有后面的类,那么就加载这个自动配置;
- @ConditionalOnMissingClass 如果没有后面的类,才自动配置。如果没有就配置,保证bean的唯一。
大量运用于SpringBoot中。
3,使用@Import导入
快速为容器中导入一个组件。
- @Import(要导入到容器中的组件);容器中就会自动注册这个组件,id默认是全类名
- ImportSelector:返回需要导入的组件的全类名数组
- ImportBeanDefinitionRegistrar:手动注册bean到容器中
4,FactoryBean(工厂Bean)
将实现FactoryBean的类加到容器中。
- 默认从容器中获取到的是工厂bean调用getObject创建的对象。
- 要获取工厂Bean本身,我们需要给id前面加一个&
二、Bean的生命周期
1,bean生命周期
bean创建 --- 初始化 --- 销毁
- 构造(对象创建)
- 单实例:在容器启动的时候创建对象
- 多实例:在每次获取的时候创建对象
- 初始化:
- 成员变量赋值,各种增强等,对象创建完成,并赋值好,调用初始化方法
- 销毁:
- 单实例:容器关闭的时候
- 多实例:容器不会管理这个bean;容器不会调用销毁方法;
2,定义Bean初始化和销毁
a)定义initMethod和destroyMethod
- 定义初始化方法,定义@Bean的initMethod为该方法
- 定义销毁方法,定义@Bean的destroyMethod为该方法
b)实现InitializingBean和DisposableBean接口
- 定义当前对象实现InitializingBean接口。其中afterPropertiesSet方法会在当前对象设置完属性之后调用。
- 定义当前对象实现DisposableBean接口。其中destroy方法会在当前对象销毁的时候调用。
c)可以使用JSR250
- @PostConstruct定义在方法上,则该方法会在Bean创建并且属性赋值之后执行,为初始化方法
- @PreDestroy定义在方法上,则该方法在容器销毁bean之前通知我们进行清理工作
d)实现BeanPostProcessor,bean的后置处理
源码:Demo04_BeanLifeCycle、Demo04_BeanPostProccessor
在bean初始化前后进行一些处理工作;
- postProcessBeforeInitialization:在初始化之前工作
- postProcessAfterInitialization:在初始化之后工作
3,从源码看BeanPostProcessor后置处理器
在Spring类AbstractAutowireCapableBeanFactory中方法doCreateBean可以看到
//给bean进行属性赋值
populateBean(beanName, mbd, instanceWrapper);
//初始化bean
exposedObject = initializeBean(beanName, exposedObject, mbd);
在方法initializeBean中可以看到
//调用applyBeanPostProcessorsBeforeInitialization进行初始化之前的处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
}
//调用自定义初始化方法
try {
invokeInitMethods(beanName, wrappedBean, mbd);
}catch ...//调用applyBeanPostProcessorsAfterInitialization进行初始化之后的处理
if (mbd == null || !mbd.isSynthetic()) {
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
}
总结:
BeanPostProcessor会在Bean对象创建并属性赋值完成之后,在执行init初始化方法的前后进行增加。
4,BeanPostProcessor在Spring中的应用
a)ApplicationContextAware各种Aware接口
查看源码类ApplicationContextAwareProcessor实现了BeanPostProcessor接口,其中postProcessBeforeInitialization的实现为:
//如果当前bean为各种指定的Aware的bean就会执行invokeAwareInterfaces方法
this.invokeAwareInterfaces(bean); private void invokeAwareInterfaces(Object bean) {
if (bean instanceof Aware) {
...
//如果当前bean为ApplicationContextAware的子类,则会调用其setApplicationContext将applicationContext进行赋值
if (bean instanceof ApplicationContextAware) {
((ApplicationContextAware)bean).setApplicationContext(this.applicationContext);
}
}
}
所以在ApplicationContextAware时,可以通过setApplicationContext获取到ApplicationContext上下文对象
b)BeanValidationPostProcessor
查看BeanValidationPostProcessor实现了BeanPostProcessor接口,其中不管是postProcessBeforeInitialization还是postProcessAfterInitialization,均调用了doValidate方法来验证当前bean是否合理
c)@PostConstruct和@PreDestroy方法
查看InitDestroyAnnotationBeanPostProcessor实现了BeanPostProcessor接口,其中postProcessBeforeInitialization在当前bean初始化之前的源码为:
//获取生命周期的metadata,得到标注有@PostConstruct和@PreDestroy的方法
LifecycleMetadata metadata = findLifecycleMetadata(bean.getClass());
try {
//这个方法会采用反射的方式,调用方法
metadata.invokeInitMethods(bean, beanName);
}...
d)AutowiredAnnotationBeanPostProcessor
用来处理@Autowire注解的属性
三、属性赋值
- @Value:给属性赋值,也可以使用SpEL和外部文件的值
- @PropertySource:读取外部配置文件中的k/v保存到运行环境中。@PropertySource(value={"classpath:/application.yaml"})
- @Autowried 装配优先级如下:构造器、参数、方法、属性。
- 使用按照类型去容器中找对应的组件
- 如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
- @Qualifier:使用@Qualifier指定需要装配的组件的id,结合@Autowried使用
- @Primary:spring自动装配的时候,默认首先bean,配合@Bean使用
- @Resource(JSR250):jsr规范:按照组件名称进行装配,不支持@Primary和@Autowired(reqiured=false)
- @Inject(JSR330):jsr规范和@Autowired功能一致,不支持require=false;
- @Profile:结合@Bean使用,默认为default环境,可以通过命令行参数来切换环境
- 加上VM参数:-Dspring.profiles.active=dev 则采用的dev环境。多个用逗号隔开
- 1.无参构造ApplicationContext,2.通过applicationContext.getEnvironment().setActiveProfiles("dev"),3.注册配置类applicationContext.register(Main.class),4.采用ApplicationContext.refresh()
Spring的IOC常用注解(含源码)的更多相关文章
- Spring提取@Transactional事务注解的源码解析
声明:本文是自己在学习spring注解事务处理源代码时所留下的笔记: 难免有错误,敬请读者谅解!!! 1.事务注解标签 <tx:annotation-driven /> 2.tx 命名空间 ...
- Spring第四天,BeanPostProcessor源码分析,彻底搞懂IOC注入及注解优先级问题!
- Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合(注解及源码)
Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合(注解及源码) 备注: 之前在Spring3 + Spring MVC+ Mybatis 3+Mysql 项目整合中 ...
- Spring 3.1新特性之二:@Enable*注解的源码,spring源码分析之定时任务Scheduled注解
分析SpringBoot的自动化配置原理的时候,可以观察下这些@Enable*注解的源码,可以发现所有的注解都有一个@Import注解.@Import注解是用来导入配置类的,这也就是说这些自动开启的实 ...
- c++实现游戏开发中常用的对象池(含源码)
c++实现游戏开发中常用的对象池(含源码) little_stupid_child2017-01-06上传 对象池的五要素: 1.对象集合 2.未使用对象索引集合 3.已使用对象索引集合 4.当前 ...
- 谈谈Spring的IoC之注解扫描
问题 IoC是Inversion of Control的缩写,翻译过来即"控制反转".IoC可以说是Spring的灵魂,想要读懂Spring,必先读懂IoC.不过有时候硬着头皮 ...
- spring security 授权方式(自定义)及源码跟踪
spring security 授权方式(自定义)及源码跟踪 这节我们来看看spring security的几种授权方式,及简要的源码跟踪.在初步接触spring security时,为了实现它的 ...
- spring MVC cors跨域实现源码解析
# spring MVC cors跨域实现源码解析 > 名词解释:跨域资源共享(Cross-Origin Resource Sharing) 简单说就是只要协议.IP.http方法任意一个不同就 ...
- Spring Boot REST(二)源码分析
Spring Boot REST(二)源码分析 Spring 系列目录(https://www.cnblogs.com/binarylei/p/10117436.html) SpringBoot RE ...
随机推荐
- Ubuntu中Unable to acquire the dpkg frontend lock (/var/lib/dpkg/lock-frontend)问题的解决
参考博客:https://blog.csdn.net/shimadear/article/details/90598646 问题描述: 解决方法: 第一种情况: 进程中存在与apt相关的正在运行的进程 ...
- JVM调优参数、方法、工具以及案例总结
这种文章挺难写的,一是JVM参数巨多,二是内容枯燥乏味,但是想理解JVM调优又是没法避开的环节,本文主要用来总结梳理便于以后翻阅,主要围绕四个大的方面展开,分别是JVM调优参数.JVM调优方法(流程) ...
- Linux-输出/输入重定向
目录 重定向的分类 输出重定向 将标准输出重定向到文件 将标准输出追加重定向到文件 将错误输出重定向到文件 将标准输出和错误输出都重定向到文件 将错误输出重定向到黑洞文件 输入重定向 重定向的分类 名 ...
- Playbook 角色(Roles) 和 Include 语句
简介 当我们刚开始学习运用 playbook 时,可能会把 playbook 写成一个很大的文件,到后来可能你会希望这些文件是可以方便去重用的,所以需要重新去组织这些文件. Include 语句 基本 ...
- virtualBox 设置增强功能粘贴和拖放
virtualBox 5.2.8 (在运行的虚拟里中) 设备 -> 安装增强功能 virtualBox 管理器中设置(要在虚拟机关机的情况下配置) 常规 -> 高级里设置双向粘贴和拖放
- cccc超级酱油心得
第一次线下比赛献给了cccc. 大致写写自己心得,比赛前一天晚上日常和室友在宿舍玩到11点多,洗漱上床.睡前突然想起第二天还有比赛,顿时激动加紧张.在床上刷了刷知乎和百度,看几道去年的真题,熬到了12 ...
- C# 数据类型(3)
动态类型 dynamic types 动态类型是后来引进的,他其实是一个static type,但是不像其他的静态类型,编译器不会检查你到底是啥类型(也不会检查你能不能去call某个'method') ...
- springboot(五)Scheduling demo
在项目开发过程中,经常会使用到定时任务(跑批),springboot默认已经实现了,只需要添加相应的注解就可以实现 在启动类上加入注解,开启定时任务 @SpringBootApplication @E ...
- TypeScript 1.7 & TypeScript 1.8
TypeScript 1.7 & TypeScript 1.8 1 1 https://zh.wikipedia.org/wiki/TypeScript TypeScript是一种由微软开发的 ...
- SQL All In One
SQL All In One Structured Query Language SQL is an ANSI (American National Standards Institute) stan ...