在spring工程中,所有的bean都是由spring来管理的,我们通常会基于注解来实现Bean的单例。但是有的情况下,我们需要动态的来创建这个bean,还要注册到spring容器,让spring容器来管理。
例如,我们在使用阿里云的oss的时候,有的时候由于我们有多个Bucket所以需要创建多个oss的对象。这里我们可以基于BeanFactoryPostProcessor来实现这个功能。
@Data
@ConfigurationProperties(prefix = "aliyun.oss")
public class AliYunOssProperties {
private Boolean enabled;
private Map<String, AliYunOssInstantProperties> instance;
}
@Data
public class AliYunOssInstantProperties {
private String beanName;
private String accessKeyId;
private String accessKeySecret;
private String bucketName;
private String endpoint;
private String urlPrefix;
}
@Configuration
@ConditionalOnProperty(prefix = "aliyun.oss", value = {"enabled"}, havingValue = "true")
@EnableConfigurationProperties(value = {
AliYunOssProperties.class
})
public class AliYunOssConfiguration implements EnvironmentAware, BeanFactoryPostProcessor {
private AliYunOssProperties ossProperties;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {
DefaultListableBeanFactory beanFactory = (DefaultListableBeanFactory) configurableListableBeanFactory;
ossProperties.getInstance().forEach((key, props) -> {
OSS oss = new OSSClientBuilder().build(props.getEndpoint(), props.getAccessKeyId(), props.getAccessKeySecret());
OssProperties ossProperties = new OssProperties();
ossProperties.setBucketName(props.getBucketName());
ossProperties.setUrlPrefix(props.getUrlPrefix());
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(AliYunOSS.class);
beanDefinition.setBeanClassName(AliYunOSS.class.getName());
ConstructorArgumentValues argumentValues = new ConstructorArgumentValues();
argumentValues.addIndexedArgumentValue(0, oss);
argumentValues.addIndexedArgumentValue(1, ossProperties);
beanDefinition.setConstructorArgumentValues(argumentValues);
beanFactory.registerBeanDefinition(StringUtils.isNotBlank(props.getBeanName()) ? props.getBeanName() : key + "_aliyunOSS", beanDefinition);
});
}
@Override
public void setEnvironment(Environment environment) {
ossProperties = Binder.get(environment).bind("aliyun.oss", AliYunOssProperties.class).get();
}
}