spring注入时获取注入的原始对象

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_36666651/article/details/81128043

spring的依赖注入是一个非常棒的设计。依赖注入的实现方式主要为两种:
- jdk动态代理的实现方式(要求代理的类实现接口)
- cglib动态代理

我们在实现component时,如果实现了某个接口,在注入时引用的是接口,然后spring会基于接口使用JDK的动态代理实现代理类注入。那么如果component没有实现接口呢?这里就要说到jdk动态代理和cglib代理的区别了,jdk动态代理是基于接口的,代理类和实现类实现相同的接口,然后通过代理类进行调用;而cglib代理则没有实现接口的要求,cglib的实现方式是生成component的子类,通过实现类的子类来进行代理调用。

所以我们在自动注入时,无论使用哪种方式去获取原本的实现类,直接通过getClass都是做不到,直接getClass获取到的是代理类而不是我们的实现类。

我们有时候需要一个实体类自动去读取配置,然后将配置类的component注入进去,这个时候可能需要对component进行一定处理。这次我遇到的场景是使用一个component去读取properties,然后将component注入到需要使用的地方,但是需要使用的地方的参数类型时Map,我需要将component转化为map,我采用的方式是先用gson将component转化为json字符串,再将json反序列化为Map。但是将component直接传递给gson时,转化报错,通过debug发现传递进去的cglib的代理类,导致转化出错。

找到原因后,我就换了种方式去处理(有种更加简单的方式,后面讲),获取到所有的Field,然后通过反射区获取属性值,但是如果直接getClass().getDeclaredFields()获取到的就是代理类的Field了,所以我们需要先获取到原始类型,这里使用的cglib代理,所以我们需要获取的是代理类的父类,实现如下:

Field[] fields = Class.forName(params.getClass().getGenericSuperclass().getTypeName()).getDeclaredFields();

这样就可以获取到父类的所有字段了,然后通过gson的过滤实现更多定制化操作。


———————————-

还一个简单粗暴的方法来完成转化,我们直接在component中实现toString方法:

@Override
    public String toString() {
        return new Gson.toJson(this);
    }

因为默认的toString的实现是super.toString();所有当我们直接调用代理类的toString方法,就可以直接拿到原始对象的所有属性。

猜你喜欢

转载自blog.csdn.net/qq_36666651/article/details/81128043
今日推荐