> Java > Java시작하기 > 본문

Java 프록시 모드 소개

王林
풀어 주다: 2021-01-27 09:50:44
앞으로
2909명이 탐색했습니다.

Java 프록시 모드 소개

먼저 에이전트가 무엇인지 소개하겠습니다.

(동영상 공유 학습: java 동영상 튜토리얼)

Proxy는 디자인 패턴이며 핵심 아이디어는 대상에 대한 액세스를 프록시 객체로 전송하는 것입니다. 이것의 장점은 대상 객체가 코드를 변경하지 않고도 프록시 객체를 통해 몇 가지 추가 기능을 추가할 수 있다는 것입니다. 이는 원본 코드를 변경하지 않고 에이전트를 통해 일부 확장 기능을 추가하는 프로그래밍 아이디어입니다.

프록시 프로세스는 그림과 같으며, 프록시 객체는 대상 객체에 액세스하여 사용자가 대상 객체에 액세스하는 목적을 달성합니다. 세 가지 역할:

ISubject: 인터페이스 개체, 이 인터페이스는 개체와 해당 프록시가 공유하는 인터페이스입니다. Java 프록시 모드 소개

TargetSubject: 대상 개체는 추상 테마 인터페이스를 구현하는 클래스입니다.

Proxy: 실제 개체를 조작할 수 있도록 대상 개체 TargetSubject에 대한 참조가 포함된 프록시 역할입니다. 프록시 객체는 대상 객체와 동일한 인터페이스를 제공하므로 언제든지 대상 객체를 대체할 수 있습니다. 동시에 프록시 개체는 대상 개체에 대한 작업을 수행할 때 다른 작업을 추가할 수 있으며 이는 실제 개체를 캡슐화하는 것과 같습니다.

일반적인 프록시 모드는 정적 프록시와 동적 프록시로 구분됩니다. Java에서 동적 프록시 구현은 JDK 동적 프록시와 cglib 프록시로 구분됩니다.

Static Proxy

앞서 언급한 것처럼 프록시 모드에는 세 가지 역할이 있습니다. 하나는 대상 인터페이스이고, 두 번째는 대상 객체이고, 세 번째는 프록시 객체입니다.

이제는 특정 코드로 구현됩니다. 먼저 대상 인터페이스는 다음과 같습니다.

 public interface IBlogService {

    void writeBlog();
}
로그인 후 복사

대상 개체는 대상 인터페이스를 구현하며 코드는 다음과 같습니다.

public class BlogService implements IBlogService {

    @Override
    public void writeBlog() {
        System.out.println("i'm writing...");
    }
}
로그인 후 복사

정적 프록시 개체, 대상 개체는 다음을 통해 얻습니다. 생성자 메소드, 대상 인터페이스의 메소드가 대상 인터페이스의 메소드에서 호출됩니다. 코드는 다음과 같습니다.

public class BlogStaticProxy implements IBlogService{
    private IBlogService blogService;

    public BlogStaticProxy(IBlogService blogService) {
        this.blogService = blogService;
    }

    @Override
    public void writeBlog() {
        System.out.println("start writing...");
        blogService.writeBlog();
        System.out.println("end writing...");
    }
}
로그인 후 복사
로그인 후 복사

정적 프록시 객체는 생성 메소드를 통해 대상 객체를 획득하고 구현합니다. 대상 인터페이스의 메소드는 대상 인터페이스의 메소드에서 호출됩니다. 코드는 다음과 같습니다.

public class BlogStaticProxy implements IBlogService{
    private IBlogService blogService;

    public BlogStaticProxy(IBlogService blogService) {
        this.blogService = blogService;
    }

    @Override
    public void writeBlog() {
        System.out.println("start writing...");
        blogService.writeBlog();
        System.out.println("end writing...");
    }
}
로그인 후 복사
로그인 후 복사

Test:

public class TestStaticProxy {

    public static void main(String[] args) {
        IBlogService target = new BlogService();
        BlogStaticProxy proxy = new BlogStaticProxy(target);
        proxy.write();
    }
}
로그인 후 복사
start writing…
i’m writing…
end writing…
로그인 후 복사

