Proxy mode analysis, static proxy and dynamic proxy will tell you all

Proxy Pattern

After two months of learning, our series of design patterns is coming to an end. However, design patterns will definitely not be mastered for a while, and we need to continue to practice in the follow-up work. With this kind of thinking, the rest is deliberate training on their own.

What we brought today is the proxy pattern, Proxy Pattern. This mode must be familiar to everyone, because Spring Aop, which is generally asked by Java programmers in interviews, will talk about dynamic proxy, which is actually an implementation of proxy mode. However, most people may not have understood it systematically. The purpose of this article is to thoroughly understand the small 99 of the agency model.

Before reading, I also think about several questions about the agency model, and learn with the purpose of clarifying the problem.

Start with questions

  1. What is the agency model?
  2. Static proxy?
  3. Dynamic proxy?
  4. Common proxy model variants?

Introduction to proxy mode

Proxy mode: Provide a stand-in or placeholder for an object to control access to this object. That is, access the target object through the proxy object. The advantage of this is that it can enhance additional functional operations based on the realization of the target object, that is, expand the function of the target object. But the focus here is still on the control of "object" access.

  1. The proxied objects can be: remote objects, objects that are expensive to create, or objects that require security control;
  2. The proxy mode has different forms, there are three main types: static proxy, dynamic proxy (JDK and Cglib);

Agent model class diagram

Insert picture description here

Static proxy

When using a static proxy, you need to define an interface or a parent class. The proxy object (target object) and the proxy object implement the same interface or inherit the same parent class.

Applications

Specific requirements

  1. Define an interface: ITeacherDao
  2. The current object TeacherDAO implements ITeacherDao
  3. To use a static proxy, you need to implement the ITeacherDao interface in TeacherDAOProxy
  4. When calling, call the target object by calling the method of the proxy object
  5. Special attention: the proxy object must implement the same interface as the target object, and then call the method of the target object by calling the same method

Idea analysis diagram (class diagram)

Insert picture description here

Code

public class Client {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		//创建目标对象(被代理对象)
		TeacherDao teacherDao = new TeacherDao();
		
		//创建代理对象, 同时将被代理对象传递给代理对象
		TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);
		
		//通过代理对象,调用到被代理对象的方法
		//即:执行的是代理对象的方法,代理对象再去调用目标对象的方法 
		teacherDaoProxy.teach();
	}

}
//接口
public interface ITeacherDao {
    
    
	
	void teach(); // 授课的方法
}
public class TeacherDao implements ITeacherDao {
    
    

	@Override
	public void teach() {
    
    
		// TODO Auto-generated method stub
		System.out.println(" 老师授课中  。。。。。");
	}

}
//代理对象,静态代理
public class TeacherDaoProxy implements ITeacherDao{
    
    
	
	private ITeacherDao target; // 目标对象,通过接口来聚合
	
	//构造器
	public TeacherDaoProxy(ITeacherDao target) {
    
    
		this.target = target;
	}

	@Override
	public void teach() {
    
    
		// TODO Auto-generated method stub
		System.out.println("开始代理  完成某些操作。。。。。 ");//方法
		target.teach();
		System.out.println("提交。。。。。");//方法
	}

}

Advantages and disadvantages of static proxy

  1. Advantages: The target function can be extended through the proxy object without changing the target object function
  2. Disadvantages: Obviously, because the proxy object needs to implement the same interface as the target object, there will be many proxy classes
  3. Once a method is added to the interface, the target object and proxy object must be maintained

Dynamic proxy

The dynamic agent is divided into JDK dynamic agent and Cglib dynamic agent. Let's take a look at how JDK dynamic agent plays.

JDK dynamic proxy

  1. The proxy object does not need to implement the interface, but the target object must implement the interface, otherwise the JDK dynamic proxy cannot be used
  2. The generation of proxy objects uses the JDK API to dynamically build proxy objects in memory

API for generating proxy objects in JDK

  1. The package where the proxy class is located:java.lang.reflect.Proxy
  2. JDK implementation agent only need to use the newProxyInstancemethod, but this method requires three parameters, complete wording is:static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)

JDK dynamic proxy application example

Here we will improve the above example using JDK dynamic proxy to proxy dynamic.

Idea diagram (class diagram)

Insert picture description here

Code

public class Client {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		//创建目标对象
		ITeacherDao target = new TeacherDao();
		
		//给目标对象,创建代理对象, 可以转成 ITeacherDao
		ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();
	
		// proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
		System.out.println("proxyInstance=" + proxyInstance.getClass());
		
		//通过代理对象,调用目标对象的方法
		//proxyInstance.teach();
		
		proxyInstance.sayHello(" tom ");
	}

}
//接口
public interface ITeacherDao {
    
    

	void teach(); // 授课方法
	void sayHello(String name);
}
public class ProxyFactory {
    
    

	//维护一个目标对象 , Object
	private Object target;

	//构造器 , 对target 进行初始化
	public ProxyFactory(Object target) {
    
    
		
		this.target = target;
	} 
	
