抽取——反射抽取、风控抽取

反射原理说明:
当一个CLass文件加载到内存的时候,jvm就会对class文件进行解剖,然后创建一个Class对象,把该类的所有成员信息封装到该对象中。

反射作用:通过指定的Class文操作整个类的成员变量,方法,构造方法

在反射技术中,一个类的任何成员都有相应的类进行描述
构造方法——Constructor类
成员函数——Method类
成员变量——Field类

object获取Class

Class<? extends Object> classInfo = object.getClass();

一。String获取Class类的三种方式

public void test1() throws Exception {		
      // 方式一		
      Class clazz1 = Class.forName("cn.itcast.gz.reflect.Person");
      		
      // 方式二		
      Class clazz2 = Person.class;
      		
      // 方式三		
      Person p1 = new Person();		
      Class clazz3 = p1.getClass();

      //反射创建对象
      String str = "com.xxx.xxx.ICBCImpl";
      Class clazz = Class.forName(String);
      return (ICBCPayImpl)clazz.newInstance();  //或者 return (Stragegy)clazz.newInstnce();        
}  	

二 获取Class类信息

有加decalre表示所有,没有加decalre表示仅公有不包括私有

1.获取类名称和修饰符 类的包名

String name = clazz1.getName();        //类的全称
String name = clazz1.getSimpleName()//类的简单名称
int modifiers = clazz1.getModifiers();   //类的修改符

method.getDeclaringClass().getName()  //通过方法获取包名+类名
method.getReturnType()                //获取方法的返回值类型  if (Collection.class.isAssignableFrom(method.getReturnType())){

2.方法method

Method[] methods = clazz1.getMethods();  //获取公共方法包括继承的父类的方法
getMethod("setName", String.class);      //获取指定参数的公共方法
Method[] getDeclaredMethods()            //获得所有的方法,包括私有
getDeclaredMethod(String name, Class<?>... parameterTypes)  //获取所有指定参数的方法,包括私有

//构造方法
Constructor[] declaredConstructors = clazz.getDeclaredConstructors();  //获取该类的所有构造方法
Constructor[] constructors = clazz.getConstructors(); //获取该类的所有公共构造方法
Constructor constructor = clazz.getConstructor(null);  //获取单个无参公共构造方法
 Constructor declaredConstructor = clazz.getDeclaredConstructor(int.class,String.class);      //获取单个有参私有构造方法
 declaredConstructor .setAccessible(true);  //暴力反射,将构造方法由私有改为公共

// 获取指定名称的方法	
Method method1 = clazz1.getMethod("eat", null);		
method1.invoke(new Person(), null);

//获取指定方法名且有参数的方法
Method method = clazz1.getMethod("eat", String.class);		
method.invoke(new Person(), "包子");

//获取静态方法
Method method = clazz1.getMethod("play", null);		
method.invoke(null, null);

//获取私有方法  method.setAccessible(true);
Method method = clazz1.getDeclaredMethod("movie", String.class);		
method.setAccessible(true);		
method.invoke(new Person(), "苍老师");

3.属性field

Field[] getFields()             //获取公共字段
Field getField(String name)    //指定参数的公共字段
Field[] getDeclaredFields()           //获取所有的字段
Field getDeclaredField(String name)   //获取所有指定参数的字段

  //获取类的属性的注解值
    public static void main(String[] args) {
        //获取类所有属性
        Field[] fields = TradeDetailDTO.class.getDeclaredFields();
        for (Field field : fields) {
            //属性类型 String
            Class classtType = field.getType();
            //属性名称 userName
            String fieldName = field.getName();
            //属性所有注解
            Annotation[] annotations = field.getAnnotations();
            //属性指定注解
            ApiModelProperty apiModelPropertyAnnotation = field.getAnnotation(ApiModelProperty.class);
            String name = apiModelPropertyAnnotation.name();
            String value = apiModelPropertyAnnotation.value();
        }
    }


//判断成员变量是否可访问并设置成可访问
public static void makeAccessible(Field field) {
	if ((!Modifier.isPublic(field.getModifiers()) ||             //成员变量修改时符不是public
			!Modifier.isPublic(field.getDeclaringClass().getModifiers()) ||    //内部类修饰符不是public
			Modifier.isFinal(field.getModifiers())) && !field.isAccessible()) {  //修饰符是final但是不可访问
		field.setAccessible(true);
	}
}

三。通过反射创建对象案例

//方式一:newInstance
String str = "com.xxx.xxx.ICBCImpl";
Class clazz = Class.forName(String);
return (ICBCPayImpl)clazz.newInstance();  //或者 return (Stragegy)clazz.newInstnce();  


//方式二:使用构造方法创建 
Constructor<?> con = clazz1.getConstructor(String.class, int.class);   //获取指定参数的构造方法
Object p1 = con.newInstance("jack", 28);

四。baseServiceImpl

