Spring系列---自动装配

114 阅读2分钟

一. 什么是自动装配

在没有springboot之前,我们使用spring如果需要引用第三方包的功能,则需要使用xml或者java进行显示配置,比如web.xml,mybatis-config.xml

现在有了springboot自动装配功能后,我们只需要引入对于的pom,开启注解就可以了,比如

@EnableFeign , @EnableSwagger2

另外,在spring工程中引入普通jar包,是无法将jar包内的bean扫描进beanFactory, 除非指定classpath(import jar包中的resources)

二 如何实现自动装配

核心注解SpringBootApplication

@SpringBootConfiguration //底层就是@Configuration
@EnableAutoConfiguration // 开启自动配置,注册AutoConfigurationPackages,加载META-INFO/spring.factories中的类
@ComponentScan(excludeFilters = { // TODO 这两个排除过滤器TypeExcludeFilter和AutoConfigurationExcludeFilter暂不知道啥作用
		@Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
		@Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })

主要核心就是

  1. @EnableAutoConfiguration , 启用 SpringBoot 的自动配置机制
  2. @ComponentScan , 扫描被@Component注解的 bean,注解默认会扫描启动类所在的包下所有的类

1.1 @EnableAutoConfiguration

核心注解有:

  1. @AutoConfigurationPackage , 内部 import了 AutoConfigurationPackages.Registrar.class ,就是注册AutoConfigurationPackages这个类,即默认包所在位置
  2. @Import(AutoConfigurationImportSelector.class) 内部process方法扫描spring.factories中的有效bean

1.2 @ComponentScan

spring自带的注解,扫描包下的bean,远古时期使用xml就使用过这个功能

思维导图

www.processon.com/embed/6275b…

三 如何自己实现一个starter

1. starter工程

1.1 主服务对象Service

这里做个简单演示类, 这个对象时starter中的主要服务提供者

public class ProviderService {
    public ProviderService(String name) {
        this.name = name;
    }

    private String name;

    public void mainService() {
        System.out.println("Hello World!" + this.name);
    }
}

1.2 自动配置类

这个是自动配置类,用于嵌入引用者的springboot中去

/**
 * @description: 配置类,一般是这个jar包的所有配置和使用对象
 * @author: 沈琪
 **/
@Configuration
@EnableConfigurationProperties
@ConditionalOnBean(value = ProviderRemark.class)
public class ProviderConfiguration {

    //属性注入,配置到被引用的项目中
    @Value("${my.name}")
    private String name;

    //暴露出服务的提供类,让其可以被外部工程注入
    @Bean
    ProviderService getInstance() {
        return new ProviderService(name);
    }
}

1.3 Enable注解及开关类

适用于外部工程,用于显示启用该starter,

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import({ProviderRemark.class})  //引入开关,打开自动装配
public @interface EnableProvider {
}
public class ProviderRemark {
}

2. 外部工程

//显示开启这个starter
@EnableProvider
@SpringBootApplication
public class TestApplication implements ApplicationContextAware, CommandLineRunner {


    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    private static ApplicationContext ctx;

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        ctx = applicationContext;
    }

    @Override
    public void run(String... args) throws Exception {
	//这里就可以使用到starter中的方法了
        ProviderConfiguration providerConfiguration = ctx.getBean(ProviderConfiguration.class);
        System.out.println(providerConfiguration == null);
        ProviderService providerService = ctx.getBean(ProviderService.class);
        providerService.mainService();
    }
}