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({});