Author 罗先生
本文是IOC系列的第五篇,往期回顾:

ImportAware是什么

实现了这个接口的类,在其setImportMetadata方法中可以拿到某个bean上的注解上的属性值

ImportAware例子-动态注入数据源:

先来个注解,让数据源的注入成为可开关,就和AOP的@EnableAspectJAutoProxy类似

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import({DynamicDateSourceImportAwareBeanPostProcessor.class})
public @interface EnnableDbConfig {
    String userName() default "";

    String password() default "";

    String url() default "";

}

值得注意的是需要注入@Import下面自定义的DynamicDateSourceImportAware 类
为什么要Import进来?而不是直接扫描?

如果是我们自己的项目自己写的当然可以扫描进来,但是如果是第三方的包,就需要用Import进来了。可看第三部分实际应用RedissonHttpSessionConfiguration 就是需要Import进项目里的,不然setImportMetadata就不会执行了

再来一个自定义实现ImportAware 接口的核心类,实现数据源的动态注入,核心方法在于setImportMetadata

@Configuration
public class DynamicDateSourceImportAware implements ImportAware {
    private String userName;

    private String password;

    private String url;

    public void setImportMetadata(AnnotationMetadata annotationMetadata) {

        Map<String, Object> map = annotationMetadata.getAnnotationAttributes(EnnableDbConfig.class.getName());
        AnnotationAttributes attrs = AnnotationAttributes.fromMap(map);
        this.userName = attrs.getString("userName");
        this.password = attrs.getString("password");
        this.url = attrs.getString("url");
    }

    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource driverManagerDataSource = new DriverManagerDataSource();
        driverManagerDataSource.setPassword(password);
        driverManagerDataSource.setUsername(userName);
        driverManagerDataSource.setUrl(url);
        driverManagerDataSource.setDriverClassName("com.mysql.jdbc.Driver");
        return driverManagerDataSource;
    }
}

值得注意的是DynamicDateSourceImportAware 类必须用@Configuration注解标注,否则setImportMetadata不会执行,也就拿不到数据源信息了
最后则是使用

@Configuration
@EnableAspectJAutoProxy
@EnnableDbConfig(userName = "root", password = "root", url = "jdbc:mysql://localhost:3306/test")
@ComponentScan("cn.study.lqw")
public class Appconfig {
    @Bean
    public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean;
    }
}

这样Spring就存在一个你想要的数据源了,不信的小伙伴可以自己测试

ImportAware实际应用:

Spring当中有一个@EnableRedissonHttpSession注解,其上可指定key和对应的key的过期时间,原理就是ImportAware接口,源码如下:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Import({RedissonHttpSessionConfiguration.class})
@Configuration
public @interface EnableRedissonHttpSession {
    int maxInactiveIntervalInSeconds() default 1800;
 
    String keyPrefix() default "";
}
@Configuration
public class RedissonHttpSessionConfiguration extends SpringHttpSessionConfiguration implements ImportAware {
    private Integer maxInactiveIntervalInSeconds;
    private String keyPrefix;
 
...
    public void setImportMetadata(AnnotationMetadata importMetadata) {
        Map<String, Object> map = importMetadata.getAnnotationAttributes(EnableRedissonHttpSession.class.getName());
        AnnotationAttributes attrs = AnnotationAttributes.fromMap(map);
        this.keyPrefix = attrs.getString("keyPrefix");
        this.maxInactiveIntervalInSeconds = (Integer)attrs.getNumber("maxInactiveIntervalInSeconds");
    }
}

看懂了我的代码,这个代码就很好看懂了。。 和我几乎是一样的