动态代理、反射

动态代理

动态代理的作用

在这里插入图片描述
1.为什么需要代理?
代理可以无侵入式的给对象增强其他功能
在这里插入图片描述
2.代理长什么样子?
代理里面就是对象要被代理的方法

3.Java通过什么来保证代理的样子?
通过接口保证,后面的对象和代理需要实现同一个接口
接口中就是被代理的对象

如何为JAVA对象创建一个代理对象?

java.lang.reflect.Proxy类:提供一个为对象产生代理对象的方法:
在这里插入图片描述
实例

public interface Star {
    public abstract String sing(String name);
    public abstract void dance();
}
public class BigStar implements Star{
    private String name;
    public BigStar() {
    }
    public BigStar(String name) {
        this.name = name;
    }
    //唱歌
    @Override
    public String sing(String name){
        System.out.println(this.name + "正在唱" + name);
        return "谢谢";
    }
    //跳舞
    @Override
    public void dance(){
        System.out.println(this.name + "正在跳舞");
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}
public class ProxyUtil {
    public static Star createProxy(BigStar bigStar){
        Star star = (Star) Proxy.newProxyInstance(
                ProxyUtil.class.getClassLoader(),//参数一:用于指定哪个类加载器,去加载生成的代理类
                new Class[]{Star.class},//参数二:指定接口,这些接口用于指定生成的代理长什么,也就是说有哪些方法
                new InvocationHandler() {
                    //参数三:用来指定生成的代理对象要干什么事
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        /*
                        参数一:代理的对象
                        参数二:要运行的方法 sing
                        参数三:调用sing方法时,传递的实参
                         */
                        if("sing".equals(method.getName())){
                            System.out.println("准备话筒,收钱");
                        }else if("dance".equals(method.getName())){
                            System.out.println("准备场地,收钱");
                        }
                        //找大明星开始唱歌或跳舞
                        //代码的表现形式:调用大明星里面唱歌或跳舞的方法
                        return method.invoke(bigStar,args);
                    }
                });
        return star;
    }
}

测试

public class test {

    public static void main(String[] args) {
        /**
         * 需求:
         *  外面的人想要明星唱一首歌
         *  1.获取代理的对象
         *    代理对象 = ProxyUtil.class
         *  2.再调用代理的唱歌方法
         *    代理对象,唱歌的方法("只因你太美")
         */
        //1.获取代理的对象
        BigStar bigStar = new BigStar("鸡哥");
        Star proxy = ProxyUtil.createProxy(bigStar);

        //2.调用唱歌的方法
       String result = proxy.sing("只因你太美");
       proxy.dance();
       System.out.println(result);
    }
}

反射

什么是反射?

反射允许对成员变量,成员方法和构造方法的信息进行编程访问
在这里插入图片描述
在这里插入图片描述

获取class对象的三种方式

在这里插入图片描述
代码实例

public class MyReflectDemo1 {
    public static void main(String[] args) throws ClassNotFoundException {
        /**
         * 获取class对象的三种方式:
         *  1.Class.forName(“全类名");
         *  2.类名.class
         *  3.对象.getClass();
         */
        //1.第一种方式
        //全类名:包名 + 类名
        //最为常用
        Class clazza1= Class.forName("com.itjuzi.Studnet");

        //2.第二种方式
        //一般更多的是当做参数进行传递
        Class clazz2 = Studnet.class;

        //3.第三种方式
        //当我们已经有了这个类的对象时,才可以使用
        Studnet s = new Studnet();
        Class clazz3 = s.getClass();

        System.out.println(clazz3 == clazza1);
    }
}

利用反射获取构造方法

在这里插入图片描述
在这里插入图片描述

public class MyReflectDemo2 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        /**
         * 获取class对象的三种方式:
         *  1.Class.forName(“全类名");
         *  2.类名.class
         *  3.对象.getClass();
         */
        //1.第一种方式
        //全类名:包名 + 类名
        //最为常用
        Class clazza1= Class.forName("com.itjuzi.Studnet");
        //2.获取构造方法
//        Constructor[] constructors = clazza1.getConstructors();
//        for(Constructor con: constructors) {
//            System.out.println(con);
//        }
        //3.获取所有构造方法
//        Constructor[] cons2 = clazza1.getDeclaredConstructors();
//        for(Constructor con: cons2) {
//            System.out.println(con);
//        }
        //4.获取单个的构造方法
//        Constructor con1 = clazza1.getDeclaredConstructor();
//        System.out.println(con1);

//        Constructor con1 = clazza1.getDeclaredConstructor(String.class);
//        System.out.println(con1);

//        Constructor con1 = clazza1.getDeclaredConstructor(int.class);
//        System.out.println(con1);
        Constructor con2 = clazza1.getDeclaredConstructor(String.class,int.class);
//        int modifiers = con2.getModifiers();
//        System.out.println(modifiers);
//
//        Parameter[] parameters = con2.getParameters();
//        for(Parameter parameter:parameters){
//            System.out.println(parameter);
//        }
        //暴力反射:临时取消权限的校验
        con2.setAccessible(true);
        Studnet student = (Studnet) con2.newInstance("张三", 23);
        System.out.println(student);//Studnet{name='张三', age=23}
    }
}

利用反射获取成员变量

在这里插入图片描述
在这里插入图片描述

public class MyReflectDemo3 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchFieldException, IllegalAccessException {
    //1.获取class字节码文件的对象
        Class clazz = Class.forName("com.itjuzi.Studnet");

        //2.获取成员变量
        Field[] fields = clazz.getFields();

        for(Field field : fields){
            System.out.println(field);
        }
        System.out.println("*********************");
        //2.获取所有成员变量
        Field[] fieldss = clazz.getDeclaredFields();

