 约定：

```xml
resources/app.yml（ 或 app.properties ） #为应用配置文件
```

 配置样例：


```yaml
track:
  name: xxx
  url: http://a.a.a
  db1:
    jdbcUrl: "jdbc:mysql://..."
    username: "xxx"
    password: "xxx"
```

 配置注入的表达式支持：

* `${xxx}` 注入属性
* `${xxx:def}` 注入属性，如果没有则提供 def 默认值。 //只支持单值接收（不支持集合或实体）
* `${classpath:xxx.yml}` 注入资源目录下的配置文件 xxx.xml

注入相关注解：

* `@Inject`，注入。可注解目标：字段，方法参数，类（配置类），方法（`@Bean`方法）
* `@BindProps`，绑定属性。可注解目标：类（配置类），方法（`@Bean`方法）。//可以生成配置提示


如何配置参考：

[《应用常用配置说明》](/article/174)


### 1、如何通过注入获得配置？

* 注入到字段

```java
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

@Component
public class DemoService{
    //注入值（带默认值：demoApi），并开启自动更新（注意：如果不是单例，请不要开启自动刷新）
    @Inject(value="${track.name:demoApi}", autoRefreshed=true)
    static String trackName; //v3.0 后支持静态字段注入
    
    //注入值（没有时，不覆盖字段初始值）
    @Inject("${track.url}")
    String trackUrl = "http://x.x.x/track";
    
    //注入配置集合
    @Inject("${track.db1}")
    Properties trackDbCfg;
    
    //注入Bean（根据对应的配置集合自动生成并注入）
    @Inject("${track.db1}")
    HikariDataSource trackDs;
}
```

* 注入到一个配置类或实体类（之后可复用）

```java
import org.noear.solon.annotation.BindProps;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;

//@Inject("${classpath:user.config.yml}")  //也可以注入一个配置文件 
@Inject("${user.config}")  
@Configuration
public class UserProperties{
    public String name;
    public List<String> tags;
    ...
}

@BindProps(prefix="user.config")  //或者用绑定属性注解。v3.0.7 后支持
@Configuration
public class UserProperties{
    public String name;
    public List<String> tags;
    ...
}

@Configuration
public class DemoConfig {
    @BindProps(prefix="user.config") //或者用绑定属性注解。v3.0.7 后支持
    @Bean
    public UserProperties userProperties(){
        return new UserProperties();
    }
}

//别处，可以注入复用
@Inject
UserProperties userProperties;
```

* 注入到 `@Bean` 方法的参数（不支持自动刷新）

```java
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Condition;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;
import org.noear.solon.data.cache.CacheService;

@Configuration
public class DemoConfig{
    //提示：@Bean 只能与 @Configuration 配合
    @Bean 
    public DataSource db1(@Inject("${track.db1}") HikariDataSource ds) {
        return ds;
    }
    
    @Bean
    public DataSourceWrap db1w(@Inject DataSource ds, @Inject("${wrap}") WrapConfig wc) {
        return new DataSourceWrap(ds, wc);
    }
    
    //也可以带条件处理
    @Bean
    @Condition(onExpression="${cache.enable:false} == true") //有 "cache.enable" 属性值，且等于true
    public CacheService cache(@Inject("${cache.config}") CacheServiceSupplier supper){
       return supper.get();
    }
}
```

* 注入到组件的构造参数（即，构造函数注入）


```java
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

@Component
public class DemoConfig{
    private String demoName;
    
    public DemoConfig(@Inject("${deom.name}") String name) {
        this.demoName = name;
    }
}
```


### 2、如何手动获得配置？

* 给字段赋值

```java
import org.noear.solon.Solon;

public class DemoService{
    //获取值（带默认值：demoApi）
    static String trackName = Solon.cfg().get("track.name", "demoApi");
    //获取值
    static String trackUrl = Solon.cfg().get("track.url");
    
    //获取配置集合
    Properties trackDbCfg = Solon.cfg().getProp("track.db1");
    //获取bean（根据配置集合自动生成）
    HikariDataSource trackDs = Solon.cfg().getBean("track.db1", HikariDataSource.class);
}
```

* 用方法时实获取最新态（建议不要获取复杂的对象，避免构建的性能浪费）


```java
import org.noear.solon.Solon;

public class DemoService{
    //获取值（带默认值：demoApi）
    public static String trackName(){
        return Solon.cfg().get("track.name", "demoApi");
    }
    
    //获取值
    public static String trackUrl(){
        return Solon.cfg().get("track.url");
    }
}
```

* 构建Bean给配置器用

```java
import org.noear.solon.Solon;
import org.noear.solon.annotation.Bean;
import org.noear.solon.annotation.Configuration;
import org.noear.solon.annotation.Inject;

@Configuration
public class DemoConfig{
    @Bean
    public DataSource db1() {
        return Solon.cfg().getBean("track.db1", HikariDataSource.class);
    }
    
    @Bean
    public DataSourceWrap db1w(@Inject DataSource ds) {
        WrapConfig wc = Solon.cfg().getBean("wrap", WrapConfig.class)；
        
        return new DataSourceWrap(ds, wc);
    }
}
```



### 3、配置的自动刷新与手动订阅变更

* 自动刷新

"自动刷新"只适合于字段注入，以及单例的类。（注意：如果不是单例，请不要开启自动刷新）

```java
import org.noear.solon.Solon;
import org.noear.solon.annotation.Component;
import org.noear.solon.annotation.Inject;

@Component
public class DemoService{
    //注入值（带默认值：demoApi），并开启自动更新
    @Inject(value="${track.name:demoApi}", autoRefreshed=true)
    String trackName;
    
    //通过函数时时获取最新的（静态或动态，按需设定）
    public static String trackName2(){
        return Solon.cfg().get("track.name:demoApi");
    }
}
```

* 手动订阅变更

这个接口会订阅所有变更的key，需要自己过滤处理：

```java
import org.noear.solon.Solon;

Solon.cfg().onChange((key,val)->{
    if(key.startsWith("track.name")){ // "track.name" 表示前缀
        //...
    }
});
```



