java patrones de diseño ---- modo proxy, el proxy JDK dinámica y entender cglib diferencia proxies dinámicos

modo de proxy:

Se refiere a proporcionar un agente para otros objetos, para controlar el acceso al objeto.

medie objeto proxy entre los objetos de los clientes y de destino.

Es patrones de diseño estructural.

clasificación de patrones de proxy:

agente estático.

proxies dinámicos.

 

agentes estáticos

Muy bien, así que empezamos con el proxy estática:

análisis de roles:

1. La función de resumen: las interfaces de uso general o clases abstractas para resolver

2. El verdadero papel: el papel de agente

3. Papel interino: papel real, el verdadero papel del agente, vamos a hacer algunas subsidiaria operativa en general

4. clientes: personas que acceden a objeto proxy

Paso Código:

1. Interfaz

/**
 * @Author Darker
 * @Descrption 租房
 * @Date : Created in 10:00 2020-3-11
 */
public interface Rent {
    public void rent();
}

2, el papel real

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:01 2020-3-11
 */
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}

3, papel temporario

/**
 * @Author Darker
 * @Descrption 代理,中介
 * @Date : Created in 10:02 2020-3-11
 */
public class Proxy{

    private Host host;

    public Proxy(){}

    public Proxy(Host host){
        this.host = host;
    }

    public void rent(){
        seeHouse();
        host.rent();
        signContract();
        fare();
    }

    public void seeHouse(){
        System.out.println("中介带你看房子");
    }

    public void signContract(){
        System.out.println("签租房合同");
    }

    public void fare(){
        System.out.println("收中介费");
    }
}

4, de acceso de cliente

/**
 * @Author Darker
 * @Descrption 客户端租房
 * @Date : Created in 10:02 2020-3-11
 */
public class Client {
    public static void main(String[] args) {
        Host host = new Host();
        Proxy proxy = new Proxy(host);
        proxy.rent();
    }
}

Estáticas beneficios modo de proxy:

1. Se puede hacer la operación más personajes reales mantienen pura! No hay que prestar atención a algunos de los asuntos públicos.

2. El papel público de la función de un agente! Para lograr la división del negocio!

3. El servicio público se produce cuando se extiende, la gestión centralizada fácil.

desventajas:

Un papel que tendrá un papel actuando reales, se duplicará la cantidad de código.

 

Por supuesto, el ejemplo anterior puede ser común en nuestro desarrollo real, pero sobre todo para entender el modelo de la agencia de importancia, que ahora la aplicación de un código, Tomar cuajada Laijiangjiang.

1, en primer lugar tenemos un negocio de la compañía es la operación de la cuajada del usuario;

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:19 2020-3-11
 */
public interface UserService {
    public void add();

    public void delete();
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:20 2020-3-11
 */
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("增加一个角色");
    }

    @Override
    public void delete() {
        System.out.println("删除一个角色");
    }
}

2, bueno, ahora la pregunta es, nuestra empresa requiere cada paso para agregar registros.

En primer lugar pensar, para cada método más userImpl dentro de la operación de registro, es demasiado tonto, pero tampoco el uso de ellos, y no en línea con la apertura y el cierre de principio.

Por lo tanto, pensamos en modelo de agencia, se utiliza un proxy para completar.

/**
 * @Author Darker
 * @Descrption 静态代理模式
 * @Date : Created in 10:26 2020-3-11
 */
public class Proxy implements UserService{
    
    private UserServiceImpl userService;

    public void setUserService(UserServiceImpl userService) {
        this.userService = userService;
    }

    @Override
    public void add() {
        log("add");
        userService.add();
    }

    @Override
    public void delete() {
        log("delete");
        userService.delete();
    }

    public void log(String msg){
        System.out.println("调用了"+msg+"方法");
    }
    
}

/**
 * @Author Darker
 * @Descrption 客户端
 * @Date : Created in 10:20 2020-3-11
 */
