package com.hundsun.jresplus.beans.config; import java.util.HashSet; import java.util.Set; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import com.hundsun.jresplus.common.util.StringUtil; /** * * 功能描述: 抽取bean复写的逻辑到此类中<br> */ public class BeanOverrideHandler { private final static Logger logger = LoggerFactory .getLogger(BeanOverrideHandler.class); Set<String> bOverriderNames; Set<String> bOverridedNames; ConfigurableListableBeanFactory beanFactory; public BeanOverrideHandler(ConfigurableListableBeanFactory beanFactory) { super(); this.beanFactory = beanFactory; bOverriderNames = new HashSet<String>(); bOverridedNames = new HashSet<String>(); } public void beanOverride() { beansOverride(); removeOverrideBeanDef(); } private void beansOverride() { String[] names = beanFactory.getBeanDefinitionNames(); for (String beanName : names) { beanOverride(beanName); } } private void beanOverride(String beanName) { if (bOverridedNames.contains(beanName)) { return; } BeanDefinition beanDefinition = beanFactory.getBeanDefinition(beanName); String beanClassName = beanDefinition.getBeanClassName(); if (StringUtil.isBlank(beanClassName)) { return; } try { Class<?> cls = Class.forName(beanClassName); if (hasOverrideAnnotation(cls)) { bOverriderNames.add(beanName); checkOverrideClass(cls); beanDefinitionOverride(beanClassName, cls); } } catch (Exception e) { logger.warn("OverrideBeanFactory bean definition process error bean[" + beanDefinition.getBeanClassName() + "]," + e); } } private boolean hasOverrideAnnotation(Class<?> cls) { return cls.isAnnotationPresent(BeanOverride.class) == true; } private void checkOverrideClass(Class<?> cls) { if (isOverrideSuperClass(cls)) { return; } if (interfaceNotMatched(cls)) { logger.error("initializing sagahl horn conext server falied step OverrideBean: the class and override must implements the same interface! "); throw new RuntimeException( "initializing sagahl horn conext server falied step OverrideBean: the class and override must implements the same interface! "); } } private boolean isOverrideSuperClass(Class<?> cls) { return cls.getSuperclass() == cls.getAnnotation(BeanOverride.class) .override(); } private boolean interfaceNotMatched(Class<?> cls) { Class<?>[] overrideInterfaces = cls.getAnnotation(BeanOverride.class) .override().getInterfaces(); for (Class<?> overrideClsInterface : overrideInterfaces) { if (hasInterface(cls, overrideClsInterface)) { return false; } } return true; } private boolean hasInterface(Class<?> cls, Class<?> overrideClsInterface) { for (Class<?> clsInterface : cls.getInterfaces()) { if (overrideClsInterface == clsInterface) { return true; } } return false; } private void beanDefinitionOverride(String className, Class<?> cls) { Class<?> overrideCls = cls.getAnnotation(BeanOverride.class).override(); for (String beanName : getMatchedBean(overrideCls)) { setBeanClass(beanFactory, className, beanName); } } private void setBeanClass(ConfigurableListableBeanFactory beanFactory, String className, String beanName) { BeanDefinition beanDefinitionTemp = beanFactory .getBeanDefinition(beanName); beanDefinitionTemp.setBeanClassName(className); bOverridedNames.add(beanName); } private Set<String> getMatchedBean(Class<?> overrideCls) { String[] namesTemps = beanFactory.getBeanDefinitionNames(); Set<String> matchedBean = new HashSet<String>(); for (String nameTemp : namesTemps) { BeanDefinition beanDefinitionTemp = beanFactory .getBeanDefinition(nameTemp); if (overrideCls.getName().equals( beanDefinitionTemp.getBeanClassName())) { matchedBean.add(nameTemp); } } return matchedBean; } private void removeOverrideBeanDef() { for (String nameTemp : bOverriderNames) { if (beanFactory instanceof BeanDefinitionRegistry) { BeanDefinitionRegistry beanDefinitionRegistry = (BeanDefinitionRegistry) beanFactory; beanDefinitionRegistry.removeBeanDefinition(nameTemp); } } } }