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

实体类

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();

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
假设有一个电影票售卖系统,我们可以使用代理类来限制未成年人的购票权限。具体实现如下: 首先,我们定义一个电影票售卖接口 `MovieTicket`,它包含了售票的方法 `sellTicket()`: ``` public interface MovieTicket { void sellTicket(); } ``` 然后,我们实现一个电影票售卖类 `RealMovieTicket`,它实现了 `MovieTicket` 接口: ``` public class RealMovieTicket implements MovieTicket { @Override public void sellTicket() { System.out.println("售卖电影票"); } } ``` 接下来,我们定义一个代理类 `ProxyMovieTicket`,它也实现了 `MovieTicket` 接口,同时包含了一个 `RealMovieTicket` 类型的成员变量 `realMovieTicket`: ``` public class ProxyMovieTicket implements MovieTicket { private RealMovieTicket realMovieTicket; public ProxyMovieTicket(RealMovieTicket realMovieTicket) { this.realMovieTicket = realMovieTicket; } @Override public void sellTicket() { if (checkAge()) { realMovieTicket.sellTicket(); } else { System.out.println("未满18岁,无法购票"); } } private boolean checkAge() { // 检查是否满18岁 return true; // 假设通过检查 } } ``` 在代理类 `ProxyMovieTicket` 中,我们重写了 `sellTicket()` 方法,并添加了一个 `checkAge()` 方法来检查购买者是否满18岁。如果购买者未满18岁,则代理类不会调用真正的售票方法,而是提示购票失败。 最后,我们可以使用以下代码来进行测试: ``` public class Main { public static void main(String[] args) { RealMovieTicket realMovieTicket = new RealMovieTicket(); // 创建真正的电影票售卖对象 ProxyMovieTicket proxyMovieTicket = new ProxyMovieTicket(realMovieTicket); // 创建代理对象 proxyMovieTicket.sellTicket(); // 调用代理对象的售票方法 } } ``` 如果购买者满18岁,则代理类会调用真正的售票方法,输出 `售卖电影票`;否则,代理类会提示购票失败,输出 `未满18岁,无法购票`。这就是一个简单的代理类的例子
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值