Spring boot @Enable原理 条件装配 自动装配原理

533 阅读1分钟

@Enable模块原理

注解实现

通过@Import加载配置类

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloWorldConfiguration.class)
public @interface EnableHelloWorldAnotation {
}
@SpringBootTest
@EnableHelloWorldAnotation
@Log4j2
class BtApplicationTests {

    @Autowired
    private String say;

    @Test
    void contextLoads() {
        log.debug(say);
        System.out.println(say);
    }

}

接口方式实现

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloWorldConfigurationSelector.class)
public @interface EnableHelloWorldAnotation {
}
public class HelloWorldConfigurationSelector implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata annotationMetadata) {
        return new String[]{HelloWorldConfiguration.class.getName()};
    }
}

条件装配

profile方式实现

application.properties:

spring:
  profiles:
    active: dev,female
public interface SayHelloService {
    public void say();
}
@Service
@Profile("male")
public class MaleSayHelloServiceImpl implements SayHelloService {
    @Override
    public void say() {
        System.out.println("hey you!");
    }
}
@Service
@Profile("female")
public class FemaleSayHelloServiceImpl implements SayHelloService {
    @Override
    public void say() {
        System.out.println("hi there");
    }
}
@SpringBootTest
@Log4j2
class DemoApplicationTests {

    @Autowired
    private SayHelloService sayHelloService;


    @Test
    void contextLoads() throws JsonProcessingException {

        sayHelloService.say();


    }

}

@conditional方式

@Configuration
public class HelloConfiguration {
    @Bean
    @ConditionalOnSystemProperty(name = "user.name", value = "yetin")
    public String aaa() {
        return "hello world";
    }
}
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.METHOD })
@Documented
@Conditional(OnSystemPropertyCondition.class)
public @interface ConditionalOnSystemProperty {
    /**
     * 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(ConditionalOnSystemProperty.class.getName());
        String propertyName = String.valueOf(annotationAttributes.get("name"));

        String propertyValue = String.valueOf(annotationAttributes.get("value"));

        String javaPropertyValue = System.getProperty(propertyName);
        return propertyValue.equals(javaPropertyValue);
    }
}

@SpringBootTest
@Log4j2
class DemoApplicationTests {

    @Autowired
    private String aaa;


    @Test
    void contextLoads() throws JsonProcessingException {

        System.out.println(aaa);


    }

}

自动装配原理

1.创建resources/META-INF/spring.factories

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.example.demo.configurations.HelloWorldAutoConfiguration

2.添加@EnableAutoConfiguration注解读取 resources/META-INF/spring.factories

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

        // helloWorld Bean 是否存在
        String helloWorld =
                context.getBean("aaa", String.class);

        System.out.println("helloWorld Bean : " + helloWorld);

        // 关闭上下文
        context.close();

    }
}

3.创建HelloWorldAutoConfiguration:

@Configuration // Spring 模式注解装配
@EnableHelloWorld // Spring @Enable 模块装配
@ConditionalOnSystemProperty(name = "user.name", value = "yetin") // 条件装配
public class HelloWorldAutoConfiguration {
}

4.enable注解加载HelloConfiguration:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Documented
@Import(HelloConfiguration.class)
//@Import(HelloWorldImportSelector.class)
public @interface EnableHelloWorld {
}
public class HelloConfiguration {
    @Bean
    public String aaa() {
        return "hello world";
    }
}