정적 프록시, 대상 객체를 수정하지 않고 프록시 객체를 사용하여 추가 작업을 수행할 수 있습니다. 확장 기능. 그러나 정적 메서드는 그다지 유연하지 않습니다. 대상 인터페이스의 코드가 수정되면 대상 개체와 프록시 개체를 모두 수정해야 합니다.

동적 프록시는 이러한 상황을 어느 정도 방지합니다. 동적 프록시는 대상 인터페이스를 구현하기 위해 프록시 객체가 필요하지 않으며, 프록시 객체는 Java 가상 머신의 메모리에 동적으로 생성됩니다.

Jdk 동적 객체

Jdk의 동적 프록시는 프록시에 의해 제어됩니다. 이 클래스는 생성되며 세 가지 매개변수를 갖습니다.

ClassLoader 로더: 클래스 로더를 사용하기 위해 현재 대상 객체를 지정합니다. 로더를 얻는 방법은 고정되어 있습니다.

Class[] 인터페이스 ,: 대상 객체에 의해 구현된 인터페이스 유형, 일반 메소드를 사용하여 유형을 확인

InvocationHandler h: 이벤트 처리, 대상 객체의 메소드를 실행할 때 이벤트 핸들러의 메소드가 트리거되고 현재 실행된 대상 개체가 매개변수로 전달됩니다

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

    }
로그인 후 복사

Jdk의 역학 프록시 코드는 다음과 같습니다.

 public class JdkBlogProxyFactory {

    private Object target;

    public JdkBlogProxyFactory(Object target) {
        this.target = target;
    }

    public Object newInstance() {
        return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(),
                (proxy, method, args) -> {
                    System.out.println("start writing");
                    Object o = method.invoke(target, args);
                    System.out.println("end writing");
                    return o;
                });
    }
}
로그인 후 복사

Test 클래스:

public class TestJdkProxy {
    public static void main(String[] args) {

        IBlogService target = new BlogService();

        System.out.println(target.getClass());

        // 给目标对象,创建代理对象
        IBlogService proxy = (IBlogService) new JdkBlogProxyFactory(target).newInstance();
        // class $Proxy0   内存中动态生成的代理对象
        System.out.println(proxy.getClass());

        // 执行方法   【代理对象】
        proxy.writeBlog();
    }
}
로그인 후 복사

콘솔은 다음과 같이 인쇄합니다.

class com.forezp.proxy.BlogService
class com.sun.proxy.$Proxy0
start writing
i&#39;m writing...
end writing
로그인 후 복사

CGLib 동적 프록시

CGLib는 매우 낮은 수준을 사용합니다. 레벨 바이트코드 기술의 원칙은 바이트코드 기술 클래스를 통해 클래스에 대한 자식을 생성하고 하위 클래스의 메서드 차단 기술을 사용하여 모든 상위 클래스 메서드 호출을 가로채고 그에 따라 교차 논리를 짜는 것입니다.

CglibBlogFactory 프록시 팩토리 클래스는 다음과 같습니다.

public class CglibBlogFactory implements MethodInterceptor {

    private Object target;

    public CglibBlogFactory(Object target) {
        this.target = target;
    }

    //给目标对象创建一个代理对象
    public Object getProxyInstance() {
        //1.工具类
        Enhancer en = new Enhancer();
        //2.设置父类
        en.setSuperclass(target.getClass());
        //3.设置回调函数
        en.setCallback(this);
        //4.创建子类(代理对象)
        return en.create();
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        System.out.println("start writing...");
        //执行目标对象的方法
        Object returnValue = method.invoke(target, objects);
        System.out.println("end writing...");
        return returnValue;
    }
}
로그인 후 복사

테스트 클래스:

public class TestCglib {

    public static void main(String[] args) {
        IBlogService target = new BlogService();
        //代理对象
        IBlogService proxy = (IBlogService) new CglibBlogFactory(target).getProxyInstance();
        //执行代理对象的方法
        proxy.writeBlog();
    }
}
로그인 후 복사

실행 프로그램, 콘솔 인쇄:

start writing...
i&#39;m writing...
end writing...
로그인 후 복사

관련 권장 사항:

java 소개 튜토리얼

위 내용은 Java 프록시 모드 소개의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:juejin.im
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