Java使用invoke反射调用方法导致@Value、@Autowired等注解失效

Java使用invoke反射调用方法导致@Value、@Autowired等注解失效

发生背景

开发过程中使用到invoke进行反射调用serviceImpl实现类的方法,在运行中发现采用反射方式调用会导致实现类中@value以及@Autowired注解失效,对应注解值都为null。

产生原因

因为在调用invoke反射方法时,Class是直接使用newInstance静态方法来实例化对象。所导致对应@value、@Autowired等注解失效。

PS :Spring的注解是在Spring实例化的时候扫描注入,当Spring实例化完毕之后如果再去newInstance一个新的对象显然是不受Spring管理了,所以相应的注解都是注入为null。

代码演示

Class baseService = serviceClassMap.get(taskRecord.getPlateform());
// 获取指定Method方法
String methodStr = CommonMethodEnum.hasMethod(taskRecord.getType());
Method method = baseService.getMethod(methodStr,Long.class,File.class);
method.invoke(baseService.newInstance(), taskRecord.getId(), file);

解决方案

使用SpringContext上下文获取对应Bean,从而避免注解失效。

method.invoke(SpringUtil.getBean(baseService), taskRecord.getId(), file);

完整代码

package com.vip.vflow2.boot.common.aspect;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.vip.vflow2.boot.common.annotation.ITSMSimpleExport;
import com.vip.vflow2.boot.common.util.EasyExcelUtil;
import com.vip.vflow2.common.po.FileManage;
import com.vip.vflow2.common.po.model.ItilHrProcess;
import com.vip.vflow2.common.service.FileManageService;
import com.vip.vflow2.common.spring.SpringContextUtil;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Objects;

/**
 * @author ex_zhangheng7
 */
@Aspect
@Component
public class ItsmSimpleExportAspect {

    @Autowired
    FileManageService service;

    @Pointcut("@annotation(com.vip.vflow2.boot.common.annotation.ITSMSimpleExport)")
    public void point(){
    }


    /**
     *
     * @author ex_zhangheng7
     * @date 2021/9/18
     * @param point
     * @param export
     * @return java.lang.Object
     */
    @Around("point() && @annotation(export)")
    public Object around(ProceedingJoinPoint point, ITSMSimpleExport export){
        // 获取注解中传递的查询方法名称
        String selectMethod = export.selectMethod();
        // 获取注解中传递的查询出list的名称,对应模板中的名称
        String listName = export.listName();
        // 导出文件的名称
        String fileName = export.fileName();
        // 导出文件的地址
        String templatePath = export.templatePath();
        // 获取切面的参数
        Object arg = point.getArgs()[0];
        // 查询方法执行完成后返回的分页对象
        IPage invokeResult;

        // 获取切面织入方法对应的参数类型
        Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())
                .getMethod().getParameterTypes();
        // 获取当前被织入的类
        Object target = point.getTarget();
        try {
            // 从Spring容器中获取类执行对象
            Object bean = SpringContextUtil.getBean(getExecuteBeanName(target));
            // 获取查询的方法
            Method method = bean.getClass().getMethod(selectMethod, parameterTypes);
            // 执行查询的方法
            invokeResult = (IPage) method.invoke(bean,arg);
            // 查询返回的数据
            List<ItilHrProcess> processList = invokeResult.getRecords();
            // 生成表格
            FileManage fileManage = EasyExcelUtil.generatorExportFile(templatePath, processList, listName, fileName);
            // 把生成的excel对象存放到数据库,并将生成的id返回到此对象中
            service.insert(fileManage);
            return fileManage;
        }  catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (IllegalAccessException | NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取需要执行类的名称
     * @author ex_zhangheng7
     * @date 2021/9/18
     * @param
     * @return java.lang.String
     */
    private String getExecuteBeanName(Object target){
        Objects.requireNonNull(target);
        String beanName = target.getClass()
                .getAnnotation(Service.class)
                .value();
        if(Objects.isNull(beanName)){
            beanName = target.getClass().getName();
        }
        return beanName;

    }

}

文章思想来源

https://www.jianshu.com/p/2f1f3dc1ad80

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值