Dynamic proxy is divided into two methods: JDK dynamic proxy and cglib dynamic proxy.
jdk dynamic proxy is implemented by Java's internal reflection mechanism, and the bottom layer of cglib dynamic proxy is implemented with the help of asm.
In general, the reflection mechanism is more efficient in the process of generating classes, while asm is more efficient in the related execution process after generating the class (you can cache the classes generated by asm, so as to solve the problem of asm generation Process inefficiency issues).
There is another point that must be noted: The prerequisite for the application of jdk dynamic proxy must be that the target class is based on a unified interface. Without the above prerequisites, jdk dynamic proxy cannot be applied.
It can be seen that jdk dynamic proxy has certain limitations. Dynamic proxy implemented by third-party class libraries such as cglib is more widely used and has more advantages in efficiency.
The following code uses proxy mode to implement a function of converting uppercase and lowercase characters.
Definition of interface and implementation class:
ISomeService interface:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;/** * 接口类 * * @author Root */public interface ISomeService { String doFirst(); void doSecond(); }
SomeServiceImpl implementation class:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;/** * 实现类 * * @author Root */public class SomeServiceImpl implements ISomeService { @Overridepublic String doFirst() { System.out.println("执行doFirst()..."); String result = "abcde";return result; } @Overridepublic void doSecond() { System.out.println("执行doSecond()..."); } }
JDK dynamic proxy class:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;import java.lang.reflect.InvocationHandler;import java.lang.reflect.Method;import java.lang.reflect.Proxy;public class Main {public static void main(String[] args) {final ISomeService target = new SomeServiceImpl(); // 使用JDK的Proxy动态代理,要求目标类和代理类必须实现相同的接口,因为其底层的执行原理与静态代理的相同ISomeService service = (ISomeService) Proxy.newProxyInstance(// 目标类的类加载器 target.getClass().getClassLoader(),// 目标类所实现的所有接口 target.getClass().getInterfaces(), new InvocationHandler() {// proxy:代理对象// method:目标方法// args:目标方法的参数列表 @Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 调用目标方法Object result = method.invoke(target, args);if (result != null) { result = ((String) result).toUpperCase(); }return result; } }); String result = service.doFirst(); System.out.println(result); service.doSecond(); } }
Cglib is an excellent dynamic proxy framework. Its bottom layer is dynamically generated in memory using ASM Subclasses of the proxied class can use CGLIB to implement dynamic proxy functions even if the proxy class does not implement any interface. CGLIB is simple and easy to use, and it runs much faster than JDK's Proxy dynamic proxy:
Core class of CGLIB:
net.sf.cglib.proxy.Enhancer – the main enhancement class
net.sf.cglib.proxy.MethodInterceptor – the main method interception class, which is a sub-interface of the Callback interface and requires users to implement
net.sf.cglib.proxy.MethodProxy – JDK’s java.lang.reflect. The proxy class of the Method class can conveniently call the source object method, such as using:
Object o = methodProxy.invokeSuper(proxy, args);//Although the first parameter is the proxy object, it will not An infinite loop problem occurs.
net.sf.cglib.proxy.MethodInterceptor interface is the most common callback type, which is often used by proxy-based AOP to implement intercept method calls. This interface only defines one method
public Object intercept(Object object, java.lang.reflect.Method method, Object[] args, MethodProxy proxy) throws Throwable;
The first parameter is the proxy pair Like, the second and third parameters are the intercepted method and method parameters respectively. The original method may be called through normal reflection using a java.lang.reflect.Method object, or using a net.sf.cglib.proxy.MethodProxy object. net.sf.cglib.proxy.MethodProxy is usually preferred because it is faster.
The following program implements the function of case conversion:
Implementation class SomeService:
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;/** * 实现类 * * @author Root */public class SomeService {public String doFirst() { System.out.println("执行doFirst()..."); String result = "abcde";return result; }public void doSecond() { System.out.println("执行doSecond()..."); } }
Agent class MyCglibFactory:
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;import java.lang.reflect.Method;import net.sf.cglib.proxy.Enhancer;import net.sf.cglib.proxy.MethodInterceptor;import net.sf.cglib.proxy.MethodProxy;public class MyCglibFactory implements MethodInterceptor {private SomeService target; public MyCglibFactory() {super(); target = new SomeService(); }public SomeService myCglibCreator() {// 创建增强器对象Enhancer enhancer = new Enhancer();// 指定目标类,即父类enhancer.setSuperclass(SomeService.class);// 设置回调接口对象enhancer.setCallback(this);return (SomeService) enhancer.create(); } @Overridepublic Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {// 调用目标方法Object result = method.invoke(target, args);if (result != null) { result = ((String) result).toUpperCase(); }return result; } }
Test:
package com.ietree.basicskill.designpattern.dynamicproxy.cglib;public class Main {public static void main(String[] args) { SomeService service = new MyCglibFactory().myCglibCreator(); String result = service.doFirst(); System.out.println("result = " + result); service.doSecond(); } }
Run result:
执行doFirst()... result = ABCDE 执行doSecond()...
The above is the detailed content of Design pattern dynamic proxy. For more information, please follow other related articles on the PHP Chinese website!