将bean注入Spring容器的五种方式

前言

  我们在项目开发中都用到Spring,知道对象是交由Spring去管理。那么将一个对象加入到Spring容器中,有几种方法呢,我们来总结一下。

@ComponentScan + @Component

  @ComponentScan可以放在启动类上,指定要扫描的包路径;该包路径下被@Component修饰的类,都会被注入到Spring容器中。

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan(basePackages = "com.gs.beanRegister")
public class BootStrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(BootStrap.class);
        A bean = context.getBean(A.class);
        bean.say();
    }

}

  com.gs.beanRegister包下:

import org.springframework.stereotype.Component;

@Component
public class A {

    public void say() {
        System.out.println("这是a");
    }

}

  注:在SpringBoot中,由于其自动装配的特性,所以@ComponentScan可以不加,只要@Component修饰的类和启动类在同一包下或者在启动类所在包的子包下。


@Configuration + @Bean

  @Configuration用来声明一个配置类,如果它的方法被@Bean修饰,那么该方法返回的对象也会被注入到Spring容器中。
  代码方面,BootStrap 类不动,A类的@Component去掉,com.gs.beanRegister包下建个配置类:

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Bean;

@Configuration
public class MyConfiguration {

    @Bean
    public A a() {
        return new A();
    }

}

通过@Import注解

  这个注解可能平时大家接触得不多,它有好几种使用方式。

      1.直接导入类的class
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

@Import(A.class)
public class BootStrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(BootStrap.class);
        A bean = context.getBean(A.class);
        //B bean = context.getBean(B.class);
        bean.say();
    }

}

  A类不用添加任何注解:

public class A {

    public void say() {
        System.out.println("这是a");
    }

}

      2.导入配置类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;

@Import(MyConfiguration.class)
public class BootStrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(BootStrap.class);
        A bean = context.getBean(A.class);
        bean.say();
    }

}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

// 使用@Import导入配置类时,@Configuration可以不加
//@Configuration
public class MyConfiguration {

    @Bean
    public A a() {
        return new A();
    }

}

      3.导入ImportSelector的实现类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;

@Import(MyImportSelector.class)
public class BootStrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(BootStrap.class);
        A bean = context.getBean(A.class);
        bean.say();
    }

}
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata metadata) {
        // 返回要注入的bean的全路径,A类不用任何注解修饰
        // SpringBoot的自动装配,就用到了这种方式:
        // 返回配置类的全路径,配置类的@Bean方法返回的对象也能注入到容器中
        return new String[] { A.class.getName() };
    }

}

      4.导入ImportBeanDefinitionRegistrar的实现类
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;

@Import(MyImportBeanDefinitionRegistrar.class)
public class BootStrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(BootStrap.class);
        A bean = context.getBean(A.class);
        bean.say();
    }

}
import org.springframework.beans.factory.config.BeanDefinition;
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 metadata, 
                BeanDefinitionRegistry registry) {
        // 构建bean的元数据,A类不用任何注解修饰
        // spring-mybatis扫描mapper接口,生成代理类,就是用的这种方式
        BeanDefinition definition = new RootBeanDefinition(A.class);
        registry.registerBeanDefinition("a", definition);
    }

}

借助FactoryBean接口

  实现FactoryBean接口的类,除了本身会被注入外,getObject方法返回的对象也会被注入到Spring容器中。

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Import;

@Import(MyFactoryBean.class)
public class BootStrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext(BootStrap.class);
        A bean = context.getBean(A.class);
        bean.say();
    }

}
import org.springframework.beans.factory.FactoryBean;

public class MyFactoryBean implements FactoryBean {

    @Override
    public Object getObject() throws Exception {
        return new A();
    }

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

借助BeanDefinitionRegistryPostProcessor接口

  在Spring容器启动时,会调用该接口的postProcessBeanDefinitionRegistry方法,大概意思是等BeanDefinition(上面提到的bean的元数据)加载完成后,再对它进行后置处理。所以可以在此调整BeanDefinition,从而把对应的bean注入。

import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class BootStrap {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext context = 
        new AnnotationConfigApplicationContext();
        BeanDefinitionRegistryPostProcessor postProcessor = 
        new MyBeanDefinitionRegistryPostProcessor();
        context.addBeanFactoryPostProcessor(postProcessor);
        context.refresh();
        A a = context.getBean(A.class);
        a.say();
    }
    
}
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;

public class MyBeanDefinitionRegistryPostProcessor implements 
             BeanDefinitionRegistryPostProcessor {

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry 
                registry) throws BeansException {
        BeanDefinition definition = new RootBeanDefinition(A.class);
        registry.registerBeanDefinition("a", definition);
    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory 
                beanFactory) throws BeansException {
    }
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot中,容器注入是一种将对象实例化并配置为Spring容器管理的方式。它可以帮助我们简化对象的创建和管理过程,同时也可以帮助我们实现依赖注入,让代码更加灵活、可维护和可扩展。 容器注入有三种方式: 1. 构造函数注入:通过构造函数将依赖注入到对象中。 ```java @Service public class UserService { private final UserRepository userRepository; public UserService(UserRepository userRepository) { this.userRepository = userRepository; } } ``` 2. Setter方法注入:通过Setter方法将依赖注入到对象中。 ```java @Service public class UserService { private UserRepository userRepository; @Autowired public void setUserRepository(UserRepository userRepository) { this.userRepository = userRepository; } } ``` 3. 字段注入:通过直接将依赖注入到字段中。 ```java @Service public class UserService { @Autowired private UserRepository userRepository; } ``` 在使用容器注入时,需要在上添加注解,以告诉Spring容器需要被管理。 - @Component:通用注解,表示该是一个组件。 - @Service:表示该是一个服务,通常用于注入业务逻辑层。 - @Repository:表示该是一个数据仓库,通常用于注入数据访问层。 - @Controller:表示该是一个控制器,通常用于注入Web层。 以上注解都是由@Component注解派生而来,它们的作用都是将该注入Spring容器中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值