概述
@Value
、@PropertySource
注解中使用${}
引用配置文件参数原理分析-
问题分析
平时在使用
@Value
和@PropertySource
两个注解(下面分别用V和P代替)时都可以在value中使用${xxx.xxx}
方式获取配置文件的值,这样可以使程序根据配置文件动态设置一些值,比如数据库连接的url,username,password或者环境变量等。
但是有时候自己实现的切面注解中也想能使用这样的方式动态配置,这就需要Spring环境变量的解析支持了。
这两个注解的解析过程
V是在spring-bean中,P是在spring-context中,但是他们的${}
解析过程都需要依赖Environment
提供的环境解析public abstract class AbstractPropertyResolver implements ConfigurablePropertyResolver {
.....
@Override
public String resolvePlaceholders(String text) {
return this.propertyResolver.resolvePlaceholders(text);
}
@Override
public String resolveRequiredPlaceholders(String text) throws IllegalArgumentException {
return this.propertyResolver.resolveRequiredPlaceholders(text);
}
....
}
就是
resolvePlaceholders
这个方法解析${}
里的参数的。加入到自己的注解中
Spring中有个
EnvironmentAware
接口,他的作用就是在任何实现了这个接口的类中注入Environment
对象,就可以在自己的类中使用这个对象的功能了,还有ApplicationContextAware
,SchedulerContextAware
等等,通过搜索spring-framework的源代码可以看到所有Spring可以对外提供的这些内部工具接口。
使用方法很简单 ```java import java.lang.annotation.*;
@Target(ElementType.METHOD) @Documented @Retention(RetentionPolicy.RUNTIME) public @interface Login { String username() default “”; String password() default “”; }
public class AspectDemo implements EnvironmentAware { Environment environment;
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
}
@Pointcut("@annotation(com.watson.onebox.aspect.annotations.Login)")
public void logPointCut() {
}
@Before(value = "logPointCut()")
public void check(){
log.info("check");
}
@After(value = "logPointCut()")
public void bye(){
log.info("bye");
}
@Around("logPointCut() && @annotation(login)")
public Object around(ProceedingJoinPoint joinPoint, Login login){
log.info("around");
//关键的就是这一行解析代码
String s = environment.resolvePlaceholders(login.username());
log.info("username: {}", login.username());
log.info("username-resolve: {}", s);
//输出使用login注解时候的passwo属性值
log.info("password: {}", login.password());
Object proceed = null;
try {
proceed = joinPoint.proceed();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
return proceed;
}
}
这个就是完整的一个自己实现切面注解解析过程的代码。这样在使用注解时就可以通过`${xxx.xxx}`方式加载配置文件参数了<br />下面是测试代码,使用SpringBoot启动就可以了
```java
@Slf4j
@Component
public class TestMethod {
@Login(username = "abc-${spring.profiles.active}", password = "b")
public String getData() {
log.info("get data");
return "getData";
}
}