Mecanismo de búsqueda de empleo en prácticas JAVA y agente dinámico

Introduccion

Antes de la aparición de la reflexión, cuando tenemos una clase java, no podemos usar la estructura privada en la clase fuera de la clase, por ejemplo, no podemos llamar al constructor privado, método privado, etc. Pero después de reflexionar, podemos llamar a cualquier estructura de esta clase, incluso privada.

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ReflectionTest {

    @Test
    public void test1(){
        Person p = new Person("tom",23);
        p.show();
    }


    @Test
    public void test2() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        //1.获取类对象
        Class<Person> personClass = Person.class;
        //2.获取类对象的构造器
        Constructor constructor = personClass.getConstructor(String.class, int.class);
        Object tom = constructor.newInstance("Jerry", 23);
        //3.获取类方法
        Method show = personClass.getDeclaredMethod("show");
        show.invoke(tom);

        //反射的特殊功能,可以调用私有的类结构
        Constructor<Person> cons1 = personClass.getDeclaredConstructor(String.class);
        cons1.setAccessible(true);
        Person wanglei = cons1.newInstance("wanglei");
        wanglei.show();


    }

}

Reflexión y modo singleton

El patrón singleton privatiza el constructor, y espero que solo se necesite crear una instancia de esta clase. En ese momento, la reflexión es resolver el problema de si se puede usar. El modo singleton es sugerir su escritura. No están en conflicto.

Comprensión de java.lang.Class

La clase como fuente de reflexión.

(1) Proceso de carga de clases: después de que javac.exe compila el programa, se generarán uno o más archivos de bytecode. La clase termina, cada clase de java corresponde a un archivo de bytecode, a través de la interpretación y ejecución de java.exe El archivo de bytecode del método mian. Esto es equivalente a cargar este archivo de bytecode en la memoria. Este proceso se llama carga de clase. La clase grabada en la memoria se llama clase de tiempo de ejecución, y esta clase de tiempo de ejecución se usa como una instancia de Class. En otras palabras, una instancia de Class corresponde a una clase de tiempo de ejecución.

Cuatro formas de obtener objetos de clase

//方式一:调用运行时类的属性:.class
        Class clazz1 = Person.class;
        System.out.println(clazz1);
        //方式二:通过运行时类的对象,调用getClass()
        Person p1 = new Person();
        Class clazz2 = p1.getClass();
        System.out.println(clazz2);

        //方式三:调用Class的静态方法:forName(String classPath)
        Class clazz3 = Class.forName("com.atguigu.java.Person");
//      clazz3 = Class.forName("java.lang.String");
        System.out.println(clazz3);

        System.out.println(clazz1 == clazz2);
        System.out.println(clazz1 == clazz3);

        //方式四:使用类的加载器:ClassLoader  (了解)
        ClassLoader classLoader = ReflectionTest.class.getClassLoader();
        Class clazz4 = classLoader.loadClass("com.atguigu.java.Person");
        System.out.println(clazz4);

        System.out.println(clazz1 == clazz4);

Tres pasos:

Cargar: agregue el archivo de clase de la clase a la memoria y cree un objeto de clase. Este proceso lo completa el cargador de clases

Enlace: asegúrese de que la información contenida en la secuencia de bytes del archivo de clase cumpla con los requisitos de la máquina virtual actual y no ponga en peligro la seguridad de la máquina virtual.

Inicialización: al compilar y generar un archivo de clase, el compilador generará dos métodos para agregar al archivo de clase, uno es el método de inicialización de clase clinit y el otro es el método de inicialización de instancia init. clinit se refiere al constructor de la clase, el papel principal es realizar en la fase de inicialización del proceso de carga de la clase, el contenido de la ejecución incluye la inicialización de variables estáticas y la ejecución de bloques estáticos.

 

 

Introduccion

El patrón proxy es uno de los 23 patrones de diseño, que es un conocimiento más importante. El AOP (Programación Orientada a Aspectos) más importante en el marco de Spring también se basa en proxy dinámico.

Comprensión del agente

En cuanto a la comprensión de los agentes, permítanme dar un ejemplo: hace 20 años, la forma en que queríamos comprar una computadora Lenovo era: fuimos a la fábrica de Lenovo, y la fábrica nos vendió computadoras y nos brindó servicios postventa.

En el desarrollo de estas décadas, han aparecido algunos distribuidores. Compraron productos de la fábrica de Lenovo y nos los vendieron. Cuando se rompió la computadora, también fuimos a la tienda del distribuidor para encontrarlo, y luego fue a la fábrica, así que La conexión con la fábrica estaba realmente rota.

En 2020, si queremos comprar una computadora portátil, iremos directamente a grandes distribuidores como Tmall, Suning y JD.com para comprar una computadora. Si hay un problema, devolveremos el producto sin motivo durante 7 días.

Aquí somos el cliente Cliente, esos distribuidores también se llaman agentes, y las fábricas de Lenovo se llaman agentes. Tal proceso es un agente.

Proxy dinámico

Las características del proxy dinámico: el código de bytes se crea y carga en cualquier momento, y se carga en cualquier momento

El papel de los agentes dinámicos: mejorar el método sin modificar el código fuente

Clasificación de agentes dinámicos: 2 tipos, uno es un agente dinámico basado en la interfaz y el otro es un agente dinámico basado en una subclase

Proxy dinámico basado en interfaz

La implementación de la clase de proxy proporcionada por JDK requiere que la clase de proxy implemente al menos una interfaz. El proceso de implementación es el siguiente

(1) Primero cree la clase Lenovo e implemente una interfaz

package com.alibaba200408.动态代理;

public class Lenovo implements ILenovo {
    @Override
    public void sale(Double money) {
        System.out.println("拿到"+money+"元,电脑发货");
    }

    @Override
    public void afterService(Double money) {
        System.out.println("拿到"+money+"元,售后服务开始");

    }
}

El código es muy simple, solo hay dos métodos involucrados, uno es vender la computadora y el otro es reparar la computadora.

El código de la interfaz es el siguiente

package com.alibaba200408.动态代理;

public interface ILenovo {

    void sale(Double money);

    void afterService(Double money);
}

(2) Instanciar un objeto proxy dinámico y llamar a métodos a través del objeto proxy

package com.alibaba200408.动态代理;

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

public class Client {
    public static void main(String[] args) {

        //联想厂家
        ILenovo lenovo = new Lenovo();


        //创建代理对象
        ILenovo proxyInstance = (ILenovo) Proxy.newProxyInstance(lenovo.getClass().getClassLoader(),
                lenovo.getClass().getInterfaces(),
                new InvocationHandler() {
                    /**
                     * invoke方法的作用是调用任何被代理对象的方法都会被这个invoke方法拦截
                     *  proxy:表示当前代理对象的引用
                     *  method:表示当前正在执行的方法
                     *  args:表示当前执行的方法的参数
                     *
                     *  返回值就是当前方法的返回值
                     */

                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        //提供增强的代码
                        Double money = (Double) args[0];
                        if ("sale".equals(method.getName())){
                            method.invoke(lenovo, money * 0.8);
                        }else {
                            method.invoke(lenovo,args);
                        }

                        return null;
                    }
                });

        proxyInstance.afterService(10000.0);

    }
}

Agente dinámico basado en subclase

Esta implementación requiere que la clase proxy no pueda ser final, porque la clase modificada final no puede tener subclases, y en segundo lugar, este método requiere un cglib de terceros. No los repetiré aquí.

111 artículos originales publicados · Me gusta 60 · 70,000 + vistas

Supongo que te gusta

Origin blog.csdn.net/Haidaiya/article/details/105512739
Recomendado
Clasificación