Table of contents
5. The code structure is as follows:
1. Create service and serviceImpl as follows:
2. Create a domain as follows:
3. Configuration file applicationContext.xml:
4. The processor is as follows:
1. Static proxy
acting:
- Add additional functions to the target method without modifying the target method code of the target class
- The proxy class must also have the same target method
- The proxy class implements the same interface as the target class
- If the target class does not implement the interface, the proxy class inherits the target class
- Basically each target class has to write a proxy class
The core is to manually create a proxy class to implement the service, and then in the configuration file: the injected bean becomes the proxy class, and the target attribute in the proxy class becomes the implementation class.
1. Proxy class:
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. Configuration file:
<?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. Implementation class:
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. Test class:
@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. The code structure is as follows:
Two, dynamic agent
There are two schemes for dynamic proxy, one is jdk and the other is cglib scheme:
- The solution that comes with jdk: a loader must be written, and it can only dynamically proxy the interface
- cglib scheme: a class loader will be passed internally, and it is not just a dynamic proxy for the interface
1. Create service and serviceImpl as follows:
- personService: void run(); method
- userService: boolean login(String username, String password);方法
- skillService is a class:
public class SkillService { public boolean save(Object skill) { System.out.println("SkillService --- save"); return false; } }
2. Create a domain as follows:
Create the Person class and related methods as follows:
public class Person { public void eat() { System.out.println("Person --- eat"); } }
3. Configuration file 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. The processor is as follows:
- The dynamic proxy related configuration that comes with 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; } } }
cglib dynamic proxy related configuration:
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; } } }
The test project structure is as follows: