需要建个类实现BeanDefinitionRegistryPostProcessor接口下的postProcessBeanDefinitionRegistry方法就行,代码如下
import cn.linkengine.pre.service.config.bean.annotation.ProfileComponent;
import lombok.extern.log4j.Log4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import java.util.Arrays;
import java.util.List;
/**
* 对bean进行自定义的处理
* 删除有ProfileComponent注解且其profile的值其不符合给定的profiles的bean
* @author: yuhh
* @create: 2019-01-15 13:22
**/
@Log4j
public class ProfileConfigBean implements BeanDefinitionRegistryPostProcessor {
private List<ProfileType> profiles;
public List<ProfileType> getProfiles() {
return profiles;
}
public void setProfiles(List<ProfileType> profiles) {
this.profiles = profiles;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
// 获取所有beanDefinitionNames
String[] beanDefinitionNames = registry.getBeanDefinitionNames();
BeanDefinition beanDefinition;
ProfileComponent profileComponent;
Class cls;
String className;
for (String beanDefinitionName : beanDefinitionNames){
// 根据beanDefinitionName获取BeanDefinition
beanDefinition = registry.getBeanDefinition(beanDefinitionName);
// 根据BeanDefinition获取其className
className = beanDefinition.getBeanClassName();
if (StringUtils.isEmpty(className)){
continue;
}
try {
// 根据className获取其Class
cls = Class.forName(className);
// 获取Class上的ProfileComponent注解
profileComponent = AnnotationUtils.findAnnotation(cls, ProfileComponent.class);
// 如果有ProfileComponent注解且其profile的值不在给定的profiles里,那就把它删除
if (profileComponent != null && !CollectionUtils.containsAny(profiles, Arrays.asList(profileComponent.profile()))){
registry.removeBeanDefinition(beanDefinitionName);
}
} catch (ClassNotFoundException e) {
log.error("自定义初始化bean出现异常", e);
}
}
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
}
ProfileComponent接口如下
import cn.linkengine.pre.service.config.bean.ProfileType;
import org.springframework.stereotype.Component;
import java.lang.annotation.*;
/**
* @author: yuhh
* @create: 2019-01-15 14:38
**/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface ProfileComponent {
String value() default "";
ProfileType[] profile() default {};
}
最后需要把ProfileConfigBean 注册成bean
import lombok.extern.log4j.Log4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import java.util.ArrayList;
import java.util.List;
/**
* @Auther: yuhh
* @Date: 2018/5/18 14:45
*/
@Configuration
@Log4j
public class InitBeanConfig {
@Bean
@Profile("redis")
public ProfileConfigBean myConfigBeanByRedis(){
log.info("激活redis环境成功。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");
ProfileConfigBean profileConfigBean = new ProfileConfigBean();
List<ProfileType> profiles = new ArrayList<>();
profiles.add(ProfileType.REDIS);
profileConfigBean.setProfiles(profiles);
return profileConfigBean;
}
@Bean
@Profile("guava")
public ProfileConfigBean myConfigBeanByGuava(){
log.info("激活guava环境成功。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");
ProfileConfigBean profileConfigBean = new ProfileConfigBean();
List<ProfileType> profiles = new ArrayList<>();
profiles.add(ProfileType.GUAVA);
profileConfigBean.setProfiles(profiles);
return profileConfigBean;
}
}
pom中需要定义相应的profile
<profiles>
<profile>
<id>guava</id>
<properties>
<profileCache>guava</profileCache>
</properties>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
</profile>
<profile>
<id>redis</id>
<properties>
<profileCache>redis</profileCache>
</properties>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
</profile>
</profiles>
当在启动时maven的profile选择redis时,就会把ProfileComponent 注解上profile为ProfileType.REDIS的bean初始化,而profile不为ProfileType.REDIS的bean则会被舍弃
ProfileType枚举为
/**
* @Auther: yuhh
* @Date: 2019/1/15 17:00
*/
public enum ProfileType {
/**
* 使用redis
*/
REDIS,
/**
* 使用guava
*/
GUAVA
}
例子
package cn.linkengine.pre.service.template.cache.dictionary;
import cn.linkengine.pre.service.config.bean.ProfileType;
import cn.linkengine.pre.service.config.bean.annotation.ProfileComponent;
/**
* @program: pre-service
* @author: yuhh
* @create: 2019-01-15 15:34
**/
@ProfileComponent(profile = ProfileType.GUAVA)
public class BaseDictionaryCacheByGuava extends BaseDictionaryCache {
}
package cn.linkengine.pre.service.template.cache.dictionary;
import cn.linkengine.pre.service.config.bean.ProfileType;
import cn.linkengine.pre.service.config.bean.annotation.ProfileComponent;
/**
* @program: pre-service
* @author: yuhh
* @create: 2019-01-15 15:19
**/
@ProfileComponent(profile = ProfileType.REDIS)
public class BaseDictionaryCacheByRedis extends BaseDictionaryCache {
}
当指定ProfileConfigBean 的profiles为ProfileType.REDIS时,BaseDictionaryCacheByGuava 会被舍弃,BaseDictionaryCacheByRedis 会注册成功
说白了ProfileComponent注解就是Component注解和Profile注解的结合体