>  기사  >  Java  >  Java의 정적, 동적 프록시 및 CGLIB 동적 프록시에 대한 자세한 설명(그림)

Java의 정적, 동적 프록시 및 CGLIB 동적 프록시에 대한 자세한 설명(그림)

黄舟
黄舟원래의
2017-08-08 10:02:171437검색

이 기사에서는 주로 JAVA의 정적 프록시, 동적 프록시 및 CGLIB 동적 프록시 요약을 소개합니다. 관심 있는 사람은 이에 대해 배울 수 있습니다.

프록시 패턴은 Java에서 가장 일반적으로 사용되는 디자인 패턴 중 하나입니다. 특히 스프링 프레임워크에서 널리 사용됩니다. Java 프록시 모드의 경우 일반적으로 정적 프록시, 동적 프록시, CGLIB 동적 프록시로 나눌 수 있습니다.

위의 세 가지 프록시 모드는 별도로 설명됩니다.

1. 정적 프록시

정적 프록시는 실제로 프로그램이 실행되기 전에 프록시 메서드의 프록시 클래스를 미리 작성한 다음 컴파일한 후에 실행하는 것을 의미합니다. 프로그램이 실행되기 전에 클래스가 이미 존재합니다.
아래에서는 정적 프록시 데모를 구현합니다.

정적 프록시

인터페이스 Target


package com.test.proxy;

public interface Target {

  public String execute();
}

TargetImpl을 정의하여 Target


package com.test.proxy;

public class TargetImpl implements Target {

  @Override
  public String execute() {
    System.out.println("TargetImpl execute!");
    return "execute";
  }
}

Proxy 클래스

를 구현합니다.

package com.test.proxy;

public class Proxy implements Target{

  private Target target;

  public Proxy(Target target) {
    this.target = target;
  }

  @Override
  public String execute() {
    System.out.println("perProcess");
    String result = this.target.execute();
    System.out.println("postProcess");
    return result;
  }
}

테스트 클래스:


package com.test.proxy;

public class ProxyTest {

  public static void main(String[] args) {

    Target target = new TargetImpl();
    Proxy p = new Proxy(target);
    String result = p.execute();
    System.out.println(result);
  }

}

작업 결과:


perProcess
TargetImpl execute!
postProcess
execute

정적 프록시는 프록시 메서드가 많을 경우 미리 프록시 클래스를 작성해야 합니다. 따라서 많은 코드를 작성해야 합니다. 위의 단점을 다이나믹 에이전트를 통해 보완하였습니다. Dyn Dynical Proxy는 주로 반사 메커니즘을 사용하여 런타임에서 필요한 프록시의 클래스를 동적으로 생성합니다.

package com.test.dynamic;

public interface Target {

  public String execute();
}

에이전트 클래스

package com.test.dynamic;

public class TargetImpl implements Target {

  @Override
  public String execute() {
    System.out.println("TargetImpl execute!");
    return "execute";
  }
}

테스트 클래스

package com.test.dynamic;


import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class DynamicProxyHandler implements InvocationHandler{

  private Target target;

  public DynamicProxyHandler(Target target) {
    this.target = target;
  }

  @Override
  public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
    System.out.println("========before==========");
    Object result = method.invoke(target,args);
    System.out.println("========after===========");
    return result;
  }
}

실행 결과:


package com.test.dynamic;

import java.lang.reflect.Proxy;

public class DynamicProxyTest {

  public static void main(String[] args) {
    Target target = new TargetImpl();
    DynamicProxyHandler handler = new DynamicProxyHandler(target);
    Target proxySubject = (Target) Proxy.newProxyInstance(TargetImpl.class.getClassLoader(),TargetImpl.class.getInterfaces(),handler);
    String result = proxySubject.execute();
    System.out.println(result);
  }

}

동적 프록시이든 정적 리더이든 관계없이 프록시 기능을 수행하기 전에 인터페이스를 정의해야 합니다. 구현됩니다. 여기에도 한계가 있으므로 이 문제를 해결하기 위해 세 번째 프록시 방법인 cglib 프록시가 등장했습니다.

3.cglib 프록시

CGLib는 바이트코드 기술을 통해 클래스에 대한 하위 클래스를 생성하고 하위 클래스에서 메소드 차단 기술을 사용하여 모든 상위 클래스를 차단하는 것이 원칙입니다. 교차 논리로 짜여져 있습니다. JDK 동적 프록시와 CGLib 동적 프록시는 모두 Spring AOP 구현의 기초입니다.


cglib 동적 프록시


대상 클래스

========before==========
TargetImpl execute!
========after===========
execute

일반 프록시 클래스:

package com.test.cglib;

public class Target {

  public String execute() {
    String message = "-----------test------------";
    System.out.println(message);
    return message;
  }
}
테스트 클래스

package com.test.cglib;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class MyMethodInterceptor implements MethodInterceptor{

  @Override
  public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
    System.out.println(">>>>MethodInterceptor start...");
    Object result = proxy.invokeSuper(obj,args);
    System.out.println(">>>>MethodInterceptor ending...");
    return "result";
  }
}

실행 결과:


package com.test.cglib;

import net.sf.cglib.proxy.Enhancer;

public class CglibTest {

  public static void main(String ... args) {
    System.out.println("***************");
    Target target = new Target();
    CglibTest test = new CglibTest();
    Target proxyTarget = (Target) test.createProxy(Target.class);
    String res = proxyTarget.execute();
    System.out.println(res);
  }

  public Object createProxy(Class targetClass) {
    Enhancer enhancer = new Enhancer();
    enhancer.setSuperclass(targetClass);
    enhancer.setCallback(new MyMethodInterceptor());
    return enhancer.create();
  }

}

프록시 객체 생성 이 프로세스는 Enhancer 클래스에 의해 구현되며 대략적인 단계는 다음과 같습니다.

1. 에이전트 클래스 Class의 바이너리 바이트코드를 생성합니다.

2 Class 객체를 생성하기 위해 Class.forName을 통해 바이너리 바이트코드를 로드합니다.


3. 리플렉션 메커니즘을 통해 인스턴스 구성을 얻고 프록시 클래스 개체를 초기화합니다.

위 내용은 Java의 정적, 동적 프록시 및 CGLIB 동적 프록시에 대한 자세한 설명(그림)의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.