zoukankan      html  css  js  c++  java
  • 反射+spring初始化工厂

    需求背景:项目启动后初始化一个 url工厂,工厂中存放固定包路径下的controller中使用 自定义注解 UpperLimitAnnotation 的方法的请求 全路径;实现方式:反射+spring InitializingBean接口;

      扩展场景:初始化其他类型工厂,如 策略模式中的策略工厂等 可以结合spring  InitializingBean 实现

    代码如下:

     说明:0.9.12 版本依赖  发布到  生产环境   报  org.reflections.ReflectionsException: Scanner MethodAnnotationsScanner was not configured  异常,使用0.9.11版本则无此问题;

    // 反射依赖
    <dependency>
                <groupId>org.reflections</groupId>
                <artifactId>reflections</artifactId>
                <version>0.9.11</version>
      </dependency>
    

      工厂类代码:

    package com.ruijie.demo.util;
    
    import com.alibaba.fastjson.JSON;
    import com.ruijie.demo.annotaion.UpperLimitAnnotation;
    import net.minidev.json.JSONUtil;
    import org.assertj.core.util.Lists;
    import org.reflections.Reflections;
    import org.reflections.scanners.*;
    import org.springframework.beans.factory.InitializingBean;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    import org.springframework.util.ObjectUtils;
    import org.springframework.util.StringUtils;
    import org.springframework.web.bind.annotation.RequestMapping;
    
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.List;
    import java.util.Set;
    
    /**
     * @ClassName UrlFactory
     * @Description 对外开放接口url工厂
     * @Author WANGQW
     * @Date 2021/4/6 10:56
     **/
    @Component
    public class UrlFactory implements InitializingBean {
    
        public static final List<String> urlFactory = Lists.newArrayList();
    
        @Value("${spring.application.name}")
        private String applicationName;
    
        /**
         * @Author wangqw
         * @Description 反射获取 所有api包下所有使用UpperLimitAnnotation 的接口全路径
         * @Date 2021/4/6 15:31
         * @Param []
         * @return void
        **/
        @Override
        public void afterPropertiesSet() throws Exception {
    //        Reflections reflections = new Reflections("com.ruijie.demo.api", Arrays.asList(
    // new SubTypesScanner(false)//允许getAllTypes获取所有Object的子类, 不设置为false则 getAllTypes 会报错.默认为true.
    // ,new MethodParameterNamesScanner()//设置方法参数名称 扫描器,否则调用getConstructorParamNames 会报错
    // ,new MethodAnnotationsScanner() //设置方法注解 扫描器, 否则getConstructorsAnnotatedWith,getMethodsAnnotatedWith 会报错
    // ,new MemberUsageScanner() //设置 member 扫描器,否则 getMethodUsage 会报错, 不推荐使用,有可能会报错 Caused by: java.lang.ClassCastException: javassist.bytecode.InterfaceMethodrefInfo cannot be cast to javassist.bytecode.MethodrefInfo
    // ,new TypeAnnotationsScanner()//设置类注解 扫描器 ,否则 getTypesAnnotatedWith 会报错
    // ));

    Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage("com.ruijie.demo.api")).setScanners(new MethodAnnotationsScanner()));

    //获取所有带有 UpperLimitAnnotation 注解的方法对象 Set<Method> methods = reflections.getMethodsAnnotatedWith(UpperLimitAnnotation.class); methods.stream().forEach(item ->{ String clazzUrl = ""; RequestMapping clazzMapping = item.getDeclaringClass().getAnnotation(RequestMapping.class); if(null != clazzMapping && !ObjectUtils.isEmpty(clazzMapping.value())){ clazzUrl = clazzMapping.value()[0]; } RequestMapping methodMapping = item.getAnnotation(RequestMapping.class); if(null == methodMapping || ObjectUtils.isEmpty(methodMapping.value())){ return; } String methodUrl = methodMapping.value()[0]; String url = StringUtils.isEmpty(clazzUrl) ? "/" + applicationName + methodUrl : "/" + applicationName + clazzUrl + methodUrl; urlFactory.add(url); }); } }

      controller 中 注解使用:

    package com.ruijie.demo.api;
    
    import com.alibaba.fastjson.JSONObject;
    import com.ruijie.demo.annotaion.UpperLimitAnnotation;
    import com.ruijie.demo.entity.remote.RemoteOrganization;
    import com.ruijie.demo.entity.remote.TycResult;
    import com.ruijie.demo.service.EeterpriseApiService;
    import com.ruijie.framework.common.RemoteResult;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.*;
    
    import java.util.Map;
    
    /**
     * @ClassName EnterpriseApiController
     * @Description
     * @Author WANGQW
     * @Date 2021/3/18 10:11
     **/
    @RestController
    @RequestMapping("/company")
    public class EnterpriseApiController {
    
        @Autowired
        private EeterpriseApiService eeterpriseApiService;
    
        /**
         * @Author wangqw
         * @Description 模糊搜索企业信息-列表
         * @Date 2021/3/16 17:47
         * @Param [keyword]
         * @return com.ruijie.framework.common.RemoteResult<com.ruijie.demo.domain.remote.TycResult>
         **/
        @UpperLimitAnnotation
        @RequestMapping(value = "/search",method = RequestMethod.GET)
        public RemoteResult<TycResult> search(@RequestParam("keyword") String keyword){
            return new RemoteResult<>(eeterpriseApiService.search(keyword));
        }
    
    
    }
    

    简述:spring  InitializingBean 接口的作用:

    1:spring为bean提供了两种初始化bean的方式,实现InitializingBean接口,实现afterPropertiesSet方法,或者在配置文件中同过init-method指定,两种方式可以同时使用
    2:实现InitializingBean接口是直接调用afterPropertiesSet方法,比通过反射调用init-method指定的方法效率相对来说要高点。但是init-method方式消除了对spring的依赖
    3:如果调用afterPropertiesSet方法时出错,则不调用init-method指定的方法。

    在spring初始化bean的时候,如果该bean是实现了InitializingBean接口,并且同时在配置文件中指定了init-method,系统则是先调用afterPropertiesSet方法,然后在调用init-method中指定的方法。

  • 相关阅读:
    python 学习 第一天
    pip 自己的源 搭建
    hadoop 完全分布式部署
    OpenCV Python 数字图像处理 基础系列(0)环境配置与准备环节
    STM32学习笔记 —— 0.1 Keil5安装和DAP仿真下载器配置的相关问题与注意事项
    TensorFlow学习笔记(1)—— 基本概念与框架
    算法研讨会-含有回溯的递归算法设计探讨
    Nvidia Jetson TX2开发板学习历程( 2 )- 更换pip源,提高下载速度
    STM32学习笔记 —— 1.1 什么是寄存器(概念分析)
    Nvidia Jetson TX2开发板学习历程(1)- 详细开箱、上电过程
  • 原文地址:https://www.cnblogs.com/wl20200316/p/14622438.html
Copyright © 2011-2022 走看看