Tabla de contenido
5. La estructura del código es la siguiente:
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: