Spring中注册Bean的方式有哪些?
目录
一、概述
二、第一种方式: XML配置方式
三、第二种方式: 使用@Component注解 + @ComponentScan包扫描方式
四、第三种方式:@Configuration + @Bean方式
五、第四种方式:FactoryBean方式
六、第五种方式:@Import方式
七、第六种方式:@Import + ImportSelector方式
八、第七种方式:@Import + ImportBeanDefinitionRegistrar方式
九、第八种方式:BeanDefinitionRegistryPostProcessor方式
十、第九种方式:BeanFactoryPostProcessor方式
一、概述
我们知道,在使用Spring框架后,Bean统一都交给IOC容器去管理和创建,那么将一个对象加入到Spring容器中有哪些方式呢,今天我们结合具体的代码来总结一下。
二、第一种方式: XML配置方式
XML配置的方式,是Spring最早支持的方式,不过现在XML方式已经用的比较少了,基本上都是用后面的配置方式替代了。
public class Student {
}<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="student" class="com.wsh.injectbean.method_01.Student"/>
</beans>/*** 第一种方式: XML文件配置*/
public class Client {public static void main(String[] args) {ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("classpath:spring-config.xml");System.out.println(applicationContext.getBean("student"));}
}
三、第二种方式: 使用@Component注解 + @ComponentScan包扫描方式
为了解决bean太多时,XML文件过大,从而导致膨胀不好维护的问题。在Spring2.5中开始支持:@Component、@Repository、@Service、@Controller等注解定义bean。@Component放在类名上面,然后通过@ComponentScan指定一个路径,Spring进行扫描带有@Componet注解的bean,然后加至容器中。
注意,这种方式不单单指的是@Component注解,还包括@Controler、@Service、@Repository等派生的注解。
具体代码如下:
@Component
public class UserHandler {
}@Service
public class UserService {
}@Repository
public class UserDao {
}@Controller
public class UserController {
}@ComponentScan("com.wsh.injectbean.method_02")
@Configuration
public class AppConfig {
}/*** 第二种方式: 使用@Component注解 + @ComponentScan包扫描方式* 包括@Controler、@Service、@Repository等派生的注解。* 为了解决bean太多时,xml文件过大,从而导致膨胀不好维护的问题。在spring2.5中开始支持:@Component、@Repository、@Service、@Controller等注解定义bean。* 其实本质上@Controler、@Service、@Repository也是使用@Component注解修饰的。* <p>* 通常情况下:** @Controller:一般用在控制层* @Service:一般用在业务层* @Repository:一般用在持久层* @Component:一般用在公共组件上*/
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);System.out.println(applicationContext.getBean("userDao"));System.out.println(applicationContext.getBean("userService"));System.out.println(applicationContext.getBean("userController"));System.out.println(applicationContext.getBean("userHandler"));}
}
四、第三种方式:@Configuration + @Bean方式
这种方式其实也是我们最常用的方式之一,@Configuration用来声明一个配置类,然后使用 @Bean 注解声明一个bean,将其加入到Spring容器中。通常情况下,如果项目中有使用到第三方类库中的工具类的话,我们都是采用这种方式注册Bean。
具体代码如下:
public class Student {
}@Configuration
public class AppConfig {@Beanpublic Student student() {return new Student();}}/*** 第三种方式:@Configuration + @Bean方式* <p>* 通常情况下,如果项目中有使用到第三方类库中的工具类的话,我们都是采用这种方式注册Bean*/
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);System.out.println(applicationContext.getBean("student"));}
}
五、第四种方式:FactoryBean方式
FactoryBean是一个Bean,它允许我们自定义Bean的创建,主要有三个方法:
- 1、getObject():自定义Bean如何创建;
- 2、getObjectType():要注册的Bean的类型;
- 3、isSingleton():是否单例;
public class User {
}@Component
public class UserFactoryBean implements FactoryBean<User> {@Overridepublic User getObject() throws Exception {return new User();}@Overridepublic Class<?> getObjectType() {return User.class;}@Overridepublic boolean isSingleton() {return true;}
}@Configuration
@ComponentScan("com.wsh.injectbean.method_04")
public class AppConfig {}/*** 第四种方式:使用FactoryBean** FactoryBean在一些框架整合上用的比较多,如Mybatis与Spring的整合中:MapperFactoryBean、SqlSessionFactoryBean等*/
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);System.out.println(applicationContext.getBean("userFactoryBean"));System.out.println(applicationContext.getBean("&userFactoryBean"));}
}
六、第五种方式:@Import方式
public class Student {
}@Import({Student.class})
@Configuration
public class AppConfig {}/*** 第五种方式:@Import方式*/
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}System.out.println("================");System.out.println(applicationContext.getBean("com.wsh.injectbean.method_05.Student"));System.out.println(applicationContext.getBean("student"));}
}
七、第六种方式:@Import + ImportSelector方式
首先介绍一下ImportSelector接口的好处,主要有以下两点:
- 1、把某个功能的相关类放到一起,方面管理和维护。
- 2、重写selectImports方法时,能够根据条件判断某些类是否需要被实例化,或者某个条件实例化这些bean,其他的条件实例化那些bean等,我们能够非常灵活的定制化bean的实例化。
这种方式我们需要实现ImportSelector接口,并重写selectImports()方法,然后将我们要导入的类的全限定名写在里面即可。
指定需要定义bean的类名,注意要包含完整路径,而非相对路径。
public class Product {
}public class User {
}public class MyImportSelector implements ImportSelector {// 指定需要定义bean的类名,注意要包含完整路径,而非相对路径@Overridepublic String[] selectImports(AnnotationMetadata importingClassMetadata) {return new String[]{"com.wsh.injectbean.method_06.Product", "com.wsh.injectbean.method_06.User"};}}@Import({MyImportSelector.class})
@Configuration
public class AppConfig {}/*** 第六种方式:@Import + ImportSelector方式* <p>* ImportSelector接口的好处主要有以下两点:* <p>* 1.把某个功能的相关类放到一起,方面管理和维护。* 2.重写selectImports方法时,能够根据条件判断某些类是否需要被实例化,或者某个条件实例化这些bean,其他的条件实例化那些bean等,我们能够非常灵活的定制化bean的实例化。*/
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {System.out.println(beanDefinitionName);}System.out.println("================");System.out.println(applicationContext.getBean("com.wsh.injectbean.method_06.Product"));try {System.out.println(applicationContext.getBean("product"));} catch (Exception e) {e.printStackTrace();}System.out.println("================");System.out.println(applicationContext.getBean("com.wsh.injectbean.method_06.User"));try {System.out.println(applicationContext.getBean("user"));} catch (Exception e) {e.printStackTrace();}}
}
八、第七种方式:@Import + ImportBeanDefinitionRegistrar方式
这种方式我们需要实现ImportBeanDefinitionRegistrar接口,并重写registerBeanDefinitions()方法,然后定义我们需要注册的Bean的定义信息,然后registry.registerBeanDefinition()方法注册即可。这种方式比ImportSelector更加灵活,可以自定义bean的名称、作用域等很多参数。 像我们常见的Spring Cloud中的Feign,就使用了ImportBeanDefinitionRegistrar,具体可以参考FeignClientsRegistrar类。
public class User {
}public class Product {
}public class CustomImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {@Overridepublic void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {// 可以自定义bean的名称、作用域等很多参数registry.registerBeanDefinition("user", new RootBeanDefinition(User.class));RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Product.class);rootBeanDefinition.setScope(BeanDefinition.SCOPE_SINGLETON);registry.registerBeanDefinition("product", rootBeanDefinition);}
}@Import({CustomImportBeanDefinitionRegistrar.class})
@Configuration
public class AppConfig {}/*** 第七种方式:@Import + ImportBeanDefinitionRegistrar方式** 可以自定义bean的名称、作用域等很多参数, 像我们常见的Spring Cloud中的Feign,就使用了ImportBeanDefinitionRegistrar* class FeignClientsRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware, EnvironmentAware {* public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {* this.registerDefaultConfiguration(metadata, registry);* this.registerFeignClients(metadata, registry);* }* }*/
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);System.out.println(applicationContext.getBean("product"));System.out.println(applicationContext.getBean("user"));}
}
九、第八种方式:BeanDefinitionRegistryPostProcessor方式
在Spring容器启动方法refresh()方法的invokeBeanFactoryPostProcessors()方法中,会执行 BeanDefinitionRegistryPostProcessor 的 postProcessBeanDefinitionRegistry()方法,它允许对beanDefinition进行后置处理,我们可以在这个方法调整IOC容器中的beanDefinition定义信息,从而干扰到后面bean初始化的过程。
具体代码如下:
public class User {
}@Component
public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {@Overridepublic void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {registry.registerBeanDefinition("user", new RootBeanDefinition(User.class));}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}@Configuration
@ComponentScan("com.wsh.injectbean.method_08")
public class AppConfig {}/*** 第八种方式:BeanDefinitionRegistryPostProcessor方式*/
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);System.out.println(applicationContext.getBean("user"));}
}
十、第九种方式:BeanFactoryPostProcessor方式
其实BeanDefinitionRegistryPostProcessor就是继承自BeanFactoryPostProcessor,所以使用BeanFactoryPostProcessor也可以实现注册Bean的功能。它们的区别如下:
- 1、 BeanDefinitionRegistryPostProcessor:侧重于bean的注册;
- 2、 BeanFactoryPostProcessor:侧重于对已经注册的bean的属性进行修改,虽然也可以注册bean;
public class Product {
}@Component
public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor {@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {DefaultListableBeanFactory registry = (DefaultListableBeanFactory) beanFactory;registry.registerBeanDefinition("product", new RootBeanDefinition(Product.class));}
}@Configuration
@ComponentScan("com.wsh.injectbean.method_09")
public class AppConfig {}/*** 第九种方式:BeanFactoryPostProcessor方式* <p>* 1. BeanDefinitionRegistryPostProcessor: 侧重于bean的注册;* 2. BeanFactoryPostProcessor:侧重于对已经注册的bean的属性进行修改,虽然也可以注册bean;*/
public class Client {public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(AppConfig.class);System.out.println(applicationContext.getBean("product"));}
}
本篇文章主要介绍了Spring中九种注册Bean的方式,大家在实际项目中,根据具体的需求,选择合适的即可。
Spring中注册Bean的方式有哪些?相关推荐
- Spring中获取bean的方式
1. 获取bean 在上图的测试类中我们是通过id来获取bean的.实际上获取bean的方式有很多种,下面我们就一一说明. 1.1 方式一:根据id获取 由于 id 属性指定了 bean 的唯一标识, ...
- 【小家Spring】Spring注解驱动开发---向Spring Ioc容器中注册Bean的7种方式
每篇一句 比你有钱的人一定会比你努力,而比你努力的人终有一天会比你有钱 前言 Spring是一个非常强大的反转控制(IOC)框架,以帮助分离项目组件之间的依赖关系.因此可以说Spring容器对Bean ...
- Spring注解驱动开发第11讲——面试官让我说说:如何使用FactoryBean向Spring容器中注册bean?
写在前面 经过前面的学习,我们知道可以通过多种方式向Spring容器中注册bean.可以使用@Configuration注解结合@Bean注解向Spring容器中注册bean:可以按照条件向Sprin ...
- Spring注解驱动开发第10讲——在@Import注解中使用ImportBeanDefinitionRegistrar向容器中注册bean
写在前面 在前面的文章中,我们学习了如何使用@Import注解向Spring容器中导入bean,不仅可以使用@Import注解快速向容器中导入bean,也可以在@Import注解中使用ImportSe ...
- Spring注解驱动开发第7讲——如何按照条件向Spring容器中注册bean?这次我懂了!!
写在前面 当bean是单实例,并且没有设置懒加载时,Spring容器启动时,就会实例化bean,并将bean注册到IOC容器中,以后每次从IOC容器中获取bean时,直接返回IOC容器中的bean,而 ...
- 详细讲解Spring中的@Bean注解
点击关注公众号,实用技术文章及时了解 来源:blog.csdn.net/weixin_42140261/ article/details/104864333 随着SpringBoot的流行,我们现在更 ...
- Spring 中的bean 是线程安全的吗?
点击上方蓝色"方志朋",选择"设为星标" 回复"666"获取独家整理的学习资料! 作者:myseries cnblogs.com/myser ...
- ImportBeanDefinitionRegistrar向容器中注册bean
一.ImportBeanDefinitionRegistrar 我们先来看看ImportBeanDefinitionRegistrar是个什么鬼,点击进入ImportBeanDefinitionReg ...
- Spring中的Bean配置、属性配置、装配内容详细叙述
文章目录 1.Bean的配置 1.1.配置方式 2.Bean的实例化 2.1.构造器实例化 2.2.静态工厂方式实例化 2.3.实例工厂方式实例化 3.Bean的作用域 3.1.作用域的种类 4.Be ...
- spring扩展点之二:spring中关于bean初始化、销毁等使用汇总,ApplicationContextAware将ApplicationContext注入...
<spring扩展点之二:spring中关于bean初始化.销毁等使用汇总,ApplicationContextAware将ApplicationContext注入> <spring ...
最新文章
- 机器学习误差分析(Error Analysis)实战
- poj2186 求有向图G中所有点都能到达的点的数量
- Mybatis-Plus基本
- java 使用jasper_使用Jasper Reports以Java创建报告
- CSS3 FlexBox布局入门简析
- openglshader实现虚拟场景_虚拟演播室设计原则
- DotNetNuke 4/5 安装提示 msajax错误,下载AJAX 1.0即可解决
- php生成文章页,php结合smarty生成静态页面php文章内分页代码
- 请问客户端PC应该如何限制其自动获取IP地址?
- 淘宝爬取某人的所有购物订单
- sever client
- Atitit.部分错误 设计模式,异常处理框架atiPartErr 的总结
- BoundsChecker的使用
- 中国武打明星——杨丽菁的故事
- Java中的数据类型
- 郭霖的LitePal版本历程
- svn上文件符号的意思
- 简单三步实现给公众号添加附件
- 数据仓库之主题模型之IBM与TD金融模型
- 苹果xr如何截屏_iphone敲两下截屏如何操作 苹果手机触控截屏方法【教程步骤】...
热门文章
- 翻译:自动驾驶相关术语的分类和定义Taxonomy and Definitions for Terms Related to On-Road Motor Vehicle Automated
- 阿里云云计算 33 PolarDB的优势 产品架构
- 阿里云云计算 11 ECS初体验-- 动手实验
- 翻译:Google研究:回顾2020年并展望2021年 - Jeff Dean
- iOS网络请求架构图URL Loading System
- 正态分布下贝叶斯决策的特例(二)
- php_eol为什么没有换行,PHP PHP_EOL 换行符
- Leetcode-Implement strStr()-Python
- 图解Python机器学习pdf 中日双语 第1页
- 357.计算各个位数不同的数字个数