동적 프록시는 JDK 동적 프록시와 cglib 동적 프록시의 두 가지 방법으로 나뉩니다.
jdk 동적 프록시는 Java 내부의 반사 메커니즘으로 구현되는 반면 cglib 동적 프록시의 하위 레이어는 asm의 도움으로 구현됩니다.
일반적으로 클래스를 생성하는 과정에서는 리플렉션 메커니즘이 더 효율적이고, 클래스 생성 후 관련 실행 과정에서는 asm이 더 효율적입니다. (asm 클래스 생성 프로세스의 비효율성은 생성된 클래스를 캐싱하여 해결할 수 있습니다.) asm 질문).
주의해야 할 또 다른 사항이 있습니다. jdk 동적 프록시를 적용하기 위한 전제 조건은 대상 클래스가 통합 인터페이스를 기반으로 해야 한다는 것입니다. 위의 전제조건이 없으면 jdk 동적 프록시를 적용할 수 없습니다.
이를 통해 jdk 동적 프록시에는 특정 제한 사항이 있음을 알 수 있습니다. cglib과 같은 타사 라이브러리로 구현된 동적 프록시는 더 널리 사용되고 효율성 면에서 더 많은 이점을 갖습니다.
다음 코드는 프록시 모드를 사용하여 대문자와 소문자를 변환하는 기능을 구현합니다.
인터페이스 및 구현 클래스 정의:
ISomeService 인터페이스:
package com.ietree.basicskill.designpattern.dynamicproxy.jdk;/** * 接口类 * * @author Root */public interface ISomeService { String doFirst(); void doSecond(); }
SomeServiceImpl 구현 클래스:
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 동적 프록시 클래스:
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는 우수한 동적 프록시 프록시 프레임워크의 최하위 계층은 ASM을 사용하여 메모리에 프록시 클래스의 하위 클래스를 동적으로 생성합니다. CGLIB를 사용하면 프록시 클래스가 인터페이스를 구현하지 않더라도 동적 프록시 기능을 구현할 수 있습니다. CGLIB는 간단하고 사용하기 쉬우며 JDK의 프록시 동적 프록시보다 훨씬 빠르게 실행됩니다.
CGLIB의 핵심 클래스:
net.sf.cglib.proxy.Enhancer - 주요 개선 클래스
net.sf.cglib 프록시. MethodInterceptor – 기본 메소드 차단 클래스입니다. 이는 콜백 인터페이스의 하위 인터페이스이며 사용자가 구현해야 합니다. net.sf.cglib.proxy.MethodProxy – JDK java.lang.reflect.Method의 프록시 클래스입니다.
Object o = methodProxy.invokeSuper(proxy, args);//첫 번째 매개변수가 프록시 객체이더라도 무한 루프 문제는 없습니다.
net.sf.cglib.proxy.MethodInterceptor 인터페이스는 가장 일반적인 콜백 유형으로 프록시 기반 AOP에서 인터셉트 메서드 호출을 구현하는 데 자주 사용됩니다. 이 인터페이스는 하나의 메소드만 정의합니다
공용 객체 인터셉트(Object 객체, java.lang.reflect.Method 메소드, Object[] args, MethodProxy 프록시)는 Throwable을 던집니다.
첫 번째 매개변수는 프록시 객체이고, 두 번째와 두 번째 매개변수는 세 가지 매개변수는 차단 방법과 방법의 매개변수입니다. 원래 메소드는 java.lang.reflect.Method 객체를 사용하거나 net.sf.cglib.proxy.MethodProxy 객체를 사용하여 일반 리플렉션을 통해 호출될 수 있습니다. net.sf.cglib.proxy.MethodProxy는 일반적으로 더 빠르기 때문에 선호됩니다.
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()..."); } }Proxy 클래스 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(); } }실행 결과:
执行doFirst()... result = ABCDE 执行doSecond()...
위 내용은 디자인 패턴 동적 프록시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!