掃描自定義註解並在spring容器中注入自定義bean
阿新 • • 發佈:2019-03-29
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());
});