栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring中注入bean的几种方式

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring中注入bean的几种方式

前言

  Spring是一个开源的框架,为开发者提供了便利,也为企业级开发产生的复杂问题提供了多种解决方法。当我们想要将组件注入到Spring的IOC容器中,除了@Controller、@Service、@Repository、@Component,还有一些常用的方法,下面我就这些方法简单的介绍下。
ps:下面所有的输出都是基于以下代码:

public void testBean() {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(MainConfig.class);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for (String name : beanDefinitionNames) { // 循环遍历容器中定义的bean的name
            System.out.println(name);
        }
    }
@Bean

我们自己写的组件,可以加上那四个注解,将组件注入到IOC容器当中,但是如果我们导入的是第三方组件呢?我们没法在类上标注注解,所以可以使用 @Bean 注解来实现。@Bean 注解既可以注入自己写的组件,也可以注入第三方组件。

@Configuration
@ComponentScan(value = {"com.zxb"})
public class MainConfig {
	@Bean
    public Cat cat() {
        return new Cat();
    }

    @Bean
    public com.mysql.cj.jdbc.Driver jdbcDriver() throws SQLException {
        return new Driver();
    }
}

Spring提供了强大的 @Bean 注解,使得我们可以方便的注入组件。标注了 @Bean 注解的方法,该方法的返回值就是要注入到IOC容器中的组件,而方法名就是该组件在IOC容器中的名称。 当然,我们也可以使用 @Bean注解的value属性来给组件赋值,如 @Bean(value = "driver")

@import

  除了使用@Bean注解来导入第三方组件,还可以使用 @import 注解来实现,在Spring的底层中,大量用到了@import注解。此注解的value值是一个数组,可以写多个Class。

@Configuration
@ComponentScan(value = {"com.zxb"})
@import(value = {com.mysql.cj.jdbc.Driver.class}) // 导入第三方组件
public class MainConfig {

}

可以看到,除了Spring内置的一些组件以及配置类本身,还加入了第三方组件com.zxb.cj.jdbc.Driver类。

@import之实现 importSelector 接口

  上面提到了使用 @import 注解来实现bean的注入,但是细想一下,一个一个注入十分麻烦,这样 @import太长也不美观。那么我们就可以自己写一个 selector ,让它继承 importSelector 接口,来实现批量注入。

自定义selector:
实现importSelector 而重写的selectimports()方法,该方法的返回值数组就是要导注册的组件的全类名数组。

import org.springframework.context.annotation.importSelector;
import org.springframework.core.type.Annotationmetadata;

public class MyimportSelector implements importSelector {

	@Override
	// Annotationmetadata:当前标注 @import 注解的类的所有注解信息,这个类的所有注解信息都能获取到
    public String[] selectimports(Annotationmetadata annotationmetadata) {
        return new String[]{"com.zxb.bean.Cat","com.zxb.bean.Dog","com.zxb.Turtle"};
    }
}

配置类:

@Configuration
@ComponentScan(value = {"com.zxb"})
@import(value = {Fish.class,MyimportSelector.class})
public class MainConfig {

    @Bean
    public com.mysql.cj.jdbc.Driver jdbcDriver() throws SQLException {
        return new Driver();
    }

}

可以看到, @import 注解中value里面只有两个Class类型,一个是Fish,另一个是MyimportSelector,但是却将Cat、Dog和Turtle都注册到IOC容器中去了。

@import之实现 importBeanDefinitionRegistrar 接口

  @import还有一种用法, 就是使用importBeanDefinitionRegistrar来注入bean。这个importBeanDefinitionRegistrar是一个接口,其中有一个方法。通过这个方法,我们可以给容器中,自己添加一些组件。

自定义一个 MyimportBeanDefinitionRegistrar:

import com.zxb.bean.Pet;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.importBeanDefinitionRegistrar;
import org.springframework.core.type.Annotationmetadata;

public class MyimportBeanDefinitionRegistrar implements importBeanDefinitionRegistrar {

    
    @Override
    public void registerBeanDefinitions(Annotationmetadata importingClassmetadata, BeanDefinitionRegistry registry) {
        boolean definitionCat = registry.containsBeanDefinition("com.zxb.bean.Cat");
        boolean definitionDog = registry.containsBeanDefinition("com.zxb.bean.Dog");
        // 写一个简单的逻辑判断
        // 如果 IOC 容器中有 Cat 和 Dog 这两个组件,就注册 Pet 这个组件
        if (definitionCat && definitionDog) {
            // 这个 beanDefinition 是一个接口,需要new它的子类,子类就是RootBeanDefinition,传入我们要注册的class信息
            RootBeanDefinition petDefinition = new RootBeanDefinition(Pet.class);
            // 注册 Bean,并指定bean的名称和类型
            registry.registerBeanDefinition("pet", petDefinition);
        }
    }
}

配置类:

@Configuration
@ComponentScan(value = {"com.zxb"})
@import(value = {Fish.class,MyimportSelector.class, 
MyimportBeanDefinitionRegistrar.class})
public class MainConfig {
    @Bean
    public com.mysql.cj.jdbc.Driver jdbcDriver() throws SQLException {
        return new Driver();
    }
}

可以看到,Fish、以及自定义的选择器Selector,和自定义的 BeanDefinitionRegistrar都生效了。

使用FactoryBean进行bean注入

  不能搞混两个概念。一个是 BeanFactory ,另一个是FactoryBean。 BeanFactory 是Spring的顶级IOC接口,定义的是最基本的编码规范。而FactoryBean则是一个bean,但是又不是简单的一个bean,它可以生产或者修饰产生的bean,它和设计模式中的工厂模式和修饰器模式相近。
  首先自定义一个FactoryBean,并且要实现Factory接口。在该接口中,一共有三个方法,一个是getObject()方法,该方法的返回类型就是要注入到容器当中的bean,第二个是获取到对象的类型,第三个是判断单例与多实例。

package com.zxb.filter;

import com.zxb.bean.Animal;
import com.zxb.bean.Pet;
import org.springframework.beans.factory.FactoryBean;

public class AnimalFactoryBean implements FactoryBean {
    // 返回一个 Animal对象,注册到 IOC 容器中
    @Override
    public Animal getObject() throws Exception {
        return new Animal();
    }

    // 注册的bean的类型
    @Override
    public Class getObjectType() {
        return Pet.class;
    }

    // 该方法表示该bean是否为单实例bean
    @Override
    public boolean isSingleton() {
        return false;
    }
}

输入结果如下:

可以看到,AnimalFactoryBean也被注册到 IOC 容器中,名字默认是类名首字母小写。此时们输出下这个名为 animalFactoryBean的class信息,发现它是 com.zxb.bean.Animal 类型的。 但是如果我就要AnimalFacotry类型,而不要Animal类型的呢? 那么就在获取 bean 的时候在bean名称前加上一个 & 符号即可。

public void testBean() {
        AnnotationConfigApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(MainConfig.class);
        Object animal = applicationContext.getBean("animalFactoryBean");
        System.out.println(animal);

        Object animalFactory = applicationContext.getBean("&animalFactoryBean");
        System.out.println(animalFactory);

    }

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/292547.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号