public class Client {
    public static void main(String[] args) {
        UserServiceImpl userService = new UserServiceImpl();
        Proxy proxy = new Proxy();
        proxy.setUserService(userService);
        proxy.add();
    }
}

De esta manera, hemos tenido que añadir una función de registro, pero en línea con el principio de apertura y cierre, al tiempo que reduce el acoplamiento, que es la aplicación de un modo de proxy estático.

Sin embargo, esto debe ser un proxy para cada función real, ya que cada uno de los servicios arriba, para ser un proxy o una molestia, la forma de resolverlo, como programador sin duda pensar en utilizar la reflexión, sólo una simple fábrica, me no quieren pasar la cadena en la que la distinción sub-clase, y voy clase pase recta y, a continuación, utilizar la reflexión para generar automáticamente el tipo de fábrica, entonces no estamos también ser directamente reflejó generan automáticamente clase proxy queremos proxy de ella, pensando que hay y, específicamente, la forma de lograr?

proxy dinámico

1, el papel del análisis: estática y proxy dinámico papel como agente

2, la clase proxy dinámico se genera automáticamente de forma dinámica, no nuestra directo emitidas

3, proxy dinámico divididos en dos categorías: interfaz basada en agente dinámico, basado en la clase proxy dinámico

    * ---- JDK dinámica interfaz basada en proxy

    * Basado en la Clase: cglib

    * Java bytecode: javasist (aprender a ser ligeramente más baja)

 

proxy dinámico JDK

Aquí nos centramos en los proxies en términos de dinámica bajo JDK, en primer lugar hay que entender primero dos clases: Proxy (Proxy), invocationHandler (procesamiento de llamadas)

Api InvocationHandler echar un vistazo a esta clase, podemos ver que se trata de una interfaz de reflexión en el paquete, a continuación, sabemos que hace uso de una tecnología reflectante.

Señalamos entrar y ver sólo una forma de saberlo

 Bueno, entonces vamos a ver el siguiente proxy de clase

 

Del mismo modo, también es un reflejo del paquete de las siguientes clases, sino que le dice dos maneras de crear un proxy 

El método es llamar a un método que getProxyClass primero obtener un constructor de objeto, el objeto newInstance utilizar este constructor para construir el objeto, y se pasa el manejador aprobada en la última declaración de una clase de proxy que desea.

El método 2 es más simple y sencillo método para devolver la llamada clase proxy directa newProxcyInstance para el objeto. 

En primer lugar, nuestro objetivo es obtener un proxy dinámico, eso significa que predicar lo que me gusta venir a cambio debe dar a un objeto proxy, el objeto que necesitamos tener una manera de hacer un poco de operación que desea operar en la clase de proxy, se puede observar desde api de solo, esto es equivalente a invocationHadler interfaz abstracta que necesitamos para poner en práctica, ya que el comportamiento de los inquilinos que agente de primera estática en (una clase de proxy y el método común de clase real).

1. generación de proxy universal que puede representar cualquier interfaz, devolver el objeto de la clase proxy que desea.

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 11:42 2020-3-11
 */
public class DynamicProxyProvider implements InvocationHandler {
    //被代理的接口
    private Object target;

    public void setObject(Object target) {
        this.target = target;
    }

    //第一个参数是为了加载类在哪个位置classLoader
    //代理类的接口
    //自己本身
    public Object getProxy(){
      return  Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
    }


    //从参数可以看出我们需要一个代理类,所以我们来一个方法生成代理类
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        log(method.getName());
        Object invoke = method.invoke(target, args);
        return invoke;
    }

    public void log(String msg){
        System.out.println("调用了"+msg+"方法");
    }
}

2. La necesidad de interfaces y entidades agente.

/**
 * @Author Darker
 * @Descrption 租房
 * @Date : Created in 10:00 2020-3-11
 */
public interface Rent {
    public void rent();
}


/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:01 2020-3-11
 */
