>  기사  >  Java  >  Java의 동적 프록시 및 정적 프록시 분석 예

Java의 동적 프록시 및 정적 프록시 분석 예

WBOY
WBOY앞으로
2023-05-05 21:37:081494검색

    0. 에이전트 모드

    에이전트 모드를 배워야 하는 이유는 무엇인가요? 이것은 SpringAOP의 하위 레이어입니다. [SpringAOP 및 SpringMVC]

    프록시 모드 분류:

    • 정적 프록시

    • 동적 프록시

    1정적 프록시에서는 대상으로 삼습니다. 대상 개체 각 메서드의 향상은 수동으로 수행됩니다(코드는 나중에 자세히 설명합니다). 이는 매우 융통성이 없습니다(예를 들어 새 메서드가 인터페이스에 추가되면 대상 개체와 프록시 개체를 수정해야 합니다). 그리고 번거롭습니다(각 대상을 수정해야 함 각 클래스는 별도의 프록시 클래스를 작성합니다

    ). 실제 애플리케이션 시나리오는 거의 없으며 일상적인 개발에 정적 프록시가 사용되는 시나리오도 거의 없습니다.

    역할 분석:

    추상 역할: 일반적으로 문제를 해결하기 위해 인터페이스 또는 추상 클래스가 사용됩니다.
    • 실제 역할: 프록시되는 역할
    • 에이전트 역할: 이후 실제 역할을 프록시합니다. 실제 역할을 대리하여 우리는 일반적으로 일부 보조 작업을 수행합니다
    • 고객: 프록시 개체에 액세스하는 사람!
    • 코드 단계:

    1. 인터페이스

    public interface Rent {
        public void rent();
    }

    2. 실제 역할

    //房东
    public class Host implements Rent {
        public void rent() {
            System.out.println("房东要租房子");
        }
    }

    4. 클라이언트 액세스 에이전트 역할

    public class Proxy implements Rent{
        private Host host;
        public Proxy() {
        }
        public Proxy(Host host) {
            this.host = host;
        }
        public void rent(){
            seeHouse();
            host.rent();
            fare();
        }
        //看房
        public void seeHouse(){
            System.out.println("中介带你看房");
        }
        //收中介费
        public void fare(){
            System.out.println("中介收费");
        }
    }

    실제 캐릭터의 조작을 더욱 순수하게 만들 수 있습니다! 공무는 신경쓰지 않아도 됩니다

      공무는 대리인 역할에 맡기겠습니다! 업무분업을 실현하라!
    • 공공부문이 확대되면 중앙관리가 편리해집니다!
    • 단점:

    • 실제 역할은 JVM 관점에서 프록시 역할을 생성하며 정적 프록시는 컴파일 중에 인터페이스, 구현 클래스 및 프록시 클래스를 실제 클래스 파일로 전환합니다.

    2. 기본 프록시 모델인 AOP에 대한 이해를 심화합니다.

    3. 동적 프록시

    Java의 동적 프록시 및 정적 프록시 분석 예동적 프록시와 정적 프록시의 역할은 동일합니다

      동적 프록시의 프록시 클래스 우리가 직접 작성한 것이 아닌 동적으로 생성됩니다!
    • 동적 프록시는 두 가지 범주로 나뉩니다: 인터페이스 기반 동적 프록시, 클래스 기반 동적 프록시
    • 인터페이스 기반 ——JDK 동적 프록시

      • 클래스 기반: cglib 동적 프록시
      • java 바이트코드 구현: javasist
      • 두 가지 클래스를 이해해야 합니다. 프록시: 프록시 클래스, InvocationHandler: 호출 핸들러

      • JVM 관점에서 동적 프록시는 런타임에 클래스 바이트코드를 동적으로 생성하고 JVM.
    public class Client {
        public static void main(String[] args) {
            Host host = new Host();
            //代理,代理角色一般会有附属操作!
            Proxy proxy = new Proxy(host);
            proxy.rent();
        }
    }

    동적 프록시의 이점:

    실제 문자의 작업을 더욱 순수하게 만들 수 있습니다! 일부 공무는 처리할 필요가 없습니다

      공무는 대리인 역할에 맡기겠습니다! 구현
    • //Proxy是生成动态代理类,提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。
      //InvocationHandler-- invoke 调用处理程序并返回接口, 是由代理实例的调用处理程序实现的接口 。
    • 1.

      loader

    • : 클래스 로더, 프록시 객체를 로드하는 데 사용됩니다.

    2.인터페이스 : 프록시 클래스에 의해 구현된 일부 인터페이스 loader :类加载器,用于加载代理对象。

    2.interfaces : 被代理类实现的一些接口;

    3.h : 实现了 InvocationHandler 接口的对象;

    要实现动态代理的话,还必须需要实现InvocationHandler 来自定义处理逻辑。 当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现InvocationHandler 接口类的 invoke 方法来调用。

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

    1.proxy :动态生成的代理类

    2.method : 与代理类对象调用的方法相对应

    3.args : 当前 method 方法的参数

    动态代理的例子

    1、定义接口

    public interface InvocationHandler {
        Object invoke(Object proxy, Method method, Object[] args) throws Throwable;
    }

    2、实现租房的接口

    public interface Rent {
        public void rent();
    }

    3、定义一个JDK动态代理类

    public class Host implements Rent {
        @Override
        public void rent() {
            System.out.println("房东要租房");
        }
    }

    invoke() 方法: 当我们的动态代理对象调用原生方法的时候,最终实际上调用到的是 invoke() 方法,然后 invoke() 方法代替我们去调用了被代理对象的原生方法。

    4、获取代理对象的工厂类

    public class DebugInvocationHandler implements InvocationHandler {
        /**
         * 代理类中的真实对象
         */
        private final Object target;
        public DebugInvocationHandler(Object target){
            this.target = target;
        }
        /**
         * 当你使用代理对象调用方法的时候实际会调用到这个方法
         */
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //调用方法前
            System.out.println("before method" + method.getName());
            Object res = method.invoke(target, args);
            //调用方法后
            System.out.println("after method" + method.getName());
            return res;
        }
    }

    getProxy() :主要通过Proxy.newProxyInstance()

    3.

    h: InvocationHandler 인터페이스 개체를 구현했습니다.

    동적 프록시를 구현하려면 InvocationHandler도 구현하여 처리 논리를 사용자 정의해야 합니다. 동적 프록시 객체가 메소드를 호출하면 이 메소드에 대한 호출은 InvocationHandler 인터페이스를 구현하는 클래스의 invoke 메소드로 전달됩니다.

    public class JdkProxyFactory {
        public static Object getProxy(Object target){
            return Proxy.newProxyInstance(
                    target.getClass().getClassLoader(),
                    target.getClass().getInterfaces(),
                    new DebugInvocationHandler(target)
            );
        }
    }

    1.

    proxy: 동적으로 생성된 프록시 클래스

    2.
    method: 프록시 클래스 객체가 호출한 메소드에 해당🎜🎜🎜3.🎜args: 현재 메소드 method의 매개변수🎜

    Dynamic 프록시 예

    🎜1. 인터페이스 정의🎜
    public static void main(String[] args) {
            //Rent rent = new Host();
            //Rent rentProxy= (Rent) Proxy.newProxyInstance(rent.getClass().getClassLoader(), rent.getClass().getInterfaces(),new DebugInvocationHandler(rent));
            Rent rentProxy = (Rent)JdkProxyFactory.getProxy(new Host());
            rentProxy.rent();
        }
    🎜2. 임대 인터페이스 구현🎜rrreee🎜3. JDK 동적 프록시 클래스 정의🎜rrreee🎜invoke() 방법: 동적 프록시 개체가 기본 메서드를 호출할 때 실제로 호출되는 것은 invoke() 메서드이고, 그런 다음 invoke() 메서드는 프록시 개체의 기본 메서드를 호출합니다. 우리를 대신해. 🎜🎜4. 프록시 객체의 팩토리 클래스 얻기🎜rrreee🎜getProxy(): 주로 Proxy.newProxyInstance() 메서드를 통해 특정 클래스의 프록시 객체를 얻습니다. 🎜🎜5. 🎜rrreee🎜🎜🎜🎜🎜🎜before methodrent🎜집주인이 집을 임대하고 싶어🎜after methodrent🎜🎜를 사용하여 실제로 위 에이전트를 실행한 결과

    위 내용은 Java의 동적 프록시 및 정적 프록시 분석 예의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제