Spring——Bean注入几种方式(放入容器)

这篇具有很好参考价值的文章主要介绍了Spring——Bean注入几种方式(放入容器)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

个人博客: 全是干货,相信不会让你失望

1.XML方式注入

在现在这个Springboot横行的年代,以XML来注入的方式可能已经不多见了,因为压根用不着,但毕竟是注入方式之一也得提一提,这种方式就是依赖于XML的解析来获取我们需要注入的Bean对象

常见的方式有:set方法注入、构造方法注入

这里举几个常见的例子:

set方式注入
// 实体类如下:
@Data
public class test {
    private String  name;
    private Integer sex;
}

// 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/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--set方式注入
           id是注入bean中的名字
           class 是全限定类名
           property 是按照set方式注入
       -->
    <bean id="student1" class="com.example.spkie.model.test">
        <property name="name" value="test"/>
        <property name="sex" value="10"/>
    </bean>
</beans>

测试:

Spring——Bean注入几种方式(放入容器)

构造方法注入
// 实体类如下: 
@Data
public class test {
    private String  name;
    private Integer sex;
    
     public test(String name,Integer sex){
        this.name=name;
        this.sex=sex;
    }
}

// XML文件如下 test.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/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--set方式注入
        id是注入bean中的名字
        class 是全限定类名
        constructor-arg 是按照构造方式注入
        index 是按照成员变量在构造函数中的参数的第几个
        name 表示成员变量名
        type 表示类型
        value 表示值
        ref 表示引用 可引用另外一个注入到Spring的中的值
    -->
    <bean id="student1" class="com.example.spkie.model.test">
        <constructor-arg index="0" name="name" value="构造方法注入"></constructor-arg>
        <constructor-arg index="1" name="sex" value="50"></constructor-arg>
    </bean>
</beans>

测试:

Spring——Bean注入几种方式(放入容器)

2.注解方式注入

@Component+@ComponentScan

我们开发中常用的 @Service@Controller 都是 @Component下的注解 ,需要配合 @ComponentScan 注解才能被扫描到并放入IOC容器中

为什么平时却没用@ComponentScan注解呢?

因为平时用的都是Springboot,Springboot启动类上的 @SpringbootApplication 注解类下已经带有 @ComponentScan 注解了,默认扫描启动类同级包下的@Component

例子如下:

我们先准备一个获取IOC容器内bean 的工具类 SpringUtils

@Component
public final class SpringUtils implements BeanFactoryPostProcessor {
    /**
     * Spring应用上下文环境
     */
    private static ConfigurableListableBeanFactory beanFactory;

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
        SpringUtils.beanFactory = beanFactory;
    }

    public static <T> T getBean(Class<T> clz) throws BeansException {
        T result = (T) beanFactory.getBean(clz);
        return result;
    }
    
    public static <T> T getBean(String name) throws BeansException {
        return (T) beanFactory.getBean(name);
    }
}

测试要注入的Bean实体类:

@Component
@Data
public class ComponentTest {
    private String name="@Component 注解注入";
    private String remark="注意需要配合@ComponentScan 注解使用";
}

Spring——Bean注入几种方式(放入容器)

可以看到报错了,压根找不到这个bean,因为我们上面说过了springboot默认扫描的是启动类同级下的路径,我们把启动类放到了独立的包下,所以扫描不到了,这时候我们要么在用@ComponentScan注解配置一次扫描路径,要么把启动类提出来,我这里演示前者

我们在启动类上加上@ComponentScan注解配置一次扫描路径,就可以看到注入成功啦

Spring——Bean注入几种方式(放入容器)

@Configuration+@Bean+@ComponentScan

@Configuration注解相信大家也都不陌生,这个注解同样要配合@ComponentScan使用,那到底和@Component有什么区别呢?

@Configuration注入的是CGlib代理类,@Component注入的是类本身

我们与 @Component 一样准备个 @Configuration 注入类:

@Configuration
@Data
public class ConfigurationTest {
    private String name="@Configuration 注解注入";
    private String remark="注意需要配合@ComponentScan 注解使用";
}

Spring——Bean注入几种方式(放入容器)

可以看到Bean类的本质区别,难道为了这个就搞了@Configuration注解吗?当然不是,这个注解还可以配合@Bean注解一起使用,用来同时注入多个Bean

// 添加一个额外的Bean对象
public class ConfigurationTestBean {

    public void test(){
        System.out.println("我是在Configuration 内部注入的 bean ");
    }

}

// ConfigurationTest中添加Bean方法

@Configuration
@Data
public class ConfigurationTest {
    private String name="@Configuration 注解注入";
    private String remark="注意需要配合@ComponentScan 注解使用";
    // ConfigurationTest 中需要注入的Bean
    @Bean
    public ConfigurationTestBean configurationTestBean(){
        return new ConfigurationTestBean();
    }
}

Spring——Bean注入几种方式(放入容器)

这样的@Bean可以在同一个类中注入多个,所以 @Component 更多的用来注入配置文件类,@Configuration 更多的用来注入多个实例类

@Import

这种方式一般用在第三方包的加载比较多,使用起来呢也简单需要注入哪个Bean,导入哪个Bean的class就可以了,例如:

// 导入单个Bean
@Import(xxxxBean.class)

// 导入多个Bean
@Import({xxxxBean.class,xxxxBean.class})


但这个注解使用得注意,一定要能被扫描到才行,可以直接放在启动类上,如果是普通需要配合@Component或者@Configuration来使用,因为此注解单独使用是不会被扫描到的,也就不会被加载了

在一个注解上导入多个Bean要写这么多可能不是很优雅,所以还可以配合ImportSelector接口使用:

// 导入实现了ImportSelector接口的类即可
@Import(MyImportSelector.class)

// 实现ImportSelector 在数组中配置需要导入的Bean路径  返回一个数组
public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{"com.example.spkie.importTest.xxxxBean","com.example.spkie.importTest.xxxxBean"};
    }
}

3.实现ImportBeanDefinitionRegistrar接口

看接口名称就知道了是不是有点像Bean的注册接口,需要配合@Import使用:

// 使用注解注入
@Import({MyImportBeanDefinitionRegistrar.class})

// 需要注入的Bean
public class DefinitionRegistrarBean {
    public void test(){
        System.out.println("我是通过Bean注册接口注入的Bean,需要配合@Import注解同样需要被扫描");
    }
}
// 自定义类
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(DefinitionRegistrarBean.class);
        registry.registerBeanDefinition("definitionRegistrarBean",beanDefinitionBuilder.getBeanDefinition());
    }
}

测试:

Spring——Bean注入几种方式(放入容器)

我们平时开发中常用的openfeign也是采用的这种方式:

Spring——Bean注入几种方式(放入容器)

4.实现FactoryBean

用这个得先搞清楚FactoryBean和BeanFactory的区别:

  • BeanFactory: IOC容器顶层接口,用来Bean容器管理
  • FactoryBean: 是一个bean,是一个能产生bean的工厂bean,本身也会作为bean给容器管理,所以作为一个能产生Bean的工厂,我们可以自定义Bean(这也是最关键的点)

让我们来看看怎么用:

// 这是我们利用工厂想要生产的bean
public class FactoryTestBean {
    public void test(){
        System.out.println("我是通过实现FactoryBean接口注入的Bean");
    }
}

// 工厂Bean 实现两个方法
@Component
public class MyFactoryBean implements FactoryBean<FactoryTestBean> {

   //这个方法就是我们要生产的Bean
    @Override
    public FactoryTestBean getObject() throws Exception {
        return new FactoryTestBean();
    }

    @Override
    public Class<?> getObjectType() {
        return FactoryTestBean.class;
    }
}

测试:

可以看到通过Class无论是工厂bean还是工厂生产的bean我们都可以获取,但是发现通过beanName获取bean的区别没有,我们通过工厂的beanName获取到的是实际生产的对象,要获取真正的工厂需要在beanName前面加上&

为什么通过工厂的beanName获取到的是实际生产的对象?

其实从上述注入的过程中也能看到我们往容器中注入的其实是工厂Bean,并没有注入工厂生产的那个对象(可以打印容器所有的beanName验证),可以理解为在从容器中获取Bean的时候有判断是否实现了FactoryBean接口,实现了则会调用该bean的getObject()方法返回,所以此时会返回实际工厂生产的对象了

Spring——Bean注入几种方式(放入容器)

我们一样以openfeign框架举例:

此注入的feign接口实际注入的是FeignClientFactoryBean,所以在调用容器中feign接口的Bean对象的时候,实际执行的是FeignClientFactoryBean.getObject()方法

Spring——Bean注入几种方式(放入容器)

5.实现BeanDefinitionRegistryPostProcessor

这个接口继承了BeanFactoryPostProcessor接口,BeanFactoryPostProcessor是BeanFactory的后置处理器,该接口多个了一个对BeanDefination处理的方法,可以在BeanFactory生成后对里面的BeanDefination做一次处理,所以当然可以注册BeanDefination啦,后续就成了Bean

BeanDefinitionRegistryPostProcessor源代码如下:

public interface BeanDefinitionRegistryPostProcessor extends BeanFactoryPostProcessor {
    void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry var1) throws BeansException;
}

怎么用呢?先直接上例子吧:

// 还是要搭配注解
@Import(MyBeanDefinitionRegistryPostProcessor.class)

// 要注入的bean对象
public class RegistrarPostProcessorBean {
    public void test(){
        System.out.println("我是通过后置处理器注入的bean");
    }
}
// 自定义类
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(RegistrarPostProcessorBean.class);
        beanDefinitionRegistry.registerBeanDefinition("registrarPostProcessorBean",beanDefinitionBuilder.getBeanDefinition());
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

乍一看和ImportBeanDefinitionRegistrar类似,都是用了BeanDefinitionRegistry 来注册的,但ImportBeanDefinitionRegistrar是Spring的扩展点之一,提供给第三方对接使用的

BeanDefinitionRegistryPostProcessor这个源码就不追溯了,后面再说(还是提一下吧,容器初始化的时候有调用)

Spring——Bean注入几种方式(放入容器)

既然是BeanFactory后置处理器,所以它还可以修改BeanDefination里面保存的Bean信息:

// 我们用到之前使用过的Bean
@Component
@Data
public class ComponentTest {
    private String name="@Component 注解注入";
    private String remark="注意需要配合@ComponentScan 注解使用";
}

// 修改后置处理器 
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {
        // 新增如下代码  修改ComponentTest Bean属性
        BeanDefinition configurationTestBean = beanDefinitionRegistry.getBeanDefinition("componentTest");
        MutablePropertyValues propertyValues = configurationTestBean.getPropertyValues();
        propertyValues.add("name","我是修改后的Bean属性" );

        BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.rootBeanDefinition(RegistrarPostProcessorBean.class);
        beanDefinitionRegistry.registerBeanDefinition("registrarPostProcessorBean",beanDefinitionBuilder.getBeanDefinition());
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {

    }
}

结果如下:
Spring——Bean注入几种方式(放入容器)

这里演示了修改字段的值,当然还可以修改其他的比如是否加载优先级、是否懒加载、单例多例等文章来源地址https://www.toymoban.com/news/detail-428014.html