public class Host implements Rent {
    @Override
    public void rent() {
        System.out.println("房东出租房子");
    }
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:19 2020-3-11
 */
public interface UserService {
    public void add();

    public void delete();
}

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 10:20 2020-3-11
 */
public class UserServiceImpl implements UserService {
    @Override
    public void add() {
        System.out.println("增加一个角色");
    }

    @Override
    public void delete() {
        System.out.println("删除一个角色");
    }
}

3. Las llamadas del cliente de acuerdo a la demanda del agente

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 11:50 2020-3-11
 */
public class Client {
    public static void main(String[] args) {
        Rent rent = new Host();
        DynamicProxyProvider proxyProvider = new DynamicProxyProvider();
        proxyProvider.setObject(rent);
        Rent proxyRent =(Rent) proxyProvider.getProxy();
        proxyRent.rent();

        UserServiceImpl userService = new UserServiceImpl();
        proxyProvider.setObject(userService);
        UserService proxyUserService = (UserService) proxyProvider.getProxy();
        proxyUserService.add();
    }
}

 

 No es magia, usar un proxy, es posible que desee Mejoras en la interfaz, tales como la adición de un registro, agregar registros operativos.

ventajas:

1. tiene todas las ventajas de un agentes estáticos

2. Una clase dinámica de proxy proxy es una interfaz, que corresponde en general a una clase de servicio que

3. Una clase dinámica proxy puede representar una pluralidad de clases, siempre que la interfaz para alcanzar el mismo

Pero! Pero! Pero! ! ! ! Después de estas dos clases de la pena al final es cómo hacer que genera dinámicamente proxy, por eso añado un método en el que método de invocación, cada método de clase agente voy a cambiarlo?

Bueno, ahora analizamos principio de aplicación proxy dinámico.

1. la clase de proxy para obtener una referencia, y que obtiene la totalidad de sus interfaces (reflexión adquirida). Nota: ¿Por qué no clase proxy directa, tiene que formar una interfaz con el agente, porque es todo método, el código de la reflexión de obtener INTERFCE.

clase 2.jdk Proxy para regenerar una nueva clase que implementa todos los métodos de la interfaz es la clase de proxy.

3. código java generado dinámicamente, se añade la lógica mejorar al código recién generado.

4. Los nuevos archivos de clase compilados código Java.

5. Cargar y volver a ejecutar la nueva clase, la clase es conseguir una nueva clase.

¿Por qué tenemos una clase completamente nueva de la misma, tenemos que mirar a la salida de la mirada de clase, nos encontraremos su tipo en un lugar UserServiceImpl $ Proxy1.

 

JDK, al final, no es como nos gustaría que lo haga, entramos en su enfoque para ver.

 

Efectivamente, se reconstruyó una clase, lo que puede explicar por qué se puede mejorar nuestro enfoque, y puso todos los medios para volver a escribir de nuevo, para ver si es anti-compilado archivos de clase, también lo encontrará los métodos son finales, lo que significa que sólo puede ser un proxy (también, por qué darse cuenta de lo anterior es menor que la longitud de la interfaz 65535, encontré la respuesta en un blog de los demás).

 proxy dinámico cglib

Lo anterior hablado de proxy de JDK dinámico, descubrieron un problema que sólo puede tener agentes de todas las subclases de una interfaz general para volver a escribir una nueva clase a través de todas las maneras de escanear el interior de esta interfaz, entonces la pregunta es, si sin interfaz de cómo hacerlo, tengo una sola clase, por supuesto, hay soluciones que cglib de proxy dinámico de lograr.

1. cglib primero en escribir una clase de proxy (aplicación cglib es un interceptor de paquetes debajo de ella MethodInterceptor, representados, la clase de proxy que desea establecer en la forma de la clase padre, es decir, el uso del principio de la herencia, la subclase puede heredar la clase padre y la reescritura de la clase padre)

/**
 * @Author Darker
 * @Descrption 实现一个cglib的拦截器
 * @Date : Created in 16:32 2020-3-11
 */
public class CGlibProxyPriveder implements MethodInterceptor {