@PostConstruct//在构造方法后,初化前执行
protected void initBaseMapper() throws Exception{
	System.out.println("=======this :"+this);
	System.out.println("=======父类基本信息:"+this.getClass().getSuperclass());
	System.out.println("=======父类和泛型的信息:"+this.getClass().getGenericSuperclass());

	ParameterizedType type =(ParameterizedType) this.getClass().getGenericSuperclass();   //父类和泛型的信息
	Class clazz = (Class)type.getActualTypeArguments()[0];       //泛型  Supplier
	//通过泛型拼装为 supplierMapper
	String localField = clazz.getSimpleName().substring(0,1).toLowerCase()+clazz.getSimpleName().substring(1)+"Mapper";	
	Field field=this.getClass().getSuperclass().getDeclaredField(localField);  // 获取指定名称的全员变量 supplierMapper
	Field baseField = this.getClass().getSuperclass().getDeclaredField("baseMapper");  // 获取指定名称的全员变量 baseMapper
	//有了这句话,后面的baseMapper就自动转为supplierMapper
	baseField.set(this, field.get(this));
}	

五。反射调用某一个类的方法

public static void main(String[] args) throws Exception {
     Class<?> clazz = AppController.class;
     Method method = clazz.getDeclaredMethod("test1", String.class, String.class); 
               //getDeclaredMethod不管公有还是私有都可以,getMethod只能公有
     method.invoke(clazz.newInstance(), "111", "222");
 }
 
private void test1(String str1, String str2) {
     System.out.println(str1);
     System.out.println(str2);
 }
Class<?> clazz = Class.forName(rpcInfo.getPackageName() + "." + rpcInfo.getClazzName());  //利用反射创建类:UserDao
Class[] classes = new Class[rpcInfo.getArgs().length];  //classes是serve这个方法所有的参数类型(从客户端传过来)
for (int i = 0 ;i<classes.length;i++){
     classes[i] = rpcInfo.getArgs()[i].getClass();
 }
Method method = clazz.getMethod(rpcInfo.getMethodName(), classes);
method.invoke(clazz.newInstance(),rpcInfo.getArgs());

六。反射设置值

field.set(bean, value);

七。风控项目多个Contrller接口抽取

1、控制器接收参数实体类

public class VerifyReqDto {
    @Schema(name="method", description = "取值参考 @RiskMethodEnums")
    private String method;
    @Schema(name="methodReq",description = "参数类型由verifyPay,verifyWithdraw,verifyTransfer等接口对应的类型")
    private Object methodReq;
}

2、Service处理

  public GuardianServiceImpl() {
        methodMap = new HashMap<>();
        methodMap.put(RiskMethodEnums.VERIFY_PAY.name(), new MethodMeta(StrategyEnums.PAY.getName(), PayReqDto.class));
        methodMap.put(RiskMethodEnums.VERIFY_WITHDRAW.name(), new MethodMeta(StrategyEnums.WITHDRAW.getName(), WithdrawReqDto.class));
        methodMap.put(RiskMethodEnums.VERIFY_RECHARGE.name(), new MethodMeta(StrategyEnums.RECHARGE.getName(), RechargeReqDto.class));
        methodMap.put(RiskMethodEnums.VERIFY_TRANSFER.name(), new MethodMeta(StrategyEnums.TRANSFER.getName(), TransferReqDto.class));
        methodMap.put(RiskMethodEnums.VERIFY_ADJUST_ACCOUNT.name(), new MethodMeta(StrategyEnums.CHANNEL.getName(), AdjustAccReqDto.class));
        methodMap.put(RiskMethodEnums.VERIFY_REGISTER.name(), new MethodMeta(StrategyEnums.REGISTER.getName(), RegisterReqDto.class));
        methodMap.put(RiskMethodEnums.VERIFY_LOGIN.name(), new MethodMeta(StrategyEnums.LOGIN.getName(), LoginReqDto.class));
        methodMap.put(RiskMethodEnums.VERIFY_SETTING.name(), new MethodMeta(StrategyEnums.SETTINGS.getName(), SettingReqDto.class));
        methodMap.put(RiskMethodEnums.VERIFY_BIND_CARD.name(), new MethodMeta(StrategyEnums.BIND.getName(), BindCardReqDto.class));

        /**担心调用方,把失败放过**/
        errorRsp = new GuardianRspDto();
        errorRsp.setCode(200);
        errorRsp.setAction(ActionEnums.REJECT.name());
        errorRsp.setMsg("Method Error");
        errorRsp.setReason("Method Error");
    }

    @Override
    public GuardianRspDto verify(VerifyReqDto reqDto) {
        MethodMeta meta = methodMap.get(reqDto.getMethod());
        if (meta == null) {
            log.warn("Find none such method:{}", reqDto.getMethod());
            return errorRsp;
        }
        Object dto = meta.to(reqDto.getMethodReq());
        return riskExec(dto, meta.getStrategy());
    }

public class MethodMeta {
    private String strategy;
    private Class<?> clazz;

    public MethodMeta(String strategy, Class<?> clazz) {
        this.strategy = strategy;
        this.clazz = clazz;
    }

    public String getStrategy() {
        return strategy;
    }

    public Object to(Object req) {
        return JSON.parseObject(JSONObject.toJSONString(req), clazz);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飘然生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值