0


SpringBoot基础(四):bean的多种加载方式

SpringBoot基础系列文章

SpringBoot基础(一):快速入门

SpringBoot基础(二):配置文件详解

SpringBoot基础(三):Logback日志

SpringBoot基础(四):bean的多种加载方式


目录

一、xml配置文件

配置文件spring-bean.xml

<?xml version="1.0" encoding="UTF-8"?><beansxmlns="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"><!--xml方式声明自己开发的bean--><beanid="person"class="com.xc.entity.Person"/><beanclass="com.xc.entity.Person"/><beanclass="com.xc.entity.Person"/><!--xml方式声明第三方开发的bean--><beanid="dataSource"class="com.alibaba.druid.pool.DruidDataSource"/></beans>

加载xml

publicclassApp{publicstaticvoidmain(String[] args){ClassPathXmlApplicationContext context =newClassPathXmlApplicationContext("spring-bean.xml");for(String beanDefinitionName : context.getBeanDefinitionNames()){System.out.println(beanDefinitionName);}}}

输出结果:

person
com.xc.entity.Person#0com.xc.entity.Person#1
dataSource

二、注解定义bean

1、使用AnnotationConfigApplicationContext对象加载

publicclassApp{publicstaticvoidmain(String[] args){AnnotationConfigApplicationContext context =newAnnotationConfigApplicationContext(MyConfig.class);for(String beanDefinitionName : context.getBeanDefinitionNames()){System.err.println(beanDefinitionName);}}}
publicclassMyConfig{}

**使用

AnnotationConfigApplicationContext

对象加载MyConfig,即使MyConfig类什么注解没有,也会被注册为bean。**

2、加载本地类

  • 使用的注解@Component或其他衍生注解@Service@Controller@Repository
@ServicepublicclassBookServiceImplimplementsBookService{}

3、加载第三方jar类

**由于我们无法在第三方提供的技术源代码中去添加上述4个注解,因此当你需要

加载第三方开发的bean

的时候可以使用

@Component

@Configuration

都可以,一般引入第三方倾向于后者。**

//@Component@ConfigurationpublicclassDbConfig{@BeanpublicDruidDataSourcedataSource(){returnnewDruidDataSource();}@BeanpublicCatcat(){Cat cat =newCat();
        cat.setDruidDataSource(dataSource());return cat;}}
  • @Configuration(proxyBeanMethods = true):默认设置,使用了cglib动态代理,cat里的dataSource和@Bean创建的dataSource是同一个对象,可以理解为单例
  • @Configuration(proxyBeanMethods = false):此时和@Component注解功能一样,cat里的dataSource和@Bean创建的dataSource不是同一个对象,可以理解为多例
  • 如果配置中@Bean标识的方法之间不存在依赖调用的话,可以设置为false,可以避免拦截方法进行代理操作,提升性能

三、特殊方式

1、使用FactroyBean接口

  • spring提供了一个接口FactoryBean,也可以用于声明bean
  • 实现了FactoryBean接口的类造出来的对象不是当前类的对象,而是FactoryBean接口泛型指定类型的对象
  • 一般用来创建复杂对象
