Java proxy mode JDKProxy and CGLibProxy

Java proxy mode

Proxy mode

Proxy is a design pattern that provides another way to access the target object; that is, to access the target object through the proxy object. The advantage of this is that additional functional operations can be enhanced on the basis of the target object, namely Extend the function of the target object.
An idea in programming is used here: don’t modify the code or method that others have written at will. If you need to modify it, you can extend the method by proxy

Let me give an example to illustrate the role of an agent: suppose we want to invite a star, so instead of connecting directly with the star, we should contact the star’s agent to achieve the same purpose. The star is a target object, and he only needs to be responsible for the activities show, and other trivial matters are left to his agent (broker) to solve. This is an example of agency thinking in reality

The key points of the proxy mode are: the proxy object and the target object. The proxy object is an extension of the target object and will call the target object

jdkProxy mode (dynamic proxy)

The jdkProxy mode (dynamic proxy) has the following characteristics:

  1. Proxy object, no need to implement interface
  2. The generation of proxy objects is to use the API of JDK to dynamically build proxy objects in memory (we need to specify the type of interface implemented by creating proxy objects/target objects)
  3. Dynamic proxy is also called: JDK proxy, interface proxy

JDK only needs to use the newProxyInstance method to implement the proxy, but this method needs to receive three parameters. The complete writing method is:

static Object newProxyInstance(ClassLoader loader, Class<?>[] 
		interfaces,InvocationHandler h )

Note that this method is a static method in the Proxy class, and the three parameters received are:

  • ClassLoader loader: Specify the current target object to use the class loader, the method of obtaining the loader is fixed
  • Class<?>[] interfaces : The type of the interface implemented by the target object, using the generic method to confirm the type
  • InvocationHandler h : Event processing, when the method of the target object is executed, the method of the event handler will be triggered, and the method of the currently executing target object will be passed in as a parameter

Code example:
Interface class: ISomeClass.java

//接口
public interface ISomeClass {
    
    
	void doSomething(String mess);
	String doSomething(int num);
}

The target object class, that is, the interface implementation class:
SomeClass.java

public class SomeClass implements ISomeClass {
    
    

	public SomeClass() {
    
    
	}
	
	@Override
	public void doSomething(String mess) {
    
    
		System.out.println(mess);
	}

	@Override
	public String doSomething(int num) {
    
    
		return "num : " + String.valueOf(num);
	}
	
	public void doSomething() {
    
    
		System.out.println("This is doSomething() method.");
	}
}

Proxy factory class:
JDKProxy.java

public class JDKProxy {
    
    
	
	public JDKProxy() {
    
    
	}

	@SuppressWarnings("unchecked")
	public static <T> T getProxy(Object object) {
    
    
		Class<?> klass = object.getClass();
		ClassLoader loader = klass.getClassLoader(); 	// 类加载器
		Class<?>[] interfaces = klass.getInterfaces();	//获得这个对象所实现的所有接口
		
		return (T) Proxy.newProxyInstance(loader, interfaces, 
				new InvocationHandler() {
    
    
					@Override
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    
    

						System.out.println("在执行方法之前,可以做些事……");
						Object result = method.invoke(object, args);
						System.out.println("在执行方法之后前,也可以做些事……");
						return result;
					}
				});
	}
	
}

Test class:

public class Test {
    
    
	public static void main(String[] args) {
    
    
		SomeClass some = new SomeClass();
		//将ISomeClass的实现类,装入代理工厂
		ISomeClass someProxy = (ISomeClass) JDKProxy.getProxy(some);
		someProxy.doSomething("这是第一条消息");
	}
}

Test Results:insert image description here

CGLibProxy mode

The dynamic proxy mode requires that the target object is a target object that implements an interface, but sometimes the target object is just a single object that does not implement any interface. At this time, the proxy can be implemented by subclassing the target object. This method is called: CGLib Proxy

Cglib proxy, also called subclass proxy, builds a subclass object in memory to extend the function of the target object.

  • JDK's dynamic proxy has a limitation, that is, objects using dynamic proxy must implement one or more interfaces. If you want to proxy a class that does not implement an interface, you can use Cglib to implement it.
  • 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 and synaop, to provide them with method interception (interception)
  • The bottom layer of the Cglib package is to convert the bytecode and generate new classes by using a small and block bytecode processing framework ASM. Direct use of ASM is discouraged because it requires you to have the JVM internal structure including the format of the class file and The instruction set is very familiar.

Cglib subclass proxy implementation method:

  1. The jar file of cglib needs to be imported, but the core package of Spring already includes the Cglib function, so it pring-core-3.2.5.jarcan be imported directly.
  2. After the feature package is introduced, subclasses can be dynamically constructed in memory
  3. The proxy class cannot be final, otherwise an error will be reported
  4. If the method of the target object is final/static, it will not be intercepted, that is, no additional business method of the target object will be executed.

The target object class above is the interface implementation class: Although SomeClass.java implements the ISomeclass interface, it also has its own methods

public void doSomething() {
    
    
		System.out.println("This is doSomething() method.");
	}

So we can use Cglib proxy to implement the above method
Code example:

 	//给目标对象创建一个代理对象
	@SuppressWarnings("unchecked")
	public static <T> T getProxy(Object object) {
    
    
		Class<?> klass = object.getClass();
		//1.工具类
		Enhancer enhancer = new Enhancer();
		//2.设置父类
		enhancer.setSuperclass(klass);
		//3.设置回调函数
		enhancer.setCallback(new MethodInterceptor() {
    
    
			@Override
			public Object intercept(Object obj, Method method, 
					Object[] args, MethodProxy mObj) throws Throwable {
    
    
				System.out.println("前置拦截");
				//执行目标对象的方法
				Object result = method.invoke(object, args);
				System.out.println("后置拦截");
				
				return result;
			}
		});
		//4.创建子类(代理对象)
		return (T) enhancer.create();
	}

Test class:

	public static void main(String[] args) {
    
    
		//创建目标对象
		SomeClass some = new SomeClass();
		//将目标对象装入Cglib代理
		SomeClass somePro = CGLibProxy.getProxy(some);
		//用Cglib执行非接口类方法
		somePro.doSomething();
	}

Execution result:
insert image description hereIn the face of these two proxy modes
, if the target object added to the container has an implementation interface, use JDK proxy;
if the target object does not implement the interface, use Cglib proxy

Guess you like

Origin blog.csdn.net/adaizzz/article/details/109545863