(31) la reflexión

Java concepto de mecanismo de reflexión

1. ¿Qué es un reflejo?
      Reflexión (reflexión): La clave es considerado como lenguajes dinámicos, API reflexión Reflexión permite que un programa para obtener cualquier tipo de información por medio de la aplicación de propiedades y métodos de cualquier objeto internos e internos puede ser operado directamente.

2, el mecanismo de reflexión de Java proporciona una funcionalidad

①, se determina en tiempo de ejecución objeto pertenece a cualquiera de las clases

②, cualquier clase de objeto constructor en tiempo de ejecución

③, una determinación de cualquier clase tiene variables y métodos en tiempo de ejecución miembro

④, para obtener información genérica en tiempo de ejecución

⑤, llame a cualquiera variables miembro y los métodos de un objeto en tiempo de ejecución

⑥, el procesamiento de las anotaciones en tiempo de ejecución

⑦, generar proxy dinámico

3, obtener instancia de clase de las tres formas comunes

Class clazz1 = String.class;
Class clazz2 = person.getClass();
Class clazz3 = Class.forName(String classpath)

4, usando reflexiones

@Test
//反射的使用
public void test01() throws Exception {
    Class clazz = Person.class;
    //1,通过反射,创建Person类的对象
    Constructor constructor = clazz.getConstructor(String.class, int.class);
    Object object = constructor.newInstance("Tommey,222");
    Person p = (Person)object;
    System.out.println(p.toString());
    
    //2,通过反射,调用对象指定的属性,方法
    Field age = clazz.getDeclaredField("age");
    age.set(p,10);
    System.out.println(p.toString());

    //调用方法
    Method show = clazz.getDeclaredMethod("show");
    show.invoke(p);

    //通过反射,可以调用Person类的私有结构的。比如:私有的构造器,方法,属性
    //调用私有的构造器
    Constructor constructor1 = clazz.getDeclaredConstructor(String.class);
    constructor1.setAccessible(true);
    Person p1 = (Person)constructor1.newInstance("Tom");
    
    //调用私有的属性
    Field name = clazz.getDeclaredField("name");
    name.setAccessible(true);
    name.set(p1, "a");
    
    //调用私有的方法
    Method showNation = clazz.getDeclaredMethod("showNation", String.class);
    showNation.setAccessible(true);
    showNation.invoke(p1,"中国");
}

Cargador de clases de cargador de clases y la comprensión

1, la comprensión de la clase java.lang.Class

①, proceso de carga de clases :

       Después de que el comando de programa javac.exe más tarde, se generará uno o más archivos de código de bytes (extremo .class). A continuación, utilizamos el comando en un archivo java.exe interpretado de ejecución de código de bytes. Equivalente a cargar un archivo de código de bytes en la memoria. Este proceso se denomina clases de carga. Cargado en clases de memoria, llamamos clases de ejecución, esta clase está en funcionamiento, es como un ejemplo de la clase.

②, en otras palabras, que se corresponde con el ejemplo de una clase en tiempo de ejecución Clase

③, cargado en una memoria de clase en tiempo de ejecución, almacena en caché algún tiempo, durante este tiempo, podemos obtener esta clase de tiempo de ejecución de diferentes maneras

2, cargue el archivo de configuración de dos maneras

Lee el archivo de configuración de la forma:

Properties pros = new Properties();
FileInputStream fis = new FileInputStream("jdbc.properties");
pros.load(fis);

Lee el archivo de configuración de la Segunda forma: ClassLoader

ClassLoader classLoader = ClassLoaderTest.class.getClassLoader();
InputStream is = classLoader.getResourceAsStream("jdbc.properties");
pros.load(fis);

Para una estructura completa de clase en tiempo de ejecución

1, la obtención de clases de la aplicación de tiempo de ejecución, los métodos, interfaces, constructores en genérico

//getFields():获取当前运行时类及其父类中声明为public访问权限的属性
Class clazz = Person.class;
Field[] fields = clazz .getFields();
//getDeclaredFields():获取当前运行时类中声明的所有属性。(不包含父类中声明的属性)
Field[] declaredFields = clazz.getDeclaredFields();
getMethods():获取当前运行时类及其所有父类中声明为public权限的方法
getDeclaredMethods():获取当前运行时类中声明的所有方法。(不包含父类中声明的方法)
Field方法中:
  public int getModifiers() 以整数形式返回此Field的修饰符 --> Modifier.toString(modifier)
  public Class<?> getType() 得到Field的属性类型
  public String getName() 返回Field的名称
全部的方法:
   public Method[] getDeclaredMethods()返回此Class对象所表示的类或接口的全部方法
   public Method[] getMethods()返回此Class对象所表示的类或接口的public的方法
