spring装配

spring从一定层面上讲是Bean容器,那么它是怎么实现Bean的装配,这块对于理解springBoot自动装配有很大帮助。这里说的装配,我指的是基于注解/代码的方式,毕竟现在开发都是注解先行,至于xml方式就不讨论了。

方式

  • 模式注解 @Component 等(Spring2.5+)
  • 配置类 @Configuration@Bean (Spring3.0+)
  • 模块装配 @EnableXXX@Import (Spring3.1+)

模式注解

使用它在我们日常开发中很常见,@Component@Service@Repository 等。但是它又个天然的缺陷,只能在我们自己写的代码中,对于jar包中组件,无能为力。

配置类

@Configuration@Bean 方式,这种方式我们在开发中也经常使用,例如配置数据源,一些中间件。但是它也有个天然的缺点,配置一多,类就显得很臃肿,编码和修改成本都比价高。

模块装配

这是个杀手锏,特别对于需要装配较多的bean到容器,一般它的套路是:@Enablexxx、@Import 注解来完成。

  • 元注解@EnableBean
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(User.class)
public @interface EnableBean {
}
  • 实体
@Data
public class Order {
    private Integer id;
    private Integer userId;
    private Integer productId;
    private BigDecimal amount;

    public Order() {
        System.out.println("order init ...");
    }
}

@Data
public class User {
    private Integer id;
    private String name;

    public User() {
        System.out.println("user init ...");
    }
}

  • 配置类
@Configuration
@EnableBean
public class Config {

}
  • 启动容器
    public static void main(String[] args) {
        AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(Config.class);
        String[] beanDefinitionNames = ctx.getBeanDefinitionNames();
        Stream.of(beanDefinitionNames).forEach(System.out::println);
    }
  • 打印的日志
user init ...
10:38:50.701 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.hf.astilt.normal.Orange'
10:38:50.702 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'com.hf.astilt.normal.Order'
order init ...
10:38:50.710 [main] DEBUG org.springframework.core.env.PropertySourcesPropertyResolver - Found key 'spring.liveBeansView.mbeanDomain' in PropertySource 'systemProperties' with value of type String
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
config
com.hf.astilt.normal.User
com.hf.astilt.normal.Orange
com.hf.astilt.normal.Order

可以看到spring启动后,打印出了我配置的几个类,是不是简单很多。

@Import

这个注解隐含了模块装配的秘密,我们看看。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Import {

	/**
	 * {@link Configuration @Configuration}, {@link ImportSelector},
	 * {@link ImportBeanDefinitionRegistrar}, or regular component classes to import.
	 */
	Class<?>[] value();

}

翻译下它的备注:@Import里面的值是个数组。被@Configuration修饰的配置类、实现ImportSelector的类,实现ImportBeanDefinitionRegistrar的类,普通的Java bean。

配置类、普通Java类就不说了,简单易懂。重点看看实现了:ImportSelectorImportBeanDefinitionRegistrar的类。

  • ImportSelector
public class UserImport implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{User.class.getName()};
    }
}
  • ImportBeanDefinitionRegistrar
public class FruitImport implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        registry.registerBeanDefinition("apple", new RootBeanDefinition(Apple.class));
        registry.registerBeanDefinition("orange", new RootBeanDefinition(Orange.class));
    }
}
  • @EnableBean
@Configuration
@EnableBean
@Import({UserImport.class, FruitImport.class})
public class Config {

}
  • 效果
user init ...
15:06:34.692 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'apple'
apple init ...
15:06:34.692 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating shared instance of singleton bean 'orange'
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
config
com.hf.astilt.normal.User
apple
orange

@Import里面配置ImportBeanDefinitionRegistrarImportSelector的实现类,效果与直接导入Java Bean一样。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值