	//给目标对象 生成一个代理对象
	public Object getProxyInstance() {
    
    
		
		//说明
		/*
		 *  public static Object newProxyInstance(ClassLoader loader,
                                          Class<?>[] interfaces,
                                          InvocationHandler h)
                                          
            //1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
            //2. Class<?>[] interfaces: 目标对象实现的接口类型,使用泛型方法确认类型
            //3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行的目标对象方法作为参数传入
		 */
		return Proxy.newProxyInstance(target.getClass().getClassLoader(), 
				target.getClass().getInterfaces(), 
				new InvocationHandler() {
    
    
					
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    
						// TODO Auto-generated method stub
						System.out.println("JDK代理开始~~");
						//反射机制调用目标对象的方法
						Object returnVal = method.invoke(target, args);
						System.out.println("JDK代理提交");
						return returnVal;
					}
				}); 
	}
	
}
public class TeacherDao implements ITeacherDao {
    
    

	@Override
	public void teach() {
    
    
		// TODO Auto-generated method stub
		System.out.println(" 老师授课中.... ");
	}

	@Override
	public void sayHello(String name) {
    
    
		// TODO Auto-generated method stub
		System.out.println("hello " + name);
	}
	
}

The code is also very simple, if you are not familiar with it, be sure to write the code above to get a feel.

Cglib dynamic proxy

  1. Both static proxy and JDK dynamic proxy require the target object to implement an interface, but sometimes the target object is just a single object and does not implement any interface. In this case, you can use a subclass of the target object to implement the proxy, which is Cglib proxy.

  2. Cglib agent is also called subclass agent, which is to expand the target object by constructing a subclass object in memory.

  3. Cglib is a powerful high-performance code generation package that can extend Java classes and implement Java interfaces at runtime. It is widely used by many AOP frameworks, such as Spring AOP, to implement method interception.

  4. How to choose which dynamic proxy to use in AOP programming?

    1. The target object implements the interface and uses the JDK dynamic proxy
    2. The target object does not need to implement the interface, use Cglib to implement the proxy
  5. The bottom layer of the Cglib package is the bytecode processing framework ASM to convert bytes and generate new classes

Cglib dynamic proxy implementation steps

  1. Need to introduce the jar package of cglib

  2. Subclasses are dynamically created in memory, so the class (target object) that needs to be proxied cannot be final, otherwise an error will be reported:
    Insert picture description here

  3. If the method of the proxied object is final/static, then the target method will not be intercepted, and the additional business processing of the target object method will not be performed, because the final and static modified methods cannot be extended by subclasses

Application example

Requirements: Implement the previous example using Cglib proxy mode

Idea diagram (class diagram)

Insert picture description here

Code

public class Client {
    
    

	public static void main(String[] args) {
    
    
		// TODO Auto-generated method stub
		//创建目标对象
		TeacherDao target = new TeacherDao();
		//获取到代理对象,并且将目标对象传递给代理对象
		TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();

		//执行代理对象的方法,触发intecept 方法,从而实现 对目标对象的调用
		String res = proxyInstance.teach();
		System.out.println("res=" + res);
	}

}
public class ProxyFactory implements MethodInterceptor {
    
    

	//维护一个目标对象
	private Object target;
	
	//构造器,传入一个被代理的对象
	public ProxyFactory(Object target) {
    
    
		this.target = target;
	}

	//返回一个代理对象:  是 target 对象的代理对象
	public Object getProxyInstance() {
    
    
		//1. 创建一个工具类
		Enhancer enhancer = new Enhancer();
		//2. 设置父类
		enhancer.setSuperclass(target.getClass());
		//3. 设置回调函数
		enhancer.setCallback(this);
		//4. 创建子类对象,即代理对象
		return enhancer.create();
		
	}

	//重写  intercept 方法,会调用目标对象的方法
	@Override
	public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
    
    
		// TODO Auto-generated method stub
		System.out.println("Cglib代理模式 ~~ 开始");
		Object returnVal = method.invoke(target, args);
		System.out.println("Cglib代理模式 ~~ 提交");
		return returnVal;
	}

}
public class TeacherDao {
    
    

	public String teach() {
    
    
		System.out.println(" 老师授课中  , 我是cglib代理,不需要实现接口 ");
		return "hello";
	}
}

Variations of several common proxy modes

  1. Firewall proxy

    1. The internal network realizes the penetration of the firewall through the proxy, and realizes the access to the public network
  2. Caching proxy

    1. When requesting files such as pictures, first go to the cache agent to fetch them. If you can fetch the resources, everyone is happy. If you can’t fetch them, go to the public network or database to fetch them, and then cache
  3. Remote agent

    1. The local proxy of the remote object, through which the remote object can be called as the local object. The remote proxy object communicates with the real remote object through the network protocol

to sum up

This article uses class diagrams and code examples to give a detailed explanation of the proxy model, aiming to let you grasp the definition of the proxy model and the static proxy, proxy proxy, and the difference between the JDK dynamic proxy and the Cglib dynamic proxy and implementation the way.

The full text code is passed by the author locally and can be used directly for testing.


The full text is over, fighting!

Personal public account

Insert picture description here

  • Friends who feel that they are writing well can bother to like and follow ;
  • If the article is incorrect, please point it out, thank you very much for reading;
  • I recommend everyone to pay attention to my official account, and I will regularly push original dry goods articles for you, and pull you into the high-quality learning community;
  • github address: github.com/coderluojust/qige_blogs

Guess you like

Origin blog.csdn.net/taurus_7c/article/details/107890887