    public Object getProxy(Class<?> clazz){
        //相当于cglib给你写了个生成代理的工具类,你只要把class传进来就可以了
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(clazz);
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) {
        log(method.getName());
        try {
            methodProxy.invokeSuper(o,objects);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        return null;
    }

    public void log(String msg){
        System.out.println("调用了"+msg+"方法");
    }
}

2. la clase de proxy no implementa la interfaz, por supuesto, también ser implementado, y sobre todo para distinguir el proxy dinámico JDK.

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 17:34 2020-3-11
 */
public class UserImpl {
    public void add(){
        System.out.println("添加一个用户");
    }
}

3. Ejecutar

/**
 * @Author Darker
 * @Descrption
 * @Date : Created in 17:36 2020-3-11
 */
public class CGlibTest {
    public static void main(String[] args) {
        CGlibProxyPriveder cGlibProxyPriveder = new CGlibProxyPriveder();
        UserImpl cGlibProxy = (UserImpl)cGlibProxyPriveder.getProxy(UserImpl.class);
        cGlibProxy.add();
    }
}

bien, con éxito, parece cglib también completó nuestra función de proxy.

 

resumen:

1.jdk mecanismo dinámico de proxy se implementa utilizando la reflexión, que está orientada de interfaz; cglib el agente dinámico basado bytecode subyacente herencia de clases de proxy de lograr, es un potente, de alto rendimiento de producción de la biblioteca de código, se puede lograr CGLIB el tiempo de ejecución de java clase expansión dinámica (ya que se hereda lograr, por lo que si la clase de proxy si modifica por la palabra clave final, se producirá un error).

2. Con respecto a los dos problemas de rendimiento:

CGLIB objeto dinámico de proxy creado en el rendimiento del tiempo de funcionamiento real de alta montón de proxy dinámico JDK, porque genera una lógica todos FastClass incluido, que contiene el método que se llama, no necesita ser invocado mediante la reflexión que hay los estudios han demostrado que la velocidad es aproximadamente 10 veces superior;

Pero cuando el tiempo CGLIB crear objetos que se necesita mucho más JDK proxy dinámico, la lógica de generación de proxy porque cglib más complejo, los estudios han demostrado que aproximadamente 8 veces la brecha;

Así, para un objeto proxy o una instancia de proxy de la piscina singleton, porque sin frecuentes Crea un objeto proxy, es más adecuado para el proxy CGLIB dinámico, de todos modos, es más adecuado para proxy dinámico JDK.

 

Modo Proxy y la primavera

Bueno, siempre decimos springAop lograr es utilizar el modelo de agencia, entonces usted sabe lo que es con el agente para lograr una cosa dinámica, y ahora tenemos que encontrar la primavera-AOP siguientes ProxyFactoryBean toman una mirada en el interior para encontrar getObject método.

Usted verá aquí, hay un juicio, si desea que la clase de proxy es un producto único, que devuelve un tipo de producto único de proxy, haya varios casos, los rendimientos de proxy más de un caso, nos fijamos en el singleton de retorno a.

 

De la sentencia anterior puede saber, pero hay implementos de frijol de la interfaz, mientras que el archivo de configuración no está configurado para usar la fuerza cuando Proxy cglib, se utilizará automáticamente proxy dinámico JDK, o si esto no es la interfaz de frijol, a continuación, se utiliza para cglib dinámicamente agentes.

Datos adjuntos:

Configuración cglib configuración abierta (se puede ver, de hecho, se derivan de la fuente de configurar, y aquí hay cuatro formas de clase mybatis exploración tener el mismo propósito):

 

Publicado 27 artículos originales · ganado elogios 1 · vistas 3644

Supongo que te gusta

Origin blog.csdn.net/qq_40111437/article/details/104789444
Recomendado
Clasificación