Spring ImportAware构建一个功能开关

前言

在读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);
}

通过官网的介绍,大概能得出下面的结论:

  1. ImportAware 是给被@Configuration注解过的类用的,一般来说就是Appconfig.class这种配置类。
  2. 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操作也可以放进去做。只需要传入时间参数即可,可说这个接口给我们提供了除配置文件以外的一个很便利的外部传参的方法。

评论 12
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值