SpringBoot如何手动注册Bean

技术介绍

Spring-boot-mybatis-starter 是如何将mapper放入Bean容器的,feign是怎么让接口能够autowired的,都是通过springboot的手动注册完成的。

BeanDefinitionRegistryPostProcessor部分

BeanDefinitionRegistryPostProcessor是springboot手动注册bean 的组件之一,于其相似的还有importBeanDefinitionRegistrar,区别在于前者需要注解@Component,后者需要别的组件@Import。

值得注意的是无论前者还是后者,都无法直接在类中@Autowired,需要实现ApplicationContextAware接口变相取得已注册Bean。以下为主要代码:


@Component
public class Test implements BeanDefinitionRegistryPostProcessor , ApplicationContextAware {
    @Autowired
    ILogger logger; // logger == null 这里依赖注入是无效的

    private static ApplicationContext applicationContext; // 上下文,在这里用来取Bean

    @Override
    public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry beanDefinitionRegistry) throws BeansException {

        // 手动注册的Bean类型 , 由于我要注册的其实是 接口的实现类
        // 所以采用FactoryBean方式创建Bean
        // 若仅仅需要对Bean注入值,可以直接指定想创建的Bean的class
        BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(TestFactory.class); //这里可以直接改成TestFactory.class
        AbstractBeanDefinition definition = builder.getRawBeanDefinition();

        //亦可通过setBeanClass方式指定创建的类
        //definition.setBeanClass(TestFactory.class);

        //由于TestBean同时有两个不同名的Bean实例,需要手动指定注入
        TestBean c = applicationContext.getBean("testBean", TestBean.class);
        definition.getPropertyValues().addPropertyValue("testBean",c); //set 方式autowired,需要指定属性有set方法

        // 构造方法autowired,FactoryBean 的 construct 方法必须有 , 两种注入方式选其一
        // definition.getConstructorArgumentValues().addGenericArgumentValue();

        // 对 TestFactory 中的所有属性默认使用 byType 的依赖注入,若同一class有多个bean,则会报错。
        definition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);

        beanDefinitionRegistry.registerBeanDefinition(TestService.class.getName(), definition);

    }

    @Override
    public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
            System.out.println("postProcessBeanFactory");
    }

    // 获得上下文
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}

上文所述实体类

TestFactory extends FactoryBean 创建Bean的工厂

实现了FactoryBean的类在注册Bean的时候,会调用getObject和getObjectType并注册他们(相当于@Bean),而不会注册本身。

//@Component //这里注解入bean 会导致提前触发getObject创建Bean 导致重复创建Bean的问题
@Getter
@Setter
//如果需要注册的bean实现了FactoryBean 接口,则会注册getObject以及getObjectType的结果而不是其本身
public class TestFactory implements FactoryBean {

    ILogger iLogger;

    TestBean testBean;

    //相当于 @Bean return的东西
    //如果是类似@Mapper那种效果感觉这里可以整个泛型
    @Override
    public TestService getObject() throws Exception {
        System.out.println("iLogger : " + iLogger + "-" + "testBean :" + testBean);
        if (testBean != null) {
            testBean.sout();
        }
        return () -> System.out.println(1);
    }

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

注册所用接口 TestService


public interface TestService {
    void invoke();
}

TestBean 测试依赖注入用的Bean 意义不大

@Component
public class TestBean {
    public void sout() {
        System.out.println(this.getClass().getName());
    }

    //创建两个Bean,方便展示手动注册如何处理多个同类型Bean注入
    @Bean
    public TestBean testBean2() {
        return new TestBean() {
            @Override
            public void sout() {
                System.out.println("override:"+this.getClass().getName());
            }
        };
    }
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: Spring Boot提供了多种方式来注册bean,其中一种是手动注册bean。具体步骤如下: 1. 创建一个Java类,用于定义要注册bean。 2. 在该类上添加注解@Component或其他相关注解,以便Spring Boot能够扫描到该类。 3. 在该类中定义一个方法,用于创建要注册bean。 4. 在该方法上添加注解@Bean,以便告诉Spring Boot该方法返回的对象应该被注册为一个bean。 5. 在需要使用该bean的地方,使用@Autowired或其他相关注解将该bean注入到目标类中。 需要注意的是,手动注册bean需要在Spring Boot启动时进行,可以通过在启动类中添加注解@Import来引入要注册bean类。 ### 回答2: 在Spring Boot中,可以通过手动注册bean的方式来将自定义的类纳入Spring容器管理。 首先,我们需要在一个配置类中添加`@Configuration`注解,将其声明为配置类。然后,使用`@Bean`注解来标记一个方法,该方法的返回值将作为一个Spring bean进行注册。 下面是一个示例: ```java @Configuration public class MyConfiguration { @Bean public MyBean myBean() { return new MyBean(); } // 其他自定义配置及bean的注册方法 } ``` 在上述示例中,`MyConfiguration`类被声明为一个配置类,并且通过`@Bean`注解将`myBean()`方法返回的实例注册为一个Spring bean。 需要注意的是,被手动注册bean可以被其他组件自动注入或通过`@Autowired`注解来获取。 除了使用上述方式手动注册bean,Spring Boot还提供了其他的方式来注册bean,例如使用`@ComponentScan`、`@Import`、`@ImportResource`等注解,或者实现`ImportBeanDefinitionRegistrar`、`BeanFactoryPostProcessor`等自定义接口。 总的来说,Spring Boot中手动注册bean的方式很灵活,可以根据实际需求选择最适合的方式进行注册。 ### 回答3: 在Spring Boot中手动注册bean可以通过编写配置类(Configuration Class)来实现。 首先,创建一个配置类,可以使用`@Configuration`注解进行标记。在配置类中,可以使用`@Bean`注解来定义需要注册bean。例如: ```java @Configuration public class MyConfiguration { @Bean public MyBean myBean() { return new MyBean(); } // 可以同时定义多个bean // ... } ``` 上述例子中,`myBean()`方法使用`@Bean`注解定义了一个`MyBean`类的实例,然后在应用中就可以通过自动装配或者手动获取来使用该bean了。 接下来,需要在Spring Boot应用的主类上使用`@Import`注解来引入该配置类。例如: ```java @SpringBootApplication @Import(MyConfiguration.class) public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } } ``` 上述例子中,`@Import`注解将`MyConfiguration`配置类引入到应用中,这样在启动应用时,定义的bean就会被注册到Spring容器中。 需要注意的是,手动注册bean一般适用于一些特殊情况,不推荐频繁使用该方法,因为Spring Boot已经提供了自动配置的功能,可以根据约定和配置进行自动注册bean,可以更好地减少开发工作量和提高开发效率。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值