关于#spring#的问题,如何解决?

spring-boot-starter-mail 这个架包的配置我不想写在配置文件里,我想写在代码里让配置自动装配

img

SpringBoot 的核心注解是 SpringBootApplication。
@SpringBootApplication注解包含

@Configuration:允许在上下文中注册额外的 bean 或导入其他配置类
@EnableAutoConfiguration:启用 SpringBoot 的自动配置机制
@ComponentScan:扫描被@Component (@Service,@Controller)注解的 bean,注解默认会扫描启动类所在的包下所有的类 ,可以自定义不扫描某些 bean
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@ComponentScan
@EnableAutoConfiguration
public @interface SpringBootApplication {

}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@ComponentScan
@EnableAutoConfiguration
public @interface SpringBootApplication {

}

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface SpringBootConfiguration {
}

从源码中可以知道,最关键的注解是

@Import(EnableAutoConfigurationImportSelector.class),借助EnableAutoConfigurationImportSelector,@EnableAutoConfiguration可以帮助Spring Boot应用将所有符合条件的@Configuration配置都加载到当前SpringBoot创建并使用的IoC容器。

同时借助于Spring框架原有的一个工具类:SpringFactoriesLoader,@EnableAutoConfiguration就可以实现智能的自动配置。

SpringFactoriesLoader中加载配置,SpringFactoriesLoader属于Spring框架私有的一种扩展方案,其主要功能就是从指定的配置文件META-INF/spring.factories加载配置,

即根据@EnableAutoConfiguration的完整类名org.springframework.boot.autoconfigure.EnableAutoConfiguration作为查找的Key,获取对应的一组@Configuration类

@EnableAutoConfiguration作用就是从classpath中搜寻所有的META-INF/spring.factories配置文件,并将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

这些功能配置类要生效的话,会去classpath中找是否有该类的依赖类(也就是pom.xml必须有对应功能的jar包才行)并且配置类里面注入了默认属性值类,功能类可以引用并赋默认值。

生成功能类的原则是自定义优先,没有自定义时才会使用自动装配类。

生效需要的条件:

spring.factories里面有这个类的配置类(一个配置类可以创建多个围绕该功能的依赖类)
pom.xml里面需要有对应的jar包

img

那你就写个配置类,然后初始化个@bean方法

img


如同下面代码:

`


import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

/**
 * SpringBoot-RestTemplate实现调用第三方API
 */
@Configuration
@Component
public class RestTemplateConfig {
    @Bean
    @LoadBalanced //使RestTemplate请求支持负载均衡
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        RestTemplate restTemplate = builder.build();
        return restTemplate;
    }
}

public static void updateYamlFile() {
    String src = "src/main/resources/application.yml";//路径
    Yaml yaml = new Yaml();
    FileWriter fileWriter = null;
    //层级map变量
    Map<String, Object> springMap, dataSourceMap, resultMap,helperDialect;
    try {
        //读取yaml文件,默认返回根目录结构
        resultMap = (Map<String, Object>) yaml.load(new FileInputStream(new File(src)));
        //get出spring节点数据
        springMap = (Map<String, Object>) resultMap.get("spring");
        //get出数据库节点数据
        dataSourceMap = (Map<String, Object>) springMap.get("datasource");
        
        dataSourceMap.put("host", "");
        //登录名
        dataSourceMap.put("username", "");
        //密码
        dataSourceMap.put("password", "");
        //字符输出
        fileWriter = new FileWriter(new File(src));
        //用yaml方法把map结构格式化为yaml文件结构
        fileWriter.write(yaml.dumpAsMap(resultMap));
        //刷新
        fileWriter.flush();
        //关闭流
        fileWriter.close();
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("对不起,yaml文件修改失败!");
    }
}

是这样吗?

直接定义一个配置类如下:


@Component
public class MailConfig {

    @Value("${spring.mail.host:默认值}")
    private String mailHost;
    
    @Value("${spring.mail.username:默认值}")
    private String mailUsername;
    
    @Value("${spring.mail.password:默认值}")
    private String mailPassword;
    
    @Value("${spring.mail.port:443}")
    private int port;

    public String getMailHost() {
        return mailHost;
    }

    public void setMailHost(String mailHost) {
        this.mailHost = mailHost;
    }

    public String getMailUsername() {
        return mailUsername;
    }

    public void setMailUsername(String mailUsername) {
        this.mailUsername = mailUsername;
    }

    public String getMailPassword() {
        return mailPassword;
    }

    public void setMailPassword(String mailPassword) {
        this.mailPassword = mailPassword;
    }

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    @Override
    public String toString() {
        return "MailConfig [mailHost=" + mailHost + ", mailUsername=" + mailUsername + ", mailPassword=" + mailPassword
                + ", port=" + port + ", toString()=" + super.toString() + "]";
    }
}

注意修改代码中标注为默认值的代码为你配置文件的代码,然后保存即可。
当然如果那天你的mail服务器地址发生了变化,你也可以打开配置文件编辑好配置,然后重启即可。
这种方式即解决了你把默认配置写入代码的问题,同时也满足日后启用配置。

另外当程序启动时会通过 Component 注解自动把配置注入到mail组件配置上去

声明个配置类就行了,把这些信息当成属性放到类中即可,这样程序初始化就能自动加载


@bean