Spring中组件添加的方式


本文所介绍的所有组件添加的方式都是基于注解的方式。

准备工作

  1. 需要一个spring项目

添加组件的方式

结合@Configuration和@Bean注解

在@Configuration注解的配置类中,通过@Bean注解方法,可以将方法返回的对象添加到容器中。下面介绍详细的步骤。

  1. 首先我们定义了一个用户类,作为要注入到容器的目标
public class User {

    private String id;
    private String username;
    private Integer age;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
            "id='" + id + '\'' +
            ", username='" + username + '\'' +
            ", age=" + age +
            '}';
    }
}
  1. 然后我们定义一个配置类BeanConfig,这个配置类使用注解@Configuration进行了配置,表示了这个类是作为Spring的配置类。BeanConfig里面有一个方法user,返回结果就是我们步骤1中定义的类User,而且这个方法被注解@Bean进行了注解。
@Configuration
public class BeanConfig {

    @Bean
    public User user(){
        return new User();
    }
}
  1. 我们定义一个测试类,测试下容器中是否可以获取到注入的组件。

public class BeanTest {
    public static void main(String[] args){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        User user = applicationContext.getBean(User.class);
        System.out.println(user);
    }
}
  1. 输出结果中可以看到,已经获取到了user组件
User{id='null', username='null', age=null}

结合@ComponentScan和@Controller、@Service、@Repository、@Component

  1. 给配置类BeanConfig上加上注解@ComponentScan,并设置值为com.wangguitang.freedom.interview.spring.bean,表示要扫描的包的位置。
@Configuration
@ComponentScan("com.wangguitang.freedom.interview.spring.bean")
public class BeanConfig {

    @Bean
    public User user(){
        return new User();
    }
}
  1. 在包com.wangguitang.freedom.interview.spring.bean下增加一个类UserService,这个类使用了@Service注解,结合扫描,意味着这个类要被作为组件加入到容器中。
@Service
public class UserService {

    public void sayHello(String name) {
        System.out.println("Hello " + name);
    }

}

  1. 我们从容器中获取到UserService这个组件,并掉用sayHello方法,输出结果证明我们成果地将UserSerice加入到容器中,并成功获取。
public class BeanTest {
    public static void main(String[] args){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        User user = applicationContext.getBean(User.class);
        System.out.println(user);

        UserService userService = applicationContext.getBean(UserService.class);
        userService.sayHello("Spring");
    }
}

使用@Import导入

这种方式在Spring boot中被大量使用。很多@EnableXXX注解的功能都是通过@Import往容器里导出组件实现的。使用@Import导入组件,又有三种方式,下面分别介绍。

直接导入组件

  1. 我们定义了一个类UserDao,我们准备将这个类导入到容器中作为组件。我们没有在代码上加上@Component之类的注解,让自动扫描去自动将此类加入到容器中,模仿这是一个外部Jar包里面一个类。
public class UserDao {

    public void getName(){
        System.out.println("My name is Spring");
    }
}
  1. 还在BeanConfig这个配置类中,我们加入了一行@Import(UserDao.class),表示往容器中导入UserDao这个类。
@Configuration
@ComponentScan("com.wangguitang.freedom.interview.spring.bean")
@Import(UserDao.class)
public class BeanConfig {

    @Bean
    public User user(){
        return new User();
    }
}

  1. 我们依旧在测试类BeanTest中的测试代码中尝试获取UserDao,发现是可以成功的。
public class BeanTest {
    public static void main(String[] args){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        User user = applicationContext.getBean(User.class);
        System.out.println(user);

        UserService userService = applicationContext.getBean(UserService.class);
        userService.sayHello("Spring");

        UserDao userDao = applicationContext.getBean(UserDao.class);
        userDao.getName();
    }
}

实现接口ImportSelector

通过查看@Import的注解,我们可以发现,我们也可以实现接口ImportSelector,通过实现方法selectImports,返回要导入类的全限定名,也可以实现导入组件,这种方式也是Spring Boot的自动配置使用的方式。下面我们试试。

  1. 我们编写了一个类UserController,将此类作为我们要导入到容器中的类。
public class UserController {
    
    public void query(){
        System.out.println("UserController#query");
    }
}
  1. 我们编写了一个类MyImportSelector,这个类实现了ImportSelector接口,并实现了方法selectImports,返回一个包含了UserController全限定名的String数组。
public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.wangguitang.freedom.interview.spring.bean.UserController"};
    }
}

  1. 还是在配置类BeanConfig上,@Import传入的值是支持数组的,我们将MyImportSelector也加入。
@Configuration
@ComponentScan("com.wangguitang.freedom.interview.spring.bean")
@Import({
    UserDao.class,
    MyImportSelector.class
})
public class BeanConfig {

    @Bean
    public User user(){
        return new User();
    }
}

  1. 在测试类BeanTest中加入获取UserController类的代码进行测试,结果是UserController成功加入到了容器中。
public class BeanTest {
    public static void main(String[] args){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        User user = applicationContext.getBean(User.class);
        System.out.println(user);

        UserService userService = applicationContext.getBean(UserService.class);
        userService.sayHello("Spring");

        UserDao userDao = applicationContext.getBean(UserDao.class);
        userDao.getName();

        UserController userController = applicationContext.getBean(UserController.class);
        userController.query();
    }
}

输出:
User{id='null', username='null', age=null}
Hello Spring
My name is Spring
UserController#query

实现ImportBeanDefinitionRegistrar接口

通过查看@Import注解,发现还可以实现ImportBeanDefinitionRegistrar接口来注入组件。

  1. 我们编写一个类BookService,作为我们要注入到容器中的组件。
public class BookService {

    public void getBookName(){
        System.out.println("Book name is A");
    }
}
  1. 我们编写一个类MyImportBeanDefinitionRegistrar,此类实现了接口ImportBeanDefinitionRegistrar,注册了一个BookService类的Bean定义。
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        BeanDefinition beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(BookService.class).getBeanDefinition();
        registry.registerBeanDefinition("bookService", beanDefinition);
    }
}
  1. 还是修改我们的配置类Bean Config,给@Import中加入类MyImportBeanDefinitionRegistrar
@Configuration
@ComponentScan("com.wangguitang.freedom.interview.spring.bean")
@Import({
    UserDao.class,
    MyImportSelector.class,
    MyImportBeanDefinitionRegistrar.class
})
public class BeanConfig {

    @Bean
    public User user() {
        return new User();
    }
}
  1. 我们在测试类中尝试获取BookService,结果是可以成功获取到此组件。
public class BeanTest {
    public static void main(String[] args){
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(BeanConfig.class);
        User user = applicationContext.getBean(User.class);
        System.out.println(user);

        UserService userService = applicationContext.getBean(UserService.class);
        userService.sayHello("Spring");

        UserDao userDao = applicationContext.getBean(UserDao.class);
        userDao.getName();

        UserController userController = applicationContext.getBean(UserController.class);
        userController.query();

        BookService bookService = applicationContext.getBean(BookService.class);
        bookService.getBookName();
    }
}

输出结果:
User{id='null', username='null', age=null}
Hello Spring
My name is Spring
UserController#query
Book name is A

总结

我们介绍了五种往容器中添加组件的办法,每种方法各有各自的使用场景。在编写我们自己的代码时,可以最经常使用的是@ComponentScan加上@Component等注解的方式。在添加第三方的配置类时,可能使用比较多的是使用@Bean注解。如果想导入一个配置类,或者使用编码的方式导入组件时,使用@Import注解是一种不错的方式。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值