Spring-proxy estático y proxy dinámico

Tabla de contenido

1. Proxy estático

1. Clase de proxy:

2. Archivo de configuración:

3. Clase de implementación:

4. Clase de prueba:

5. La estructura del código es la siguiente:

 Dos, proxy dinámico

1. Cree service y serviceImpl de la siguiente manera:

 2. Cree un dominio de la siguiente manera:

3. Archivo de configuración applicationContext.xml:

4. El procesador es el siguiente:


1. Proxy estático

interino:

  • Agregue funciones adicionales al método de destino sin modificar el código del método de destino de la clase de destino
  • La clase de proxy también debe tener el mismo método de destino.
  • La clase de proxy implementa la misma interfaz que la clase de destino
  • Si la clase de destino no implementa la interfaz, la clase de proxy hereda la clase de destino
  • Básicamente, cada clase de destino tiene que escribir una clase de proxy

El núcleo es crear manualmente una clase de proxy para implementar el servicio y luego en el archivo de configuración: el bean inyectado se convierte en la clase de proxy y el atributo de destino en la clase de proxy se convierte en la clase de implementación.

1. Clase de proxy:

package com.mj.proxy;

import com.mj.service.UserService;

public class UserServiceProxy implements UserService {
    private UserService target;

    public void setTarget(UserService target) {
        this.target = target;
    }

    public boolean login(String username, String password) {
        System.out.println("这里写附加代码1");
        target.login(username,password);
        System.out.println("这里写附加代码2");
        return false;
    }
}
package com.mj.proxy;

import com.mj.service.SkillService;

public class SkillServiceProxy extends SkillService {

    private SkillService target;

    public void setTarget(SkillService target) {
        this.target = target;
    }

    @Override
    public boolean save(Object skill) {
        System.out.println("SkillServiceProxy ----- 1");
        boolean result = target.save(skill);
        System.out.println("SkillServiceProxy ----- 2");
        return result;
    }
}

 

2. Archivo de configuración:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="userService" class="com.mj.proxy.UserServiceProxy">
        <property name="target" >
            <bean class="com.mj.service.impl.UserServiceImpl"/>
        </property>
    </bean>

    <bean id="skillService" class="com.mj.proxy.SkillServiceProxy">
        <property name="target" >
            <bean class="com.mj.service.SkillService"/>
        </property>
    </bean>

</beans>

3. Clase de implementación:

package com.mj.service.impl;

import com.mj.service.UserService;

public class UserServiceImpl implements UserService {

    public boolean login(String username, String password) {
        System.out.println("--login " + username + password);
        return false;
    }

}
package com.mj.service;

public class SkillService {
    public boolean save(Object skill) {
        System.out.println("SkillService --- save");
        return false;
    }
}

 

4. Clase de prueba:

 @Test
    public void test(){
        // 创建容器
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService service = ctx.getBean("userService", UserService.class);
        boolean result = service.login("小马哥","123456");
        // 关闭容器
        ctx.close();


        // 创建容器
        ClassPathXmlApplicationContext ctx1 = new ClassPathXmlApplicationContext("applicationContext.xml");
        SkillService service1 = ctx1.getBean("skillService", SkillService.class);
        service1.save(null);
        // 关闭容器
        ctx1.close();
    }

5. La estructura del código es la siguiente:

 Dos, proxy dinámico

Hay dos esquemas para el proxy dinámico, uno es jdk y el otro es el esquema cglib:

  • La solución que viene con jdk: se debe escribir un cargador, y solo puede representar dinámicamente la interfaz
  • esquema cglib: un cargador de clases se pasará internamente, y no es solo un proxy dinámico para la interfaz

1. Cree service y serviceImpl de la siguiente manera:

  • personService: void ejecutar(); método
  • servicio de usuario: inicio de sesión booleano (nombre de usuario de cadena, contraseña de cadena); 方 法
  • skillService es una clase:
public class SkillService {
    public boolean save(Object skill) {
        System.out.println("SkillService --- save");
        return false;
    }
}

 2. Cree un dominio de la siguiente manera:

Cree la clase Person y los métodos relacionados de la siguiente manera:

public class Person {
    public void eat() {
        System.out.println("Person --- eat");
    }
}

3. Archivo de configuración applicationContext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">


<!--    <bean class="com.mj.processor.LogProcessor"/>-->
    <bean class="com.mj.processor.LogProcessor2"/>
    <bean id="userService" class="com.mj.service.impl.UserServiceImpl"/>
    <bean id="personService" class="com.mj.service.impl.PersonServiceImpl"/>
    <bean id="skillService" class="com.mj.service.SkillService"/>

    <bean id="person" class="com.mj.domain.Person"/>

</beans>

4. El procesador es el siguiente:

  • La configuración relacionada con el proxy dinámico que viene con jdk:
package com.mj.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

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

/**
 * 会拦截每一个bean的生命周期,这个是jdk自带的动态代理方案,必须要写加载器,并且只能对接口动态代理
 */
public class LogProcessor implements BeanPostProcessor {

    public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {
      return   Proxy.newProxyInstance(getClass().getClassLoader(), // 类加载器,必须要有
                target.getClass().getInterfaces(),      // 代理类需要实现的接口(目标类的接口),必须要有接口不然会报错
                new LogInvocationHandler(target));      // 附加代码
    }


    private static class LogInvocationHandler implements InvocationHandler {
        private Object target;

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

        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

            // proxy: 代理对象
            // method:目标方法
            // args:目标方法的参赛
            System.out.println("proxy111-----------------1");
            // 调用目标对象的目标方法(核心业务代码)
            Object result = method.invoke(target,args);
            System.out.println("proxy222-----------------2");
            return result;
        }
    }
}

Configuración relacionada con el proxy dinámico de cglib:

package com.mj.processor;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**
 * 会拦截每一个bean的生命周期,CGlib方案,内部会传一个类加载器,并且不只是对接口进行动态代理
 */
public class LogProcessor2 implements BeanPostProcessor {
    public Object postProcessAfterInitialization(Object target, String beanName) throws BeansException {

        // 有些需要过滤
       if (!beanName.endsWith("Service")) return target;

        Enhancer enhancer = new Enhancer();
        enhancer.setClassLoader(getClass().getClassLoader());// cglib可以不要
        enhancer.setSuperclass(target.getClass());
        enhancer.setCallback(new LogMethodInterceptor(target));
        return enhancer.create();
    }

    private static class LogMethodInterceptor implements MethodInterceptor {
        private Object target;

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

        public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
            System.out.println("proxy1-------------------");
            Object result = method.invoke(target,args);
            System.out.println("proxy2-------------------");
            return result;
        }
    }
}

La estructura del proyecto de prueba es la siguiente:

 

Supongo que te gusta

Origin blog.csdn.net/weixin_45689945/article/details/127153822
Recomendado
Clasificación