到了这里,关于Spring——Bean注入几种方式(放入容器)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 4.3---Spring框架之Spring中bean的注入方式---(深入版本)

    Spring基于xml注入bean的几种方式: set()方法注入; 2.构造器注入:①通过index设置参数的位置;②通过type设置参数类型; 静态工厂注入; 实例工厂; Spring IOC注入方式用得最多的是(1)(2)种; 注意:通过Spring创建的对象默认是单例的,如果需要创建多实例对象可以在标签后面添

    2023年04月10日
    浏览(30)
  • spring(1):基于XML获取Bean对象以及各种依赖注入方式

    1.1 根据id获取 1.2 根据类型获取 1.3 根据id和类型获取 注意: 当根据类型获取bean时,要求IOC容器中指定类型的bean有且只能有一个。 例如以下XML文件,当IOC容器中一共配置了两个,根据类型获取时会抛出异常。 根据类型来获取bean时,在满足bean唯一性的前提下,其实只是看:

    2024年01月25日
    浏览(34)
  • 【Spring】基于注解方式存取JavaBean:Spring有几种注入方式?有什么区别?

     Hello,我是小黄。众所周知,Spring是一个开源的Java应用程序框架,其中包括许多通过注解实现依赖注入的功能。Spring提供了多种注入方式,可以满足不同的需求和场景。常见的注入方式包括构造函数注入、Setter方法注入和属性注入。不同的注入方式有不同的适用场景和优缺

    2024年02月11日
    浏览(33)
  • Spring的加载配置文件、容器和获取bean的方式

    🐌个人主页: 🐌 叶落闲庭 💨我的专栏:💨 c语言 数据结构 javaweb 石可破也,而不可夺坚;丹可磨也,而不可夺赤。 properties文件: jdbc.properties 1.开启context命名空间 2.使用context命名空间,加载指定properties文件 3.使用属性占位符 ${} 读取properties文件中的属性 properties文件

    2024年02月15日
    浏览(30)
  • Spring容器获取Bean的9种方式 | 京东云技术团队

    随着SpringBoot的普及,Spring的使用也越来越广,在某些场景下,我们无法通过注解或配置的形式直接获取到某个Bean。比如,在某一些工具类、设计模式实现中需要使用到Spring容器管理的Bean,此时就需要直接获取到对应的Bean。 本文为大家整理汇总了常见的获取Bean的方式,并提

    2024年02月12日
    浏览(25)
  • 实战讲解及分析Spring新建Bean的几种方式以及创建过程(图+文+源码)

    作为一个应用开发人员而言,会使用某一个工具分为两个层次(个人观点): 第一个层次,知道工具,会使用这个工具解决问题; 第二个层次,理解工具的实现原理。 关于Spring的学习,还在第一个层次转悠,缺少原理的研究, 随着学习的深入,开始研究些Spring源码,配合

    2023年04月08日
    浏览(27)
  • Spring的简介ioc容器及注入方式

    Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。    Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。    然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Sprin

    2024年02月11日
    浏览(24)
  • spring ico容器 spring注入方式 spring与tomcat整合

    目录 一、简介 1、什么是spring? 2、目的 3、功能及使用范围 二、spring IOC 1、ioc的理解 2、开发人员可达到的目的 3、分析实现 4、bean配置 三、spring IOC的注入方式 1、set方法属性注入 2、构造注入 3、自动装配 四、spring与tomcat的整合/spring与web容器的整合 五、spring AOP 1、aop的特

    2024年02月12日
    浏览(32)
  • 【Spring学习】走进spring,spring的创建和使用,spring获取Bean的几种常见方式, ApplicationContext 和 BeanFactory的区别(重点面试)

    前言: 大家好,我是 良辰丫 ,我们在上一篇文章不是简单介绍了SpringBoot嘛,为什么不学习SpringBoot,而是要开始Spring呢?Spring是SpringBoot的前身,我们先学习以前的稍微复杂的框架,才能更好的学习SpringBoot.💌💌💌 🧑个人主页:良辰针不戳 📖所属专栏:javaEE进阶篇之框架学习 🍎励志

    2024年02月08日
    浏览(34)
  • 【Spring】1、Spring 框架的基本使用【读取配置文件、IoC、依赖注入的几种方式、FactoryBean】

    Spring 框架可以说是 Java 开发中最重要的框架,功能 非常 强大 中文文档:https://springdoc.cn/spring/ 官网:https://spring.io/ Spring makes Java Simple、modern、productive … Spring 框架的几个核心概念: IoC: I nversion o f C ontrol:控制反转 DI: D ependency I njection:依赖注入 AOP: A spect O riented P rogram

    2024年02月09日
    浏览(36)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包