反射和动态代理 简单易懂的小例子实现

实体类

package com.bin.entity;

// 猫
public class Cat{

   public Cat(int age, String catching) {
      this.age = age;
      this.catching = catching;
   }

   public Cat() {
   }

   private int age;
   private String catching;

   public int getAge() {
      return age;
   }

   public void setAge(int age) {
      this.age = age;
   }

   public String getCatching() {
      return catching;
   }

   public void setCatching(String catching) {
      this.catching = catching;
   }


   @Override
   public String toString() {
      return "Cat{" +
            "age=" + age +
            ", catching='" + catching + '\'' +
            '}';
   }
   
   public void eat(){
   System.out.println("111");
}
public void eat(int a){
   System.out.println(a);
}
}

反射获取构造方法

通过无参构造获取对象
@Test
//通过反射获取构造方法,通过无参构造创建对象
public void testss() throws Exception {
   //获取要操作的类
   Class<?> clazz = Class.forName("com.bin.entity.Cat");
   //通过无参构造创建对象
   Cat cat = (Cat) clazz.newInstance();
   System.out.println(cat);
}


通过有参构造获取对象
@Test
//通过反射获取构造方法,通过有参构造创建对象
public void tesss() throws Exception{
   //获取要操作的类
   Class<?> clazz = Class.forName("com.bin.entity.Cat");
   //获取有参构造函数对象(可以一个参数不给,就是调用无参的构造对象),因为是反射阶段,我们操作的都是字节码,参数也都是给的字节码
   Constructor<?> constructor = clazz.getConstructor(int.class, String.class);
   //通过构造对象创建对象
   Cat c = (Cat) constructor.newInstance(5, "抓老鼠");
   System.out.println(c);
}

通过反射获取成员变量

   @Test
   //通过反射获取成员变量
   public void tee() throws Exception{
      Class<?> clazz = Class.forName("com.bin.entity.Cat");
      Constructor<?> c = clazz.getConstructor(int.class, String.class);
      Cat cat = (Cat) c.newInstance(5, "抓老鼠");

      //获取字段(只适用于获取非私有的字段)
//    Field catching = clazz.getField("catching");
//    catching.setAccessible(true);
//    //修改字段的值
//    catching.set(cat,"asd");

      //获取字段
      Field catching = clazz.getDeclaredField("catching");
      //解除私有权限
      catching.setAccessible(true);
      catching.set(cat,"asd1");
      System.out.println("cat = " + cat);
      catching.setAccessible(false);

//    这两个方法都是用于获取字段
//    getField 只能获取public的,包括从父类继承来的字段。
//    getDeclaredField 可以获取本类所有的字段,包括private的,但是不能获取继承来的字段。
//    (注: 这里只能获取到private的字段,但并不能访问该private字段的值,除非加上setAccessible(true))
   }

通过反射获取方法

@Test
   //通过反射获取方法
   public void tes() throws Exception{
      Class<?> clazz = Class.forName("com.bin.entity.Cat");
      Cat cat = (Cat) clazz.newInstance();
      //获取无参的方法
      Method eat = clazz.getMethod("eat");
      eat.invoke(cat);

      //获取有参的方法
      Method eat1 = clazz.getMethod("eat", int.class);
      eat1.invoke(cat,9);
   }
}

通过反射越过泛型检查

@Test
//通过反射越过泛型检查(泛型只在编译期有效,在运行期会被擦拭掉)
public void test01() throws Exception{
   List<Integer> list =new ArrayList<>();
   list.add(111);
   list.add(222);
   Class<?> clazz = Class.forName("java.util.List");
   Method m = clazz.getMethod("add", Object.class);
   m.invoke(list,"adc");
   System.out.println(list);
}

把某个对象的某个属性设置为指定的值

@Test
//通用设置方法,把某个对象的某个属性设置为指定的值
public void test02() throws Exception {
   Cat cat =new Cat(3,"李四");
   System.out.println(cat);

   Tool tool =new Tool();
   tool.setProperty(cat,"catching","王五");
   System.out.println("cat = " + cat);
}

-----------------------------------------------------
// 新的类里面编写的方法
package com.bin.action;

import java.lang.reflect.Field;

/**
 * @author fanfan
 * @date 2020-07-27 13:55
 * @Description
 */
public class Tool {

    public void setProperty(Object obj,String name,Object value)throws Exception{

        Class<?> clazz = obj.getClass();
        Field field = clazz.getDeclaredField(name);
        field.setAccessible(true);
        field.set(obj,value);
        field.setAccessible(false);
    }
}

动态代理

接口
package com.bin.action;

/**

  • @author fanfan
  • @date 2020-07-27 16:00
  • @Description
    */
    public interface User {
    public void add();
    public void delete();

}

实现类

package com.bin.action;

/**
 * @author fanfan
 * @date 2020-07-27 16:01
 * @Description
 */
public class UserImpl implements User{
    @Override
    public void add() {
        System.out.println("添加功能");
    }

    @Override
    public void delete() {
        System.out.println("删除功能");
    }
}

动态代理类

package com.bin.action;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @author fanfan
 * @date 2020-07-27 16:03
 * @Description
 */
public class MyInvocationHandler implements InvocationHandler {
    private Object ojb;

    public MyInvocationHandler(Object ojb) {
        this.ojb = ojb;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("先进行检查");
        //执行被代理的ojb对象的方法(ojb要传参进来的类对象,method.invoke(),那个方法调用就执行那个方法)
        //调用的时候,相当于执行了这个Method eat = clazz.getMethod("方法");
        method.invoke(ojb,args);
        System.out.println("完成提交");
        return null;
    }
}

使用动态代理

@Test
//动态代理。对方法加强
public void test04() throws Exception{
   UserImpl user =new UserImpl();
   MyInvocationHandler m = new MyInvocationHandler(user);
   //1,类的字节码文件。2、获取所有的接口.3、代理对象
   User u = (User) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), m);
   u.add();
   u.delete();

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值