当前位置: 首页 > news >正文

扫描自定义注解并在spring容器中注入自定义bean

为什么80%的码农都做不了架构师?>>>   hot3.png

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());
                    });

 

转载于:https://my.oschina.net/zhu97/blog/3029472

相关文章:

  • Mac osx 系统安装 eclipse
  • 项目实战8.2-Linux下Tomcat开启查看GC信息
  • CopyTranslator v0.0.8 Zouwu RC1 发布
  • Mars 1.3.0 发布,微信官方跨平台跨业务终端基础组件
  • 华为6.0系统(亲测有效)激活XPOSED框架的方法
  • SOP 1.1.0 发布,开放平台解决方案项目
  • c# webapi上传、读取、删除图片
  • JAVA面向对象的总结(函数重载与数组)
  • CUBA Studio 9.0 发布 ,企业级应用开发平台
  • Maven 的这 7 个问题你思考过没有?
  • Maven 运行启动时****找不到符号*com.xxx.user.java
  • win10子系统 (linux for windows)打造python, pytorch开发环境
  • 美团全链路压测自动化实践
  • 现代密码学知识图谱
  • 盘点几个在手机上可以用来学习编程的软件
  • Golang-长连接-状态推送
  • Java IO学习笔记一
  • Linux编程学习笔记 | Linux多线程学习[2] - 线程的同步
  • Node + FFmpeg 实现Canvas动画导出视频
  • php的插入排序,通过双层for循环
  • REST架构的思考
  • swift基础之_对象 实例方法 对象方法。
  • 关于使用markdown的方法(引自CSDN教程)
  • 和 || 运算
  • 基于Dubbo+ZooKeeper的分布式服务的实现
  • 记录一下第一次使用npm
  • 前嗅ForeSpider教程:创建模板
  • 如何优雅的使用vue+Dcloud(Hbuild)开发混合app
  • 职业生涯 一个六年开发经验的女程序员的心声。
  • ###C语言程序设计-----C语言学习(6)#
  • $.ajax中的eval及dataType
  • (12)目标检测_SSD基于pytorch搭建代码
  • (14)学习笔记:动手深度学习(Pytorch神经网络基础)
  • (二)c52学习之旅-简单了解单片机
  • (附源码)springboot码头作业管理系统 毕业设计 341654
  • (入门自用)--C++--抽象类--多态原理--虚表--1020
  • (三)mysql_MYSQL(三)
  • (一)Linux+Windows下安装ffmpeg
  • (转载)微软数据挖掘算法:Microsoft 时序算法(5)
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • .Net 应用中使用dot trace进行性能诊断
  • .netcore如何运行环境安装到Linux服务器
  • /etc/shadow字段详解
  • @converter 只能用mysql吗_python-MySQLConverter对象没有mysql-connector属性’...
  • @RestControllerAdvice异常统一处理类失效原因
  • @select 怎么写存储过程_你知道select语句和update语句分别是怎么执行的吗?
  • @开发者,一文搞懂什么是 C# 计时器!
  • [ vulhub漏洞复现篇 ] GhostScript 沙箱绕过(任意命令执行)漏洞CVE-2019-6116
  • [20171106]配置客户端连接注意.txt
  • [Android]How to use FFmpeg to decode Android f...
  • [BUUCTF]-PWN:wustctf2020_number_game解析(补码,整数漏洞)
  • [BZOJ 1032][JSOI2007]祖码Zuma(区间Dp)
  • [C++] Windows中字符串函数的种类
  • [C++]打开新世界的大门之C++入门
  • [CCIE历程]CCIE # 20604