java的反射 和 动态代理

Posted 每天进步一点点。。。

tags:

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

一、反射的概述

 

JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法;对于任意一个对象,都能够调用它的任意一个方法和属性;这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制。

 

要想解剖一个类,必须先要获取到该类的字节码文件对象。而解剖使用的就是Class类中的方法.所以先要获取到每一个字节码文件对应的Class类型的对象.
 
反射就是把java类中的各种成分映射成一个个的Java对象
例如:一个类有:成员变量、方法、构造方法、包等等信息,利用反射技术可以对一个类进行解剖,把个个组成部分映射成一个个对象。
 

 

 二、反射的使用

  直接上代码  

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;

public class ReflectDemo {

    private String name;
    int age;

    @Override
    public String toString() {
        return "ReflectDemo{" +
                "name=\'" + name + \'\\\'\' +
                ", age=" + age +
                \'}\';
    }

    public static void main(String[] args) throws ClassNotFoundException,
            NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchFieldException {
        //给对象的属性赋值  包括私有和共有  都可以赋值
        ReflectDemo reflectDemo = new ReflectDemo();
        reflectDemo.setProperty(reflectDemo,"name","你大爷");
        reflectDemo.setProperty(reflectDemo,"age",2222);
        System.out.println(reflectDemo);

        //获取指定类的字节码文件
        Class c = Class.forName("com.bytech.cn.dao.domain.AdminPo");

        //通过字节码文件 所有的公共构造方法
        Constructor[] constructors = c.getConstructors();
        for (Constructor constructor : constructors){
            System.out.println(constructor);
        }

        //通过字节码文件 获取所有的所有构造方法
        Constructor[] constructors1 = c.getDeclaredConstructors();

        //通过字节码文件 获取无参构造方法
        Constructor constructor2 = c.getConstructor();

        System.out.println(constructor2);

        //1.获取反射去获取该构造方法  并使用
        Class c3 =  Class.forName("com.bytech.cn.dao.domain.AdminPo");
        //2.获取带参构造器
        Constructor constructor4 = c.getConstructor(Integer.class,String.class,String.class);
        //获取这个对象
        Object obj = constructor4.newInstance(2222,"222","222");
        System.out.println(obj);

        //获取私有的构造方法
        Constructor constructor5  = c.getDeclaredConstructor(String.class,String.class);
        //暴力访问
        constructor5.setAccessible(true);
        //创建对象
        Object obj2 = constructor5.newInstance("aa","bb");
        System.out.println("==============");
        System.out.println(obj2);

        //获取成员变量 并给成员变量赋值
        Field adminFiled  = c3.getDeclaredField("adminName");
        adminFiled.setAccessible(true);
        adminFiled.set(obj,"管理员姓名");
        System.out.println("~~~~~~~~~~~~~~~~~~~~~");
        System.out.println(obj);


        //所有的方法访问
        //public Menthod getMothod (String name ,Class<?> ...parmeterTypes)
        //第一个参数表示的是方法名,第二个参数表示的是方法的参数class类
        Method m1 = c.getMethod("方法名字");
        /*public Object invoke(Object obj,Object ...args)*/
        m1.invoke(obj);//调用obj对象的m1方法
        System.out.println("============");
        Method m2 = c.getMethod("方法名字",String.class);
        m2.invoke(obj,"hello");
        System.out.println("=================");
        Method m3 = c.getMethod("getString",String.class,Integer.class);
        Object objectString = m3.invoke(obj,"hello",100);

        Method m4 = c.getDeclaredMethod("function");
        m4.setAccessible(true);
        m4.invoke(obj);

        //我给你ArrayList<Integer>的一个对象 ,我想在这个集合中添加一个字符串数据,如何实现呢*/
        //解答开始
        ArrayList<Integer> array = new ArrayList<>();
        array.add(11);
        Class arrayClass1 = array.getClass();
        Method m = arrayClass1.getMethod("add",Object.class);
        m.invoke(array,"你好");
        System.out.println(array);
        System.out.println("..............................................");
        Class arrayClass = Class.forName("java.util.ArrayList");
        Constructor constructor = arrayClass.getConstructor();
        Object object = constructor.newInstance();
        Method methodArray = arrayClass.getMethod("add",Object.class);
        methodArray.invoke(object,"hello ni da ye");
        System.out.println(object);
        //解答完毕
    }


       public void setProperty(Object obj,String filedName,Object filedValue) throws NoSuchFieldException, IllegalAccessException {
           Class c = obj.getClass();
           Field field = c.getDeclaredField(filedName);
           field.setAccessible(true);
           field.set(obj,filedValue);
        }



}

三、实现一个动态代理

public interface UserDao {

    void add();

    void delete();

    void update();

    void select();

}
public class UserDaoImpl implements UserDao {
    @Override
    public void add() {
        System.out.println("添加功能");
    }

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

    @Override
    public void update() {
        System.out.println("修改功能");
    }

    @Override
    public void select() {
        System.out.println("查询功能");
    }
}
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

    private Object target;  //目标对象

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

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("权限校验");
        Object result = method.invoke(target,args);
        System.out.println("日志记录");
        return result;  //返回的是代理对象
    }
}
import java.lang.reflect.Proxy;

public class TestProxy {
    public static void main(String[] args) {
        UserDao ud = new UserDaoImpl();
        ud.add();
        ud.delete();
        ud.select();
        ud.update();
        System.out.println("----------------");
        //我们要创建一个动态代理类
        //proxy类中有一个方法 可以创建动态代理对象
        //public static Class<?> getProxyClass(ClassLoader loader,Class<?>... interfaces)throws IllegalArgumentException
        MyInvocationHandler handler = new MyInvocationHandler(ud);
        UserDao userDaoProxy = (UserDao)Proxy.newProxyInstance(ud.getClass().getClassLoader(),ud.getClass().getInterfaces(),handler);
        userDaoProxy.update();
        userDaoProxy.select();
        userDaoProxy.delete();
        userDaoProxy.add();

    }

}

这样就实现了一个动态代理。。

 

以上是关于java的反射 和 动态代理的主要内容,如果未能解决你的问题,请参考以下文章

java反射和动态代理有啥关系

java反射机制动态代理初探

java反射机制与动态代理

Java开发人员必懂的基础——反射与动态代理

动态代理与Scala反射/Java反射在JavaScalaKotlin中的使用

java 反射之静态and动态代理