前言
在读Spring源码的时候偶然看到了这个类,它是在ImportAwareBeanPostProcessor这个后置处理器中使用的,用来设置某个类上的注解内容的。可以让我们在Import的过程中提供一些默认参数,进行初始化。我们可以使用这个接口和@Import一起做一个功能开关,比如希望在开启特定功能的时候就可以完成初始化过程,就可以使用这个接口。更多Spring内容进入【Spring解读系列目录】。感谢网友zjavax的回复,目前这个接口如果要用的话需要加上@Configuration
注解。
ImportAware
首先还是看看源码什么样子。根据源码上的注解,可以得知这个接口是给哪些具有@Configuration
注解的类使用的,并且希望能够注入一些AnnotationMetadata
使用的。并且官网也说了这个这个接口和@Import
一起使用非常的有用。
/**
* Interface to be implemented by any @{@link Configuration} class that wishes
* to be injected with the {@link AnnotationMetadata} of the @{@code Configuration}
* class that imported it. Useful in conjunction with annotations that
* use @{@link Import} as a meta-annotation.
*
* @author Chris Beams
* @since 3.1
*/
public interface ImportAware extends Aware {
/**
* Set the annotation metadata of the importing @{@code Configuration} class.
*/
void setImportMetadata(AnnotationMetadata importMetadata);
}
通过官网的介绍,大概能得出下面的结论:
- ImportAware 是给被
@Configuration
注解过的类用的,一般来说就是Appconfig.class
这种配置类。 - ImportAware 和
@Import
注解一起使用更好。
Sample
基于以上两点,我们可以写一个例子来做一个连接数据库的开关,当我开启这个功能时,数据库的连接内容就可以直接传入到项目里。假设有一个DBConnection
类用来存储数据库内容,自然他要实现ImportAware
。还要有一个开关@interface
的自定义注解来完成这个开关的功能。最后要把这个些都@Import
到项目中,所以要有一个Appconfig
类。
//@Component 旧版本可用,新版需要用@Configuration,下同
@Configuration
public class DBConnection implements ImportAware {
private String sqlUrl; //假设存的连接信息
private String dbUser; //假设存的用户名
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
//可以拿到已给注解上所有注解的属性值,并放到一个map中
Map<String, Object> map = importMetadata.getAnnotationAttributes(EnableMetadata.class.getName());
//从map中拿到注解的所有属性信息
AnnotationAttributes attrs = AnnotationAttributes.fromMap(map);
//取出注解中的值,并给全局变量赋值
this.sqlUrl=attrs.get("dbUrl").toString();
this.dbUser=attrs.get("dbUser").toString();
}
public String getDbUser() {
return dbUser;
}
public String getSqlUrl() {
return sqlUrl;
}
}
@Retention(RetentionPolicy.RUNTIME)
@Import(DBConnection.class) //导入连接类
public @interface EnableMetadata { //注解开关
String dbUrl() default "";
String dbUser() default "";
}
@Configuration
@ComponentScan("com.demo")
@EnableMetadata(dbUrl = "sqlUrl",dbUser = "username") //写入需要的值进入方法
public class AppConfig {
}
最后还有一个main方法,来测试我们是否可以取到,注解中传递进去的值。
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext anno=new AnnotationConfigApplicationContext(AppConfig.class);
DBConnection d=anno.getBean(DBConnection.class);
System.out.println("name:"+d.getDbUser()+"; sqlUrl:"+d.getSqlUrl());
}
}
输出,可以看到成功取到了外部传递进来的值。
name:username; sqlUrl:sqlUrl
举一反三
在这个例子里,DBConnection
传入了在注解上的值并打印了出去。这里完全可以在里面写一个方法,比如叫getConnection
的方法,把外部传入的值在里面进行数据库的初始化连接,让后返回一个SqlSession
对象出去给系统调用。或者我们可以实现对某些功能的限时timeout
操作也可以放进去做。只需要传入时间参数即可,可说这个接口给我们提供了除配置文件以外的一个很便利的外部传参的方法。