        for(Field field : fieldss){
            System.out.println(field);
        }
        System.out.println("*********************");

        //2.获取单个成员变量
        Field gender = clazz.getField("gender");
        System.out.println(gender);
        System.out.println("*********************");

        Field name = clazz.getDeclaredField("name");
        System.out.println(name);
        System.out.println("*********************");

        //获取权限修饰符
        int modifiers = name.getModifiers();
        System.out.println(modifiers);

        System.out.println("*********************");
        //获取成员变量的名字
        String n = name.getName();
        System.out.println(n);
        //获取成员变量的数据类型
        Class<?> type = name.getType();
        System.out.println(type);

        //获取成员变量记录的值
        Studnet studnet = new Studnet("张三四",23,"男");
        name.setAccessible(true);
        Object value = name.get(studnet);
        System.out.println(value);
        //修改里面的值
        name.set(studnet,"lisi");
        System.out.println(studnet);
    }
}

利用反射获取成员方法

在这里插入图片描述
在这里插入图片描述

public class MyReflectDemo4 {
    public static void main(String[] args) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        //1.获取class字节码文件的对象
        Class clazz = Class.forName("com.itjuzi.Studnet");

        //2.获取所有的方法对象(父类中的所有的公工方法)
        Method[] methods = clazz.getMethods();
        for(Method method: methods){
            System.out.println(method);
        }
        System.out.println("**************************");
        //2.获取所有的方法对象(不能获取父类的,但是可以获取本类中私有的
        Method[] methodss = clazz.getDeclaredMethods();
        for(Method method: methodss){
            System.out.println(method);
        }
        System.out.println("**************************");

        //2.获取指定的单一方法
        Method eat = clazz.getDeclaredMethod("eat", String.class);
        System.out.println(eat);

        //获取方法的修饰符
        int modifiers = eat.getModifiers();
        System.out.println(modifiers);

        //获取方法的名字
        String name = eat.getName();
        System.out.println(name);

        //获取方法的形参
        Parameter[] parameters = eat.getParameters();
        for(Parameter parameter : parameters){
            System.out.println(parameter);
        }
        //获取方法的返回值

        //获取方法抛出的异常
        final Class<?>[] exceptionTypes = eat.getExceptionTypes();
        for(Class exceptionType : exceptionTypes){
            System.out.println(exceptionType);
        }

        //方法运行
        /*
        Method类用于创建对象的方法
        Object invoke(Object obj, Object ...args):运行方法
            参数一:用obj对象调用该方法
            参数二:调用方法的传递的参数(如果没有就不写)
            参数三:调用方法的返回值(如果没有就不写)
         */
        Studnet s = new Studnet();
        //参数一s:表示方法的调用者
        //参数二“汉堡包":表示在调用方法的时候传递的实际参数
        eat.setAccessible(true);
        String result = (String) eat.invoke(s, "汉堡包");
        System.out.println(result);
    }}

反射的作用

①获取一个类里面的所有的信息,获取到之后,再执行其他的业务逻辑
②结合配置文件,动态的创建对象并调用方法

保存信息
在这里插入图片描述

public class MyReflectDemo {
    public static void main(String[] args) throws IllegalAccessException, IOException {
         /*
    对于任意一个对象,都可把所有的字段名和值保存到文件中去
     */
        Student s = new Student("小a",23, '女',156.4,"睡觉");

        Teacher t = new Teacher("波妞",1000);
        saveObject(s);
    }
    //把对象里面所有的成员变量名和值都保存到本地文件中
    public static void saveObject(Object obj) throws IllegalAccessException, IOException {
        //1.获取字节码文件的对象
        Class claz = obj.getClass();
        //创建IO流
        BufferedWriter bw = new BufferedWriter(new FileWriter("D:\\a_java_workspace\\java_daili\\myreflect5\\a.txt"));

        //2.获取所有的成员变量
        Field[] declaredFields = claz.getDeclaredFields();
        for (Field field :declaredFields){
            field.setAccessible(true);
            //获取成员变量的名字
            String name = field.getName();
            //获取成员变量的值
            Object value = field.get(obj);
            //写出数据
            bw.write(name + "=" + value);
            bw.newLine();
        }
        bw.close();
    }
}
public class MyReflectDemo {
    public static void main(String[] args) throws IOException, ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
        /*
        反射可以跟配置文件结合的方式,动态的创建对象,并调用方法
         */
        //1.读取配置文件的信息
        Properties prop = new Properties();

        FileInputStream fis = new FileInputStream("D:\\a_java_workspace\\java_daili\\myreflect6\\src\\main\\resources\\prop.properties");
        prop.load(fis);
        System.out.println(prop);
        //2.获取群里面和方法名
        String classname = (String) prop.get("classname");
        String method = (String) prop.get("method");

        //3.利用反射创建对象并运行方法
        Class clazz = Class.forName(classname);

        //获取构造方法
        Constructor construct = clazz.getDeclaredConstructor();
        Object o = construct.newInstance();
        System.out.println(o);

        //获取成员方法并运行
        Method mehtod = clazz.getDeclaredMethod(method);
        mehtod.setAccessible(true);
        mehtod.invoke(o);
    }
}

1.反射的作业
①获取任意一个类中的所有信息
②结合配置文件动态创建对象
2.获得class字节码文件对象的三种方式
①Class.forName(“全雷名”);
②类名.class
③对象.getClass();
3.如何获取构造方法、成员方法、成员变量
get:获取 set :设置
Constructor:构造方法 Parameter:参数
Field:成员变量 Modifiers:修饰符
Method:方法 Declared:私有的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值