利用cglib以及反射实现简单的Autowire

最近在学java代理类的使用方法,结合了之前看过的注解,想自己实现一个简单的类似于Spring的AutoWire的注解。通过注解的方式给对象的字段生成一个代理类对象。


首先需要一个注解类,这个注解是RunTime时可以读取到的,作用在字段上,通过value来获取该字段指向的实现类

@Retention(value = RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface AnnoImpl{
    String value();
}

一个有方法的接口,以及该接口的实现类

public interface SuperInterface {
    void func();
}
public class RealSuper implements SuperInterface {
    public void func() {
        System.out.println("RealSuper");
    }
}

一个Bean对象,里面有上面那个接口的字段,但是这个字段不要new一个对象,里面的run()方法直接调用这个字段的方法。一般会报空指针异常,所以接下来需要实现代理类。

public class WrapperBean{

    @AnnoImpl(value = "com.lsj.test.jdkProxy.RealSuper")
    SuperInterface superInterface;

    public void run(){
        superInterface.func();
    }
}

大部分准备工作已经做好,现在需要通过cglib来实现为这个Bean对象中superInterface生成一个对象。

代理类通过集成MethodInterceptor,来实现代理,我们需要传入一个Bean对象,来生成这个Bean的代理类。getInstance()网上大部分都有这个方法,通过Enhancer来生成一个代理对象。

intercept()方法是对象每次调用方法时,都会被拦截下来执行intercept()方法,通过intercept()方法来调用原对象的方法,我们可以在原对象调用方法前后添加自己的操作,比如这里,在调用方法前,对调用对象o进行自动装配。

一开始,我通过method.invoke(o,objects)来调用原对象的方法,但是发现会一直循环下去,后面想了一下,原对象每次调用方法,都会被intercept()拦截执行这个intercept()方法,这样就会一直陷入死循环。

public class WrapperProxy implements MethodInterceptor{
    private  Object target ;

    public Object getInstance(Object target ){
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        Object object = enhancer.create();
        return object;
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("========method before========");
        // 这里实现自动装配
        autoConfig(o);
        //method.invoke(o,objects);
        methodProxy.invokeSuper(o,objects);
        System.out.println("========method atfer========");
        return null;
    }

    public boolean autoConfig(Object object){
        boolean result = true;
        try {
            // 获取所有字段
            Field[] fields = target.getClass().getDeclaredFields();

            // 遍历字段获取所需要的注解信息
            for (Field field : fields) {
                Annotation annotation = field.getAnnotation(AnnoImpl.class);
                if (annotation != null) {
                    String classString = ((AnnoImpl) annotation).value();
                    if(!classString.isEmpty()){
                        field.setAccessible(true);
                        field.set(object, Class.forName(classString).newInstance());
                        field.setAccessible(false);
                    }
                }
            }
        }catch (Exception e){
            result = false;
        }
        return  result;
    }
}

主要看里面的autoConfig()方法,这个方法通过获取target对象的所有字段,对这些字段进行遍历获取我之前创建的Annonation。如果该字段的AnnoImpl注解不是空的,则通过反射对这个字段进行赋值。

for (Field field : fields) {
    Annotation annotation = field.getAnnotation(AnnoImpl.class);
    if (annotation != null) {
        //进行赋值操作
           String classString = ((AnnoImpl) annotation).value();
           if(!classString.isEmpty()){
                 field.setAccessible(true);
                 field.set(object, Class.forName(classString).newInstance());
                 field.setAccessible(false);
            }
    }
}

main()方法跑起来,不需要new,通过注解以及代理类反射创建字段对象

public class Main {
    public static void main(String[] args) {
        WrapperProxy wrapperProxy = new WrapperProxy();
        WrapperBean wrapperBean = new WrapperBean();
        // 获取代理对象
        wrapperBean = (WrapperBean) wrapperProxy.getInstance(wrapperBean);
        wrapperBean.run();
    }
}

利用cglib以及反射实现简单的Autowire_第1张图片

你可能感兴趣的:(java)