Springboot版本是1.5.release.
Springboot中使用EnableAutoConfiguration注解,如下所示:
List-1
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {
String ENABLED_OVERRIDE_PROPERTY = "spring.boot.enableautoconfiguration";
/**
* Exclude specific auto-configuration classes such that they will never be applied.
* @return the classes to exclude
*/
Class<?>[] exclude() default {};
/**
* Exclude specific auto-configuration class names such that they will never be
* applied.
* @return the class names to exclude
* @since 1.3.0
*/
String[] excludeName() default {};
}
複制
主要是那個EnableAutoConfigurationImportSelector,繼承了接口ImportSelector,方法String[] selectImports(AnnotationMetadata var1)傳回的類都會注入到Sping容器中。
我們來實作一個自己的ImportSelector。
圖1
如圖1所示,我們定義自己的類SelectorA、SelectorB、SelectorC,定義MyImportSelector如下所示:
List-2
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSelector implements ImportSelector {
//會将這個方法傳回的數組,放到容器中
@Override
public String[] selectImports(AnnotationMetadata annotationMetadata) {
return new String[]{"com.mjduan.project.springbootlearn.selector.SelectorA",
"com.mjduan.project.springbootlearn.selector.SelectorB"};
}
}
複制
之後定義自己的EnableMyX,如下List-3
List-3
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({MyImportSelector.class})
public @interface EnableMyX {
}
複制
在main方法的類上加上注解EnableMyX,如下所示:
List-4
import com.mjduan.project.springbootlearn.enable.EnableEcho;
import com.mjduan.project.springbootlearn.selector.EnableMyX;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
@EnableMyX
public class SpringbootLearnApplication {
public static void main(String[] args) {
SpringApplication.run(SpringbootLearnApplication.class, args);
}
}
複制
我們通過BeanPostProcessor來驗證SelectorA和SelectorB加入到容器中了,如下
List-5
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;
@Component
public class MyImportSelectorBeanPostProcessor implements BeanPostProcessor {
private String[] classess={
"com.mjduan.project.springbootlearn.selector.SelectorA",
"com.mjduan.project.springbootlearn.selector.SelectorB"};
@Override
public Object postProcessBeforeInitialization(Object o, String s) throws BeansException {
return o;
}
@Override
public Object postProcessAfterInitialization(Object o, String s) throws BeansException {
for (String str : classess) {
if (o.getClass().getName().equals(str)) {
System.out.println(o.getClass().getName());
}
}
return o;
}
}
複制
之後啟動應用,在控制台就可以看到列印出的SelectorA和SelectorB了。
ImportSelector傳回的String[]會被注入到Spring容器中,EnableAutoConfiguration中EnableAutoConfigurationImportSelector傳回的是META-INF/spring.factories中org.springframework.boot.autoconfigure.EnableAutoConfiguration的值,這些值都是些類名,這些類上都有@Configuration注解,這樣就将這個配置類中的bean加入到容器中。
思考
- 問題1,ImportSelector傳回的String[]是怎麼加入到Spring容器中的,在Springboot啟動流程中的哪個步驟呢?
Reference
- https://www.jianshu.com/p/3da069bd865c
(adsbygoogle = window.adsbygoogle || []).push({});