spring通过注解注册bean的方式+spring生命周期
spring容器通过注解注册bean的方式
- @ComponentScan + 组件标注注解 (@Component/@Service...)
@ComponentScan(value = "com.example.demo.annotation")
spring会将
com.example.demo.annotation目录下标注了spring能识别的注解的类注册为bean
@ComponentScan还可以指定排除和包含规则- excludeFilters: 指定排除规则,排除哪些组件
- includeFilters: 指定只需要包含哪些组件,需要设置 useDefaultFilters = false
- FilterType.ANNOTATION 基于注解过滤
- FilterType.ASSIGNABLE_TYPE : 基于给定的类型过滤
- ...
- FilterType.CUSTOM: 自定义规则过滤
@ComponentScan(value = "com.example.demo.annotation",
/*excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Controller.class})
},*/
includeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION, classes = {Configuration.class}),
@ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE,classes = {TestController.class}),
@ComponentScan.Filter(type = FilterType.CUSTOM,classes = {MyTypeFilter.class})
},useDefaultFilters = false
)
其中
CUSTOM自定义规则中的MyTypeFilter需要实现TypeFilter接口,举例如下public class MyTypeFilter implements TypeFilter {
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
String className = metadataReader.getClassMetadata().getClassName();
System.out.println("------>"+className);
if (className.contains("er")){
return true;
}
return false;
}
}
- @Bean (可以将第三方包中的类注册为bean)
@Bean
Person person() {
return new Person("zhang");
}
- @Import
@Import({Color.class, MyImportSelector.class, MyImportBeanDefinitionRegistrar.class})
- 导入一个普通类,容器会自动注册这个组件,组件的id默认是类的全类名
- 导入
ImportSelector:返回需要注册的组件
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.example.demo.annotation.bean.Red"};
}
}
- 导入
ImportBeanDefinitionRegistrar类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { @Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean b = registry.containsBeanDefinition("com.example.demo.annotation.bean.Color");
boolean b1 = registry.containsBeanDefinition("com.example.demo.annotation.bean.Red");
if (b && b1){
registry.registerBeanDefinition("rainBow",new RootBeanDefinition(RainBow.class));
}
}
}
- 使用spring提供的 FactoryBean
public class ColorFactoryBean implements FactoryBean<Color> {
@Override
public Color getObject() throws Exception {
return new Color();
} @Override
public Class<?> getObjectType() {
return Color.class;
}
} @Bean
ColorFactoryBean colorFactoryBean() {
return new ColorFactoryBean();
}
applicationContext.getBean("colorFactoryBean") 默认获取到的是FactoryBean调用getObject方法返回的对象
要获取FactoryBean本身,需要在id前面加个& (&colorFactoryBean)
当满足某种条件时才注册bean,使用@Conditional
举例:在windows和linux上分别注册不同的bean
@Conditional({WindowsConditional.class})
@Bean("windows")
Person person1() {
return new Person("windows");
}
@Bean("linux")
@Conditional({LinuxConditional.class})
Person person2() {
return new Person("linux");
}
public class WindowsConditional implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
return property.toLowerCase().contains("windows");
}
}
public class LinuxConditional implements Condition {
@Override
public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
Environment environment = conditionContext.getEnvironment();
String property = environment.getProperty("os.name");
return property.toLowerCase().contains("linux");
}
}
bean的生命周期
spring容器管理bean的生命周期:创建--》初始化--》销毁
我们可以自定义初始化和销毁方法,容器在bean进行到当前生命周期时来调用我们自定义的初始化和销毁方法
创建对象:
单实例:在容器启动时创建对象
多实例:在每次获取bean的时候创建对象每个BeanPostProcessor的 postProcessBeforeInitialization 方法会在初始化之前执行
初始化: 对象创建好,调用初始化方法
每个BeanPostProcessor的 postProcessAfterInitialization 方法会在初始化之后执行销毁:
单实例:容器关闭时销毁
多实例:容器会帮助创建这个bean,但不会管理这个bean,所以容器不会调用销毁方法,可以手动调用销毁方法
指定初始化和销毁的方法:
- 在 @Bean注解指定(initMethod = "",destroyMethod = "")
- 通过让bean实现 InitializingBean(定义初始化逻辑) 和 DisposableBean(定义销毁时逻辑)
- 使用JSR250: @PostConstruct (定义初始化逻辑) @PreDestroy(在容器销毁bean之前通知进行清理工作)
bean的后置处理器 BeanPostProcessor,其有如下两个方法,在bean的初始化前后做一些处理:
- postProcessBeforeInitialization:在初始化之前工作
- postProcessAfterInitialization:在初始化之后工作
@Component
public class MyBeanPostProcessor implements BeanPostProcessor {
private final ApplicationContext applicationContext;
public MyBeanPostProcessor(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessBeforeInitialization--->"+beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("postProcessAfterInitialization--->"+beanName);
return bean;
}
}
如果自定义组件想要使用spring容器底层的组件(ApplicationContext,BeanFactory,***),自定义组件可以实现 ***Aware,
在创建bean的时候,相关BeanPostProcessor会调用接口规定的方法注入相关组件
例如:
如果自定义bean 实现了ApplicationContextAware 接口,在ApplicationContextAwareProcessor中会调用ApplicationContextAware的
setApplicationContext方法,注入ApplicationContext组件
spring通过注解注册bean的方式+spring生命周期的更多相关文章
- @Scope注解设置创建bean的方式和生命周期
1.1.1 Scope注解创建bean的方式和生命周期 作用 Scope设置对象在spring容器(IOC容器)中的生命周期,也可以理解为对象在spring容器中的创建方式. 取 ...
- Spring框架系列(三)--Bean的作用域和生命周期
Bean的作用域 Spring应用中,对象实例都是在Container中,负责创建.装配.配置和管理生命周期(new到finalize()) Spring Container分为两种: 1.BeanF ...
- 五 Spring的配置:Bean的配置,生命周期和作用范围
Bean相关的配置: <bean>标签的id和name的配置: id:使用了约束中的唯一约束,里面不能出现特殊字符 name:没有使用唯一约束,理论上可以重复,实际上开发不行,里面可以出现 ...
- 【String注解驱动开发】面试官让我说说:如何使用FactoryBean向Spring容器中注册bean?
写在前面 在前面的文章中,我们知道可以通过多种方式向Spring容器中注册bean.可以使用@Configuration结合@Bean向Spring容器中注册bean:可以按照条件向Spring容器中 ...
- 【String注解驱动开发】如何按照条件向Spring容器中注册bean?这次我懂了!!
写在前面 当bean是单实例,并且没有设置懒加载时,Spring容器启动时,就会实例化bean,并将bean注册到IOC容器中,以后每次从IOC容器中获取bean时,直接返回IOC容器中的bean,不 ...
- spring IOC容器实例化Bean的方式与RequestContextListener应用
spring IOC容器实例化Bean的方式有: singleton 在spring IOC容器中仅存在一个Bean实例,Bean以单实例的方式存在. prototype 每次从容器中调用Bean时, ...
- 在Listener(监听器)定时启动的TimerTask(定时任务)中使用Spring@Service注解的bean
1.有时候在项目中需要定时启动某个任务,对于这个需求,基于JavaEE规范,我们可以使用Listener与TimerTask来实现,代码如下: public class TestTaskListene ...
- Spring中Bean的作用域、生命周期
Bean的作用域.生命周期 Bean的作用域 Spring 3中为Bean定义了5中作用域,分别为singleton(单例).protot ...
- Spring之Bean的作用域与生命周期
在前面博客中提到容器启动获得BeanDefinition对象中有一个scope 属性.该属性控制着bean对象的作用域.本章节介绍Bean的作用域及生命周期,了解bean是怎么来的又怎么没的. 一.B ...
随机推荐
- pycharm中的terminal和Windows命令提示符有什么区别?二者用pip安装的包是不是位于相同位置?
那要看pycharm使用了什么shell,可以在设置->工具->终端里查看shell path.如果使用的是cmd.exe那就没区别.pycharm终端和Windows命令提示符用pip安 ...
- Egg.js学习与实战系列 · 文件上传配置
在使用Egg.js搭建文件上传服务时,遇到了几个一般新手都会遇到的坑. 经查阅官方文档,Egg框架中默认使用egg-multipart插件进行文件上传,所以上传文件前需要做相关的配置. 上传文件提示: ...
- spring security整合QQ登录
最近在了解第三方登录的内容,尝试对接了一下QQ登录,此次记录一下如何实现QQ登录的过程,在这个例子中是和spring secuirty整合的,不整合spring secuirty也是一样的. 需求: ...
- FastAPI 学习之路(三十三)操作数据库
通过创建pydantic模型进行验证提交数据 from pydantic import BaseModel class UserBase(BaseModel): email: str class Us ...
- Noip模拟15 2021.7.14
T1 夜莺与玫瑰 题目越发的变态起来... 这题刚开始看超级像仪仗队,好不容易码完欧拉函数后尝试×2后输出但不对!! 于是选择了跳过.... 正解居然是莫比乌斯函数....我也是醉了 预处理完就剩下$ ...
- C语言中都有哪些常见的数据结构你都知道几个?
上次在面试时被面试官问到学了哪些数据结构,那时简单答了栈.队列/(ㄒoㄒ)/~~其它就都想不起来了,今天有空整理了一下几种常见的数据结构,原来我们学过的数据结构有这么多~ 首先,先来回顾下C语言中常见 ...
- reactnative实现qq聊天消息气泡拖拽消失效果
前言(可跳过) 我在开发自己的APP时遇到了一个类似于qq聊天消息气泡拖拽消息的需求,因为在网上没有找到相关的组件,所以自己动手实现了一下 需求:对聊天消息气泡拖拽到一定长度松开时该气泡会消失(可自行 ...
- sum-root-to-leaf-numbers leetcode C++
Given a binary tree containing digits from0-9only, each root-to-leaf path could represent a number. ...
- IM服务器:开发一个高并发的IM服务器难在哪
IM服务器要实现的最基本功能就是消息的转发.--好像是一句废话! 这就意味着IM服务器要为每个登录用户创建一个与该用户信息相关的内存上下文,为方便描述我们在这里称之为:user_context.use ...
- go defer、return的执行顺序
一.一个函数中多个defer的执行顺序 defer 的作用就是把defer关键字之后的函数执行压入一个栈中延迟执行,多个defer的执行顺序是后进先出LIFO,也就是先执行最后一个defer,最后执行 ...