publicclassDogFactoryBeanimplementsFactoryBean<Dog>{//创建bean的复杂过程@OverridepublicDoggetObject()throwsException{Dog d =newDog();//.........return d;}//bean的类型@OverridepublicClass<?>getObjectType(){returnDog.class;}//bean是否单例@OverridepublicbooleanisSingleton(){returntrue;}}

配置类

publicclassMyConfig{@BeanpublicDogFactoryBeandog(){returnnewDogFactoryBean();}}

启动类

publicclassApp{publicstaticvoidmain(String[] args){AnnotationConfigApplicationContext context =newAnnotationConfigApplicationContext(MyConfig.class);System.out.println(context.getBean("dog"));}}

3.2、注解导入XML格式配置的bean

  • 场景:旧项目xml配置bean融入配置类项目中
  • @ImportResource在配置类上直接写上要被融合的xml配置文件名即可
@Configuration@ImportResource(locations ="spring-bean.xml")publicclassSpringConfig{}

3.3、通过上下文ApplicationContext注册bean

  • 在容器初始化完成后手动加载bean,创建方式很多

在这里插入图片描述

方式一:无参构造

publicclassApp{publicstaticvoidmain(String[] args){AnnotationConfigApplicationContext ctx =newAnnotationConfigApplicationContext(SpringConfig.class);//上下文容器对象已经初始化完毕后,手工加载bean
        ctx.register(Mouse.class);}}

方式二:多参构造

publicclassApp{publicstaticvoidmain(String[] args){AnnotationConfigApplicationContext ctx =newAnnotationConfigApplicationContext(SpringConfig.class);//上下文容器对象已经初始化完毕后,手工加载bean
        ctx.registerBean("tom",Cat.class,"花猫",3);}}

四、@Import注解注入bean

1、@Import导入普通类

  • 场景:将一个无任何注解的类加载为bean
  • 一个类@Improt只能用一次,想要导入多个使用{…,…}
  • 只有MyConfig加载为bean,@Import才生效
@Configuration//@Import(Pig.class)@Import({Dog.class,Cat.class})publicclassMyConfig{}
publicclassApp{publicstaticvoidmain(String[] args){AnnotationConfigApplicationContext context =newAnnotationConfigApplicationContext(MyConfig.class);for(String beanDefinitionName : context.getBeanDefinitionNames()){System.err.println(beanDefinitionName);}}}

输出结果:

myConfig
com.xc.springboot.bean.Dogcom.xc.springboot.bean.Cat

2、@Import导入实现了ImportSelector接口的类

  • 可以通过添加判断语句就可以实现对bean的加载控制
  • 返回值为多个全路径类名字符串
  • metadata为@Import注解类的元数据,可以拿到MyConfig类上所有的注解,注解里的属性,继承的接口,父类等等信息
  • 如下则是判断MyCofig类上有@Configuration注解则加载Dog类,否则加载Cat类
publicclassMyImportSelectorimplementsImportSelector{@OverridepublicString[]selectImports(AnnotationMetadata metadata){System.out.println("元数据Class名称:"+ metadata.getClassName());//各种条件的判定,判定完毕后,决定是否装载指定的beanboolean flag = metadata.hasAnnotation("org.springframework.context.annotation.Configuration");if(flag){returnnewString[]{"com.xc.springboot.bean.Dog"};}returnnewString[]{"com.xc.springboot.bean.Cat"};}}

配置类

@Configuration@Import(MyImportSelector.class)publicclassMyConfig{}

启动类

publicclassApp{publicstaticvoidmain(String[] args){AnnotationConfigApplicationContext context =newAnnotationConfigApplicationContext(MyConfig.class);for(String beanDefinitionName : context.getBeanDefinitionNames()){System.err.println(beanDefinitionName);}}}

输出结果:

元数据Class名称:com.xc.springboot.bean.MyConfig
myConfig
com.xc.springboot.bean.Dog

3、@Import导入实现了ImportBeanDefinitionRegistrar接口的类

  • 返回值为void,通过Bean定义(beanDefinition)注册创建新的bean
  • 同样可以通过添加判断语句就可以实现bean的加载控制,更加细粒度判断bean
publicclassMyRegistrarimplementsImportBeanDefinitionRegistrar{@OverridepublicvoidregisterBeanDefinitions(AnnotationMetadata metadata,BeanDefinitionRegistry registry){BeanDefinition beanDefinition =BeanDefinitionBuilder.rootBeanDefinition(BookService.class).getBeanDefinition();
        registry.registerBeanDefinition("bookService",beanDefinition);}}

4、@Import导入实现了BeanDefinitionRegistryPostProcessor接口的类

  • BeanDefinitionRegistryPostProcessor接口,其中有两个重要的方法:- postProcessBeanDefinitionRegistry:用于注册新的BeanDefinition- postProcessBeanFactory:用于在BeanFactory准备好后进行自定义操作
  • BeanDefinitionRegistryPostProcessor:bean定义注册最后的处理器(在以上处理后执行此操作),如果想bean最后确定一个值,可以在这里操作
publicclassMyBeanDefinitionRegistryPostProcessorimplementsBeanDefinitionRegistryPostProcessor{@OverridepublicvoidpostProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)throwsBeansException{// 通过 BeanDefinitionBuilder 创建一个新的 Bean 定义BeanDefinitionBuilder builder =BeanDefinitionBuilder.genericBeanDefinition(MyCustomBean.class);// 注册这个 bean 定义到 registry 中
        registry.registerBeanDefinition("myCustomBean", builder.getBeanDefinition());System.out.println("Bean definition registered: myCustomBean");}@OverridepublicvoidpostProcessBeanFactory(org.springframework.beans.factory.config.ConfigurableListableBeanFactory beanFactory)throwsBeansException{// 在这里可以对 BeanFactory 进行进一步的配置System.out.println("Bean factory post-processing");}}

注意:所有通过@Import导入的bean名称为全路径名

标签: spring boot spring java

本文转载自: https://blog.csdn.net/qq_35512802/article/details/125752358
版权归原作者 冬天vs不冷 所有, 如有侵权,请联系我们删除。

“SpringBoot基础(四):bean的多种加载方式”的评论:

还没有评论