动态代理对象的属性注入

Posted 技术无产者

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了动态代理对象的属性注入相关的知识,希望对你有一定的参考价值。

下面会分别对Jdk和Cglib两种类型的动态代理的对象进行分析

1.Cglib

1> 直接通过反射创建代理对象

  User user=new User("zyz",123);
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(user.getClass());
        enhancer.setInterfaces(user.getClass().getInterfaces());
        enhancer.setCallback(new NoOp() 
            @Override
            public int hashCode() 
                return super.hashCode();
            
        );

        User u=(User) enhancer.create();
        System.out.println(u);
        BeanUtil.setFieldValue(u,"name","mzd");
        BeanUtil.setFieldValue(u,"age",456);
        System.out.println(u);
        u.name="cyq";
        System.out.println(u);


// res:
Username='null', age=0
Username='mzd', age=456
Username='cyq', age=456

     没有指定代理的对象时,直接修改和通过强制注入都是可以修改代理对象的属性值的

2> 代理某个对象

  User user=new User("zyz",123);
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(user.getClass());
        enhancer.setInterfaces(user.getClass().getInterfaces());


        enhancer.setCallback(new MethodInterceptor() 
            public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable 

             return methodProxy.invoke(user,objects);
            
        );
        User u=(User) enhancer.create();
        System.out.println(u);
        BeanUtil.setFieldValue(u,"name","mzd");
        BeanUtil.setFieldValue(u,"age",456);
        System.out.println("****");
        System.out.println(u);
        BeanUtil.setFieldValue(user,"name","mzd");
        System.out.println("****");
        System.out.println(user);
        System.out.println(  u.getClass().getFields().length);
        for (Field field:u.getClass().getFields())
        
            System.out.println(field.getName());
        
        System.out.println("****");

        u.name="qaz";
        System.out.println(u);
        System.out.println("****");


// res:

Username='zyz', age=123
****
Username='zyz', age=123
****
Username='mzd', age=123
3
CGLIB$FACTORY_DATA
name
age
****
Username='mzd', age=123
****

Process finished with exit code 0

     由结果可见,创建了一个user对象,用cglib来代理这个类,直接改变代理类的属性值,是不起作用的,虽然修改代理类u的属性,但是输出u结果还是输出的被代理对象user本身的属性值,我猜测是因为User是它的父类,由于编译看左边的缘故所以优先输出User对象的属性? 这点我也存在疑惑。总之,若指定了代理的对象,直接修改生成代理对象的属性是不起作用的。

    但是直接修改被代理类的值,这时候代理类的值是变化的

2.JDK动态代理

   1>直接通过反射创建

        User user=new User();
        User user1 = user.getClass().newInstance();
        BeanUtil.setFieldValue(user1,"name","mzd");
        BeanUtil.setFieldValue(user1,"age",456);
        System.out.println(user1);
        user1.name="cyq";
        System.out.println(user1);

    // res:
       Username='mzd', age=456
       Username='cyq', age=456

          反射创建可以修改属性的值

2>

     User user=new User("zyz",1321);
        User user1 = user.getClass().newInstance();


        UserService1 u = (UserService1) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), user.getClass().getInterfaces(), new InvocationHandler() 
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable 
                return method.invoke(user, args);
            
        );
        System.out.println(u);
        BeanUtil.setFieldValue(u,"name","mzd");
        BeanUtil.setFieldValue(u,"age",456);
        System.out.println("****");
        System.out.println(u);
        BeanUtil.setFieldValue(user,"name","mzd");
        System.out.println("****");
        System.out.println(user);
        System.out.println(  u.getClass().getFields().length);
        for (Field field:u.getClass().getFields())
        
            System.out.println(field.getName());
        

JDK动态代理更无法更改属性,因为jdk动态代理创建的对象必须用接口接收

以上是关于动态代理对象的属性注入的主要内容,如果未能解决你的问题,请参考以下文章

IOC 控制反转Android 事件依赖注入 ( 事件依赖注入具体的操作细节 | 创建 事件监听器 对应的 动态代理 | 动态代理的数据准备 | 创建调用处理程序 | 创建动态代理实例对象 )(代码片

框架扩展:注解 RPC Consumer属性动态注入

学习Spring

学习Spring

学习Spring

第 16 章:给代理对象设置属性注入