Spring中一些类的使用理解

1、ImportBeanDefinitionRegistrar接口

  该接口用来实现动态注入Bean,可以实现该接口,但是还要利用@Import进行导入才能实现Bean的注入。使用示例如下:

  定义一个注解:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(EnableJedisClusterClients.class)
@Import(JedisClusterClientRegistrar.class)
public @interface EnableJedisClusterClient {
    String namespace() default "default";
}

  然后实现该接口中的方法:

public class JedisClusterClientRegistrar implements ImportBeanDefinitionRegistrar {
    @Override
    public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
        boolean processed = false;
        {
            AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata
                    .getAnnotationAttributes(EnableJedisClusterClient.class.getName()));
            if (attributes != null) {
                dealOne(registry, attributes);
                processed = true;
            }
        }
        {
            AnnotationAttributes attributes = AnnotationAttributes.fromMap(importingClassMetadata
                    .getAnnotationAttributes(EnableJedisClusterClients.class.getName()));
            if (attributes != null) {
                AnnotationAttributes[] annotationArray = attributes.getAnnotationArray("value");
                if (annotationArray != null && annotationArray.length > 0) {
                    for (AnnotationAttributes oneAttributes : annotationArray) {
                        dealOne(registry, oneAttributes);
                        processed = true;
                    }
                }
            }
        }
        if (!processed)
            throw new IllegalStateException("no @EnableJedisClusterClient or @EnableJedisClusterClients found! pls check!");
    }

    private void dealOne(BeanDefinitionRegistry registry, AnnotationAttributes oneAttributes) {
        String namespace = oneAttributes.getString("namespace");
        Assert.isTrue(StringUtils.isNotEmpty(namespace), "namespace must be specified!");
        BeanRegistrationUtil.registerBeanDefinitionIfBeanNameNotExists(registry, namespace + JedisClusterClient.class.getSimpleName(), JedisClusterClientFactoryBean.class);
    }

  在启动类上添加该注解,在SpringApplication启动时注入Bean:

@EnableJedisClusterClient(namespace = "shua-day-walk")
@EnableRocketMQConsumer(namespace = OrderPaySuccessConsumer.ORDER_PAY_SUCCESS_CONSUMER)
@EnableDataSource(namespace = "shua-day-walk",mapperPackages = "com.coohua.day.walk.mapper")
@EnableScheduling
@EnableAsync
public class ShuaDayWalkApplication {
    public static void main(String[] args) {
        SpringApplication.run(ShuaDayWalkApplication.class, args);
    }

2、ApplicationContextAware接口

  该接口主要有一个方法,就是为了将ApplicationContext设置到实现类中,从而可以让实现类对整个容器进行相应操作,但是实现类只有在被加载时,Spring才会自动调用设置方法。使用示例如下:

public class CustomizedConfigurationPropertiesBinder implements ApplicationContextAware {
    private ConfigurableApplicationContext applicationContext;
    private PropertySources propertySources;
    private Binder binder;

    public void bind(String configPrefix, Bindable<?> bean) {
        BindHandler handler = new IgnoreTopLevelConverterNotFoundBindHandler();
        this.binder.bind(configPrefix, bean, handler);
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = (ConfigurableApplicationContext) applicationContext;
        this.propertySources = this.applicationContext.getEnvironment().getPropertySources();
        this.binder = new Binder(getConfigurationPropertySources(), getPropertySourcesPlaceholdersResolver(),
                getConversionService(), getPropertyEditorInitializer());
    }

    private Iterable<ConfigurationPropertySource> getConfigurationPropertySources() {
        return ConfigurationPropertySources.from(this.propertySources);
    }

    private PropertySourcesPlaceholdersResolver getPropertySourcesPlaceholdersResolver() {
        return new PropertySourcesPlaceholdersResolver(this.propertySources);
    }

    private ConversionService getConversionService() {
        return this.applicationContext.getBeanFactory().getConversionService();
    }

    private Consumer<PropertyEditorRegistry> getPropertyEditorInitializer() {
        return this.applicationContext.getBeanFactory()::copyRegisteredEditorsTo;
    }
}

  实现类的加载:定义Configuration,并在其中将实现类通过@Bean注入,然后在spring.factories中配置该Configuration。

@Order(1)
public class CustomizedPropertiesBinderAutoConfiguration {
    @Bean
    public CustomizedConfigurationPropertiesBinder customizedConfigurationPropertiesBinder() {
        return new CustomizedConfigurationPropertiesBinder();
    }
}

    

 

posted @ 2021-02-08 11:04  jingyi_up  阅读(90)  评论(0编辑  收藏  举报