探索 SpringBoot (一) 自动装配

探索 SpringBoot (一) 自动装配

1 缘起

随着 微服务的兴起,越来越多的人开始用 SpringBoot ,但是大部分人仅仅停留在使用的 层面 对于 SpringBoot 的实现缺少了解。所以跟着楼主一起揭开 SpringBoot 的面纱吧。

2 SpringBoot 自动装配 & Spring 手动装配

SpringBoot 最大的特点就少了各种各样的配置。遵守约定优于配置的原则。封装了许多底层实现。这是也 SpringBoot 为啥易学难精的原因了。

2.1 @Configuration 配置类模式注解

我们先来看看 @Configuration ,想必大家都不陌生,底层通过 继承 Component 标明是一个配置组件

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface Configuration {
    @AliasFor(
        annotation = Component.class
    )
    String value() default "";
}

2.2 Spring @Enable 模块装配

@Enable 模块装配, 有许多 像 @EnableWebMvc,@EnableAsync…等

@Enable 模块装配 主要有两种实现方式

  • 1 注解驱动方式
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorld {

    String value() default "";
}
@Configuration
public class HelloWorldConfiguration {

    @Bean
    public String helloWorld() {
        return "this is hello word bean";
    }
}

这种方式会 直接加载 HelloWorldConfiguration 类,并且初始化里面的 @Bean 对象

  • 2 接口编程方式
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(HelloworldImportSelector.class)
public @interface EnableHelloWorld {

    String value() default "";
}
public class HelloworldImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[] {HelloWorldConfiguration.class.getName()};
    }
}
1 这种方式 先加载 HelloworldImportSelector ,并且必须得实现 ImportSelector

2 执行 selectImports 获取 要加载的类数组

3 加载 HelloWorldConfiguration 并且初始化里面的 Bean 同上

2.3 Spring 条件装配 @Profile & @Conditional

Spring 条件装配分成两块 @Profile(配置化条件装配) & @Conditional(编程条件装配)

  • 1 @Profile

被 @Profile(“xxx”) 标注的 bean 在注入之前 会获取系统的配置(profiles(“xxx”)), 如果 找到对应配置就装载,如果没找到对应配置就不装载

  • 2 @Conditional
满足条件才装配的 bean

@Bean
@ConditionOnSystemProperty(name = "user.name", value = "jun")
public String helloWorld() {
    return "hello word, junjun";
}
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionOnSystemProperty {

    /**
     * java 系统属性名称
     * @return
     */
    String name();

    /**
     * Java 系统属性值
     * @return
     */
    String value();
}
public class OnSystemPropertyCondition implements Condition{

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Map<String, Object> annotationAttributes = annotatedTypeMetadata.getAnnotationAttributes(ConditionOnSystemProperty.class.getName());

        String propertyName =String.valueOf(annotationAttributes.get("name"));
        String propertyVale =String.valueOf(annotationAttributes.get("value"));

        String javaPropertyVale = System.getProperty(propertyName);

        return propertyVale.equals(javaPropertyVale);
    }
}

流程说明

 1 用 @ConditionOnSystemProperty(name = "user.name", value = "jun") 注解标注 bean, 当条件满足时才执行注入
 
 2 加载 OnSystemPropertyCondition 类,并且 OnSystemPropertyCondition 必须实现 Condition 
 
 3 执行 matches, 通过 注解名 ConditionOnSystemProperty 从 annotatedTypeMetadata, 获取该注解成员变量的 map
 
 3 执行具体的业务逻辑 返回是否,如果返回 true 则注入 bean, 否则 不注入

3 SpringBoot 自动装配

好了 上面的铺垫说的 差不多了, 现在我们手写一个 SpringBoot 自动装配的例子

  • 实现步骤

1 激活自动装配 @EnableAutoConfiguration
2 实现自动装配
3 配置自动装配的实现 META-INF/spring.factories

  • 1 写一个起动类,并且激活自动装配 @EnableAutoConfiguration
@EnableAutoConfiguration
public class EnableAutoConfigurationBootstrap {

    public static void main(String[] args) {
        ConfigurableApplicationContext context = new SpringApplicationBuilder(EnableAutoConfigurationBootstrap.class)
                .web(WebApplicationType.NONE)
                .run(args);

        String helloWorld = context.getBean("helloWorld", String.class);
        System.out.println("检查 bean:" + helloWorld);
        context.close();
    }
}

  • 2 实现自动装配
@Configuration // Spring 模式注解
@EnableHelloWorld // Spring @Enable 模块装配
@ConditionOnSystemProperty(name = "user.name", value = "jun") // 条件装配
public class HelloWorldAutoConfiguration {
}

2.1 ConditionOnSystemProperty 实现

@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionOnSystemProperty {

    /**
     * java 系统属性名称
     * @return
     */
    String name();

    /**
     * Java 系统属性值
     * @return
     */
    String value();
}
public class OnSystemPropertyCondition implements Condition{

    @Override
    public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
        Map<String, Object> annotationAttributes = annotatedTypeMetadata.getAnnotationAttributes(ConditionOnSystemProperty.class.getName());

        String propertyName =String.valueOf(annotationAttributes.get("name"));
        String propertyVale =String.valueOf(annotationAttributes.get("value"));

        String javaPropertyVale = System.getProperty(propertyName);

        return propertyVale.equals(javaPropertyVale);
    }
}

2.2 EnableHelloWorld

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

    String value() default "";
}
public class HelloworldImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[] {HelloWorldConfiguration.class.getName()};
    }
}

  • 3 在 resources 下创建 META-INF/spring.factories 添加如下配置
# 配置 HelloWorldAutoConfiguration 自动装配
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.imooc.configuration.HelloWorldAutoConfiguration

4 自动装配流程分析

1 springboot 扫描 META-INF/spring.factories 下面的 EnableAutoConfiguration 配置。

2 根据配置 加载 HelloWorldAutoConfiguration

3 先进行 ConditionOnSystemProperty 进行条件判断

4 如果满足条件 执行 EnableHelloWorld 自动装配 bean

5 总结

因为写文章的时间比较短, 所以难免有疏漏之处。如果大家发现那里写的不对,欢迎在评论里面评论哈。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值