Method类中:
   public Class<?> getReturnType()取得全部的返回值
   public Class<?>[] getParameterTypes()取得全部的参数
   public int getModifiers()取得修饰符
   public Class<?>[] getExceptionTypes()取得异常信息
   //获取运行时类的带泛型的父类的泛型
   Type genericSuperclass = Person.class.getGenericSuperclass();
   ParameterizedType paramType = (ParameterizedType) genericSuperclass;
   //获取泛型类型
   Type[] actualTypeArguments = paramType.getActualTypeArguments();

   //获取运行时类实现的接口
   Class[] interfaces = clazz.getInterfaces();
   //获取运行时类的父类实现的接口
   Class[] interfaces1 = clazz.getSuperclass().getInterfaces();

2, el tiempo de ejecución llama a la estructura asignada clase: propiedades, métodos / font>

atributo:

  //创建运行时类的对象
  Person p = (Person)clazz.newInstance();
  //1,getDeclaredField(String fieldName):获取运行时类中指定变量名的属性
  Field name = clazz.getDeclaredField("name");
  //获取指定的属性:要求运行时类中属性声明为public,不理想,要求属性权限太高
  Field id = clazz.getField("id");
  id.set(p,1000);
  //2,保证当前属性是可访问的
  name.setAccessible(true);
  //3,获取,设置指定对象的此属性值
  name.set(p, "Tommey");

métodos:

  //1,获取指定的某个方法getDeclaredMethod():参数1:指明获取的方法的名称 参数2:指明获取的方法形参列表
  Method show = clazz.getDeclaredMethod("show", String.class);
  show.setAccessible(true);
  //2,调用方法invoke():参数1:方法的调用者 参数2:给方法形参赋值的实参,invoke()的返回值即为对应类中调用的方法的返回值
  Object returnValue = show.invoke(p, "CHN");
  //调用静态方法
  Method showDesc = clazz.getDeclaredMethod("showDesc");
  showDesc.setAccessible(true);
  Object returnVal = showDesc.invoke(Person.class);

agente dinámico reflejado

1, el principio de patrón de diseño servidor proxy de gestión:
      el uso de un objeto proxy se empaqueta, y luego reemplazar el objeto original con el objeto proxy. Cualquier llamada al objeto original debe ser a través de un proxy. objeto proxy para decidir si y cuándo ir a la llamada al método objeto original.

2, el agente estático, por ejemplo:

interface ClothFactory{
    void produceCloth();
}
//代理类
class ProxyClothFactory implements ClothFactory{

    private  ClothFactory factory;//用被代理类对象进行实例化

    public ProxyClothFactory(ClothFactory factory) {
        this.factory = factory;
    }

    @Override
    public void produceCloth() {
        System.out.println("代理工厂做一些准备工作");
        factory.produceCloth();
        System.out.println("代理工厂做一些后续的收尾工作");
    }
}

//被代理类
class NikeClothFactory implements ClothFactory{

    @Override
    public void produceCloth() {
        System.out.println("Nike工厂生产一批运动服");
    }
}

public class StaticProxyTest {
    public static void main(String[] args) {
        //创建被代理类的对象
        ClothFactory nike = new NikeClothFactory();
        //创建代理类的对象
        ClothFactory proxyClothFactory = new ProxyClothFactory(nike);
        proxyClothFactory.produceCloth();
    }
}

3, proxies dinámicos por ejemplo:

Para lograr los problemas de proxy dinámicos deben ser abordados?

  • Uno de los problemas : la colocación de la memoria en la clase de proxy, crear una clase de proxy dinámico y sus objetos (implementado por Proxy.newProxyInstance ())

  • Segundo problema : Cuando un objeto mediante una llamada al método de la clase de proxy, cómo llamar a los nombres de métodos dinámicos son la misma clase de proxy (de clases y sus métodos de implementación de la interfaz de invocación InvocationHandler ())

interface Human{

    String getBelief();
    void eat(String food);
}

class SuperMan implements Human{

    @Override
    public String getBelief() {
        return "他有一个喜欢的人!";
    }

    @Override
    public void eat(String food) {
        System.out.println("她喜欢吃"+food);
    }
}

class ProxyFactory{
    //调用此方法,返回一个代理类的对象。解决问题一
    public static Object getProxInstance(Object obj){
        MyInvocationHandler handler = new MyInvocationHandler();
        handler.bind(obj);
        return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(), handler);
    }
}

class  MyInvocationHandler implements InvocationHandler{

    private Object obj;

    public void bind(Object obj){
        this.obj = obj;
    }

    //当我们通过代理类的对象,调用方法a时,就会自动的调用如下方法:invoke();
    //将被代理类要执行的方法a的功能久声明在invoke中
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //method:即为代理类对象调用的方法,此方法也就作为了被代理类对象要调用的方法
        //obj:被代理类的对象
        return method.invoke(obj,args);
    }
}

public class ProxyTest {

    public static void main(String[] args) {
        SuperMan superMan = new SuperMan();
        //proxyInstance:代理类的对象
        Human proxyInstance = (Human) ProxyFactory.getProxInstance(superMan);
        String belief = proxyInstance.getBelief();
        System.out.println(belief);

        proxyInstance.eat("东坡肉");
    }
}
Publicado 67 artículos originales · ganado elogios 19 · vistas 9868

Supongo que te gusta

Origin blog.csdn.net/qq_41530004/article/details/104367122
Recomendado
Clasificación