1. 程式人生 > >掃描自定義註解並在spring容器中注入自定義bean

掃描自定義註解並在spring容器中注入自定義bean

開發十年,就只剩下這套架構體系了! >>>   

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName ModelInital
 * @Description 初始化註釋Model
 * @Date 2019/3/28 0028 15:14
 * @Version 0.1
 **/
@Component
public class ModelInital {

    @Autowired
    private ConfigurableListableBeanFactory beanFactory;

    @Autowired
    private ApplicationContext applicationContext;


    private static final String RESOURCE_PATTERN = "com.xxx";

    /**
     * 初始化方法
     */
    @PostConstruct
    public void init() {
        // 使用自定義掃描類,針對@Model進行掃描
        AnnotationScanner scanner = AnnotationScanner.getScanner((BeanDefinitionRegistry) beanFactory, Model.class);
        scanner.doScan(RESOURCE_PATTERN).forEach(beanDefinitionHolder -> {
                    Object o = applicationContext.getBean(beanDefinitionHolder.getBeanName());
                    Class<?> clazz = o.getClass();
                    Model model = clazz.getAnnotation(Model.class);
                    String  newName = model.tableName();
                    Map<Object, Object> map = new HashMap<>();
                    if (!StringUtils.isEmpty(newName)) {
//自己業務邏輯產生的結果Map(我這裡是獲取表的註釋)
                        map = xxxservice.findComments(newName);
                    }
                    for (; clazz != Object.class; clazz = clazz.getSuperclass()) {
                        try {
                            Field[] fields = clazz.getDeclaredFields();
                            for (Field field : fields) {
                                field.setAccessible(true);
                                ModelProperty modelProperty = field.getAnnotation(ModelProperty.class);
                                if (modelProperty != null && !StringUtils.isEmpty(modelProperty.value())) {
                                    map.put(field.getName(), modelProperty.value());
                                }
                            }

                        } catch (Exception e) {
                            //doNothing
                        }
                    }
                    //重新注入
            if (StringUtils.isEmpty(newName)) {
                newName = StringUtils.underscoreName(beanDefinitionHolder.getBeanName());
            }
            ((BeanDefinitionRegistry) beanFactory).removeBeanDefinition(beanDefinitionHolder.getBeanName());
            GenericBeanDefinition beanDef = new GenericBeanDefinition();
            beanDef.setBeanClass(Map.class);
            beanDef.setPropertyValues(new MutablePropertyValues(map));
            ((BeanDefinitionRegistry) beanFactory).registerBeanDefinition(newName, beanDef);
        });
    }
}
import lombok.Setter;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.filter.AnnotationTypeFilter;

import java.lang.annotation.Annotation;
import java.util.Set;

/**
 * @ClassName AnnotationScanner
 * @Description 自定義Model註解掃描器
 * @Date 2019/3/28 0028 14:44
 * @Version 0.1
 **/
public class AnnotationScanner extends ClassPathBeanDefinitionScanner {
    /**
     * 實體類對應的AnnotationClazz
     */
    @Setter
    private Class<? extends Annotation> selfAnnotationClazz;

    /**
     * 傳值使用的臨時靜態變數
     */
    private static Class<? extends Annotation> staticTempAnnotationClazz = null;

    /**
     * 因建構函式無法傳入指定的Annotation類,需使用靜態方法來呼叫
     * @param registry
     * @param clazz
     * @return
     */
    public static synchronized AnnotationScanner getScanner(BeanDefinitionRegistry registry, Class<? extends Annotation> clazz){
        staticTempAnnotationClazz = clazz;
        AnnotationScanner scanner = new AnnotationScanner(registry);
        scanner.setSelfAnnotationClazz(clazz);
        return scanner;
    }

    private AnnotationScanner(BeanDefinitionRegistry registry) {
        super(registry);
    }

    // 建構函式需呼叫函式,使用靜態變數annotationClazz傳值
    @Override
    public void registerDefaultFilters() {
        // 新增需掃描的Annotation Class
        this.addIncludeFilter(new AnnotationTypeFilter(staticTempAnnotationClazz));
    }

    // 以下為初始化後呼叫的方法
    @Override
    public Set<BeanDefinitionHolder> doScan(String... basePackages) {
        return super.doScan(basePackages);
    }

    @Override
    public boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        return super.isCandidateComponent(beanDefinition)
                && beanDefinition.getMetadata().hasAnnotation(this.selfAnnotationClazz.getName());
    }
}

import java.lang.annotation.*;

/**
 * @ClassName Model
 * @Description 轉換類實體註解
 * @Date 2019/3/28 0028 11:10
 * @Version 0.1
 **/
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface Model {
    /**
     * 表名
     * @return
     */
    String tableName() default "";
}
import java.lang.annotation.*;

/**
 * @ClassName ModelProperty
 * @Description 實體屬性註解
 * @Date 2019/3/28 0028 11:13
 * @Version 0.1
 **/
@Target({ElementType.FIELD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface ModelProperty {

    /**
     * 對應的欄位名
     * @return
     */
    String value() default "";
}

使用方式就是讓spring掃描到改元件

在自己的Pojo上面註解@Model就可以將model的相關注釋@ModelProperty注入到spring容器中

使用的時候直接從spring容器中取就可以了

MutablePropertyValues mutablePropertyValues =  beanFactory.getBeanDefinition(剛剛自定義的名字).getPropertyValues();
                    Map<String, Object> commentsMap = new HashMap<>();
                    mutablePropertyValues.forEach(propertyValue -> {
                        commentsMap.put(propertyValue.getName(), propertyValue.getValue());
                    });