SpringBoot八种bean的加载方式
目录
第一种bean的加载方式-配置文件
第二种加载bean方式-注解和扫描
创建第三方的bean对象
第三种加载bean方式-不使用配置文件
扩展-bean的加载方式扩展FactoryBean<>
扩展-@ImportResource导入配置文件
扩展-proxyBeanMethods属性-产生代理对象
第四种加载bean方式-使用@Import
第五种加载bean方式-registerBean
第六种加载bean方式-实现ImportSelector接口
第七种加载bean方式-实现ImportBeanDefinitionRegistrar
第八种bean的加载方式-实现BeanDefinitionRegistryPostProcessor
实现bean的方式总结
第一种bean的加载方式-配置文件
先创建一个使用maven的spring工程
导入spring核心配置
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.9</version></dependency>
创建一个类
public class Cat {}
public class Dog {
}
创建一个名为applicationContext.xml的配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="cat" class="com.service.Cat"/>
<bean id="dog" class="com.service.Dog"/></beans>
创建一个启动类
package com.app;import com.service.Dog;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App1 {public static void main(String[] args) {ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");Object cat = app.getBean("cat");//根据id获取System.out.println(cat);Object dog = app.getBean(Dog.class);//根据类获取,当不唯一时会报错System.out.println(dog);}
}
运行结果,这样就可以得到bean的对象了
或者使用可以使用一次性获取所有bean
public class App1 {public static void main(String[] args) {ApplicationContext app=new ClassPathXmlApplicationContext("applicationContext.xml");String[] names = app.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}}
}
运行结果
第二种加载bean方式-注解和扫描
使用注解,注解的作用就是替代配置文件的配置,注解有@Component @Service @Repository等
替换配置文件中的<bean id= class=..>
@Component("cat") //起的名
public class Cat {}
@Component
public class Dog {
}
使用完注解还得让spring去扫描到这个注解,在配置文件中的写
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:context="http://www.springframework.org/schema/context"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!--告诉spring扫描哪个包component导入context命名空间--><context:component-scan base-package="com"/></beans>
运行结果
创建第三方的bean对象
先导入对应的坐标
<dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1.24</version></dependency>
创建一个类,返回你需要导入的对象即可,加入注解
package com.config;import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;@Component
public class DBconfig {@Beanpublic DruidDataSource dataSource(){DruidDataSource ds =new DruidDataSource();return ds;}
}
运行结果
第三种加载bean方式-不使用配置文件
创建一个类代替配置文件
package com.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;@Configuration//定义为配置类
@ComponentScan({"com.config","com.service"}) //注解扫描包
public class springConfig {
}
运行类也得修改
package com.app;import com.config.springConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App2 {public static void main(String[] args) {
ApplicationContext app=new AnnotationConfigApplicationContext(springConfig.class);String[] names = app.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}}
}
运行结果
扩展-bean的加载方式扩展FactoryBean<>
初始化实现FactoryBean<>接口的类,实现对bean加载到容器之前的批处理操作。
实现了FactoryBean接口创建出来的对象不是本身而是里面的泛型。
创建一个类实现接口
package com.config;import com.service.Dog;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.context.annotation.Bean;public class DogFactoryBean implements FactoryBean<Dog> {public Dog getObject() throws Exception {return new Dog();}
//返回对象的类型public Class<?> getObjectType() {//这里可以做一系列的初始化工作return Dog.class;}//是否是单例,单例则多次获取都是一个对象public boolean isSingleton() {return false;}
}
@Component
public class Dog {
}
启动的主类
import com.config.springConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class App2 {public static void main(String[] args) {
ApplicationContext app=new AnnotationConfigApplicationContext(springConfig.class);String[] names = app.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}System.out.println(app.getBean("dog1"));System.out.println(app.getBean("dog1"));}
}
运行结果
产生的是泛型的对象
扩展-@ImportResource导入配置文件
看源码可知道,可以写入多个string类型的数组,使用{}
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
@Configuration
@ComponentScan("com")
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
public class SpringConfig2 {@Beanpublic Cat cat(){return new Cat();}
}
两个配置文件中的bean,排在前面的首先加载,后面的之后加载,同的内容以之后的为主,不同的内容都加载。
扩展-proxyBeanMethods属性-产生代理对象
@Configuration注解中有一属性proxyBeanMethod属性,默认值是true
值为false时
@Configuration(proxyBeanMethods = false)
@ComponentScan("com")
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
public class SpringConfig2 {@Beanpublic Cat cat(){return new Cat();}
}
主方法中
public class app3 {public static void main(String[] args) {ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfig2.class);String[] names = app.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}System.out.println("--------");System.out.println(app.getBean("springConfig2"));SpringConfig2 springConfig2 = app.getBean("springConfig2", SpringConfig2.class);System.out.println(springConfig2.cat());System.out.println(springConfig2.cat());System.out.println(springConfig2.cat());}
}
运行结果
产生的是普通对象,每一次调用方法都会new一个新的对象前提是这个方法是被bean管理的对象。
值为true时
不写或写true时
@Configuration(proxyBeanMethods = true)
@ComponentScan("com")
@ImportResource({"applicationContext2.xml","applicationContext.xml"})
public class SpringConfig2 {@Beanpublic Cat cat(){return new Cat();}
}
运行结果
会产生一个代理对象,这个代理对象让我们每次调用方法是都是同一个,前提也是需要被bean容器管理
注:产生的bean对象没指定名称时,默认是方法名或类名首字母小写,如类名是SpringTest则产生的bean是springTest
第四种加载bean方式-使用@Import
翻看@Import源码可知,需要一个类class字节码对象
在类中
import com.service.TestBean1;
import com.service.TestBean2;
import org.springframework.context.annotation.Import;@Import({TestBean1.class, TestBean2.class})
public class springConfig4 {
}
创建测试的类
public class TestBean1 {
}
public class testBean2 {
}
主类上
public class app4 {public static void main(String[] args) {ApplicationContext app=new AnnotationConfigApplicationContext(springConfig4.class);String[] names = app.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}}
}
运行结果
全路径名,加入的类即使没有被spring管理也可以产生bean。
第五种加载bean方式-registerBean
使用上下文对象在容器初始化后注入bean
在创建完上下文对象的时候可以加载bean
只能使用 AnnotationConfigApplicationContext获取上下文对象
public class app5 {public static void main(String[] args) {AnnotationConfigApplicationContext app=new AnnotationConfigApplicationContext(springConfig5.class);//加载完成后app.registerBean("CaiDog", Dog.class,1 );app.registerBean("CaiDog", Dog.class,2);app.registerBean("CaiDog", Dog.class,3 );String[] names = app.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}System.out.println("------");System.out.println(app.getBean(Dog.class));}
}
Dog类下
@Component
public class Dog {int age;public Dog(){}public Dog(int age){this.age=age;}@Overridepublic String toString() {return "Dog{" +"age=" + age +'}';}
}
运行结果 ,当有多个的时候,且bean的名字一致时,以最后的为准。
或者直接使用
app.register(Cat.class);
也可以快速的加载一个bean
第六种加载bean方式-实现ImportSelector接口
这个接口有许多方法用来判定
导入实现了ImportSelector接口的类,实现对导入源的编程式处理
public class MyImportSelector implements ImportSelector {public String[] selectImports(AnnotationMetadata annotationMetadata) {//AnnotationMetadata 注解的源数据// 做判定条件,是否有这个注解boolean flag = annotationMetadata.hasAnnotation("org.springframework.context.annotation.Configuration");if (flag){return new String[]{"com.service.Dog"};}return new String[]{"com.service.Cat"};}
}
@Import({MyImportSelector.class})
public class SpringConfig6 {
}
public class app6 {public static void main(String[] args) {ApplicationContext app=new AnnotationConfigApplicationContext(SpringConfig6.class);String[] names = app.getBeanDefinitionNames();for (String name : names) {System.out.println(name);}}
}
运行结果
第七种加载bean方式-实现ImportBeanDefinitionRegistrar
导入实现ImportBeanDefinitionRegistrar接口的类,通过BeanDefinition的注册器注册实名bean,实现对容器中bean的决定,例如对现有的bean的覆盖,进而达到
import com.service.Dog;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
public class MyRegistrar implements ImportBeanDefinitionRegistrar {public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {BeanDefinition beanDefinition= BeanDefinitionBuilder.rootBeanDefinition(Dog.class).getBeanDefinition();registry.registerBeanDefinition("woDog", beanDefinition);}
}
@Import({MyRegistrar.class})
public class SpringConfig7 {
}
运行结果
第八种bean的加载方式-实现BeanDefinitionRegistryPostProcessor
导入实现了BeanDefinitionRegistryPostProcessor接口的类,通过BeanDefintion的注册器注册实名bean,实现对容器中bean的最终裁定.(以这个接口加载的bean为主)
@Component
public class DBconfig {@Beanpublic DruidDataSource dataSource(){DruidDataSource ds =new DruidDataSource();return ds;}
}
public class MyPostProcessor implements BeanDefinitionRegistryPostProcessor {public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(DBconfig.class).getBeanDefinition();registry.registerBeanDefinition("dataSource",beanDefinition);}public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {}
}
@Import({MyPostProcessor.class})
public class SpringConfig8 {
}
运行结果
实现bean的方式总结
1.xml+<bean/>
2.xml:context+注解(@Component+4个@Bean
3.配置类+扫描+注解(@Component+4个@Bean)
- @Bean定义FactoryBean接口
- @ImportResource
- @Configuration注解的proxyBeanMethods属性
4.@Import导入bean的类
- @Import导入配置类
5.AnnotationConfigApplicationContext调用register方法
6.@Import导入ImportSelector接口
7.@Import导入ImportBeanDefinitionRegistrar接口
8.@Import导入BeanDefinitionRegistryPostProcessor接口
SpringBoot八种bean的加载方式相关推荐
- 【uniapp】 两种上拉加载方式
1.直接动用声明周期 需要先在pack.json中配置位置 然后在页面中 配合声明周期使用 export default {data() {return {content_detailList: [{ ...
- HBase的协处理器(Coprocessor)、HBase如何使用二级索引、observer协处理器、 endpoint协处理器、Hbase 协处理器加载方式
HBase的协处理器(Coprocessor).HBase不可以使用二级索引吗? 起源 Hbase 作为列族数据库最经常被人诟病的特性包括: 无法轻易建立"二级索引" 难以执 行求 ...
- java懒加载注解_在springboot中实现个别bean懒加载的操作
懒加载---就是我们在spring容器启动的是先不把所有的bean都加载到spring的容器中去,而是在当需要用的时候,才把这个对象实例化到容器中. @Lazy 在需要懒加载的bean上加上@Lazy ...
- SpringBoot如何正确控制bean的加载顺序
1. 为什么需要控制bean的加载顺序 springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题.在此基础上,又提供了SPI[Service Provider Interface]机 ...
- 如何正确控制springboot中bean的加载顺序总结
1.为什么需要控制加载顺序 springboot遵从约定大于配置的原则,极大程度的解决了配置繁琐的问题.在此基础上,又提供了spi机制,用spring.factories可以完成一个小组件的自动装配功 ...
- Springboot之Bean的加载过程
加载和实例化bean分以下几个重要步骤: 1.根据package扫描出需要被管理的类 2.将这些类封装成BeanDefinition并注册到BeanFactory容器 3.实例化所有扫描到的BeanD ...
- hive--udf函数(开发-4种加载方式)
UDF函数开发 标准函数(UDF):以一行数据中的一列或者多列数据作为参数然后返回解雇欧式一个值的函数,同样也可以返回一个复杂的对象,例如array,map,struct. 聚合函数(UDAF):接受 ...
- 动态链接库dll的两种加载方式
在第一篇技术博客"动态链接库简介"中说到了两种加载方式,当时没有详细说明,这里详细说明一下 可以通过两种方式 1.隐式链接(需要.dll,.lib,.h) 2.显式链接(需要.dl ...
- 这两种完全不同的JPEG加载方式,你肯定见过!
现如今网站所使用的的图片格式多种多样,但是有一种图片格式占到了 74% 的使用量.它就是 JPEG,即联合图像专家组.这类文件的后缀通常为 .jpg 或 .jpeg,是摄影中常见的图片类型. JPEG ...
最新文章
- [OS复习]虚拟存储管理技术 1
- 数据库SQL语言从入门到精通--Part 4--SQL语言中的模式、基本表、视图
- idea gui插件_给 IDEA 换了酷炫的主题,研发小姐姐看到:feel so high。。。
- 一文玩转 EhCache 缓存框架!
- 数据库扩容 mysql_mysql数据库怎么扩容
- maven安装的详细步骤
- 起床困难综合症(位运算)
- Git--分布式版本控制系统
- 压力测试中需要掌握的几个基本概念
- Alex Chen:3月21日阿里云北京峰会演讲大神
- Java开发人员简历做假的常见情况
- 帆软报表(多sheet)自定义分页查询
- mysql pdf教程_MySQL5.7从入门到精通(刘增杰 著)带书签完整版PDF[230MB]
- 量化视角下的基金定投策略
- DLP和DMD的区别
- html5模仿手机音乐播放器(添加音乐进度条和时长)
- linux echo命令做运算,linux常用计算命令
- 用ubuntu的使用习惯使用windows (by quqi99)
- 【杰理AC695X】7脚屏PWM控制亮度
- message:Error app.json app.json 未找到 public
热门文章
- 幽门螺杆菌检测方法学习笔记
- OnDraw和OnPaint函数的区别
- NYOJ 952 最大四边形 (n个点求组成四边形的最大面积)
- elementui表格宽度自适应
- 关于qq第三方登录一些问题!无法获取信息等等
- Java 代码实现阿姆斯特朗炮的原理
- Dart 入门学习(5)—— Numbers(数值)
- How can you determine how much disk space a particular MySQL table is taking up?
- Python变量和数据类型,类型转换
- Java项目:房屋销售管理系统(java+SSM+JSP+jQuery+Mysql)