springboot 自动配置原理

SpringBoot的自动配置就是当spring容器启动后,一些配置类、bean对象就自动存入到了IOC容器中,不需要我们手动去声明,从而简化了开发,省去了繁琐的配置操作

研究springboot原理就是研究在springboot项目中我们引入maven依赖后,是如何将依赖jar包中所定义的配置类,以及bean加载到springIOC容器当中。

先在pom.xml中引入对应的坐标,重新加载maven,如下自定义了一个模块,通过maven将其引入到当前模块中。

<dependency>
    <groupId>com.example</groupId>
    <artifactId>itheima-utils</artifactId> 
    <version>0.0.1-SNAPSHOT</version>
</dependency>

现在测试方法中判断是否能够获取在itheima-utils模块中声明的bean。利用applicationContextgetBean方法

@Autowired
    private ApplicationContext applicationContext; //IOC容器对象

public void testBean(){
        System.out.println(applicationContext.getBean(TokenParser.class));
}

报错不能找到com.example。解决方法:点开Mavenitheima-utils双击生命周期,双击install,重新加载。

发现并不能获取到在itheima-utils模块中TokenParser类中通过@Component注解声明的bean对象。这是因为在当前测试类中的启动方法上的@SpringBootApplication只能扫描到当前包及其子包。有如下两种方案解决:

方案一·:

@ComponentScan 组件扫描

@ComponentScan({"com.itheima","com.example"})
@SpringBootApplication
public class SpringbootWebConfig2Application {

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

这种方法较为繁琐,因为每次获取到依赖jar包中所定义的配置类,以及bean,都需要配置扫描的包名

方法二:

@Import 导入。使用@Import导入的类会被Spring加载到IOC容器中,导入形式主要有以下几种:

1.导入 普通类

@Import({TokenParser.class})

TokenParser为JAR包的普通类

2.导入 配置类

@Import({HeaderConfig.class})
@Configuration
public class HeaderConfig {

    @Bean
    public HeaderParser headerParser(){
        return new HeaderParser();
    }

    @Bean
    public HeaderGenerator headerGenerator(){
        return new HeaderGenerator();
    }
}

如果要管理的bean对象来自于第三方(不是自定义的),是无法用 @Component 及衍生注解声明bean的,就需要用到 @Bean注解。

若要管理的第三方bean对象,建议对这些bean进行集中分类配置,可以通过 @Configuration 注解声明一个配置类。

通过@Bean注解的name或value属性可以声明bean的名称,如果不指定,默认bean的名称就是方法名。

如果第三方bean需要依赖其它bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配

3.导入 ImportSelector 接口实现类

@Import({MyImportSelector.class})
public class MyImportSelector implements ImportSelector {
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.example.HeaderConfig"};
    }
}

4.在第三方JAR包中实现@EnableHeaderConfig注解

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Import(MyImportSelector.class)
public @interface EnableHeaderConfig {
}

使用时只需要让启动类上加上@EnableHeaderConfig

自定义starter

实际开发中,经常会定义一些公共组件,提供给各个项目团队使用。而在SpringBoot的项目中,一般会将这些公共组件封装为SpringBootstarter

步骤:

1.创建 aliyun-oss-spring-boot-starter 模块

starter不需要任何的JAVA代码只需要引入autoconfigure的Maven依赖

<dependency>
			<groupId>com.aliyun.oss</groupId>
			<artifactId>aliyun-oss-spring-boot-autoconfigure</artifactId>
			<version>0.0.1-SNAPSHOT</version>
		</dependency>

2.创建 aliyun-oss-spring-boot-autoconfigure 模块

先实现一个POJO类定义,如本例的AliOSSProperties,提供对应的GET,SETTER方法,并加上@ConfigurationProperties(prefix = "aliyun.oss"),以便后续在yml文件中配置属性信息。

在实现一个工具类,完成静态方法的封装:

public class AliOSSUtils {
    private AliOSSProperties aliOSSProperties;
    public AliOSSProperties getAliOSSProperties() {
        return aliOSSProperties;
    }
    public void setAliOSSProperties(AliOSSProperties aliOSSProperties) {
        this.aliOSSProperties = aliOSSProperties;
    }
    /**
     * 实现上传图片到OSS
     */
    public String upload(MultipartFile file) throws IOException {
        //获取阿里云OSS参数
        String endpoint = aliOSSProperties.getEndpoint();
        String accessKeyId = aliOSSProperties.getAccessKeyId();
        String accessKeySecret = aliOSSProperties.getAccessKeySecret();
        String bucketName = aliOSSProperties.getBucketName();
        // 获取上传的文件的输入流
        InputStream inputStream = file.getInputStream();
        // 避免文件覆盖
        String originalFilename = file.getOriginalFilename();
        String fileName = UUID.randomUUID().toString() + originalFilename.substring(originalFilename.lastIndexOf("."));
        //上传文件到 OSS
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, inputStream);
        //文件访问路径
        String url = endpoint.split("//")[0] + "//" + bucketName + "." + endpoint.split("//")[1] + "/" + fileName;
        // 关闭ossClient
        ossClient.shutdown();
        return url;// 把上传到oss的路径返回
    }
}

在实现自动配置类

@Configuration
@EnableConfigurationProperties(AliOSSProperties.class)
public class AliOSSAutoConfiguration {
    @Bean
    public AliOSSUtils aliOSSUtils(AliOSSProperties aliOSSProperties){ // 如果第三方bean需要依赖其它bean对象,直接在bean定义方法中设置形参即可,容器会根据类型自动装配
        AliOSSUtils aliOSSUtils = new AliOSSUtils();
        aliOSSUtils.setAliOSSProperties(aliOSSProperties);
        return aliOSSUtils;
    }
}

3.在 aliyun-oss-spring-boot-autoconfigure 模块中自定义自动配置功能,并定义resources下的META-INF下的spring目录的org.springframework.boot.autoconfigure.AutoConfiguration.imports

在该文件下的全类名类会被Spring加载到IOC容器中

com.aliyun.oss.AliOSSAutoConfiguration

这样在使用中只需要引入starter,在yml文件中配置所需要的信息即可