Java 프록시란 무엇인가요?
프록시란 무엇인가요? , 실제로 이해하기 쉽습니다. 즉, 대상에 직접 액세스하지 않고 다음과 같이 중간 계층을 통해 액세스합니다.
# 🎜🎜#Java 정적 프록시
예를 들어 바나나, 사과 등과 같은 과일을 Java 코드로 작성하면 다음과 같을 것입니다. (추천 튜토리얼: #🎜 🎜#java tutorial)//Fruit.java/**
* 水果的接口
*/public interface Fruit { /**
* 获取水果的名字
*/
public String getName();
}//Apple.javapublic class Apple implements Fruit { @Override
public String getName() { return "苹果";
}
}//Banana.javapublic class Banana implements Fruit { @Override
public String getName() { return "香蕉";
}
}
//PeelFruitProxy.java/** * 代理,让每个水果去皮 */public class PeelFruitProxy implements Fruit { private Fruit mFruit; public PeelFruit(Fruit fruit) { this.mFruit = fruit; } @Override public String getName() { System.out.println("proxt:" + proxy.getClass().getName()); return "去皮的" + mFruit.getName(); } }
//Main.javapublic class Main { public static void main(String[] args) { Apple apple=new Apple();//原始的苹果 Banana banana=new Banana();//原始的香蕉 PeelFruitProxy peelApple=new PeelFruitProxy(apple);//代理,添加去皮功能 PeelFruitProxy peelBanana=new PeelFruitProxy(banana);//代理,添加去皮功能 System.out.println(peelApple.getName()); System.out.println(peelBanana.getName()); } }
위는 Java의 정적 프록시는 간단히 말하면 원래 대상 객체를 하나의 레이어로 래핑하고 새로운 것을 추가한 다음 대상 자체를 호출하는 것을 의미합니다. 그런데 그냥 이런 정적 프록시라면 인터페이스에 프록시가 필요한데, 구현하기가 많이 번거롭나요?
Java의 동적 프록시Java에는 Proxy라는 클래스가 있는데 직접 리플렉션, 프록시 가로채기를 사용할 수 있습니다. 먼저 이 클래스를 간단히 소개하겠습니다. 실제로 가장 일반적으로 사용되는 정적 메서드는 Proxt.newProxyInstance()입니다. 이는 다음과 같습니다.
public static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
먼저 InvocationHandler를 구현하고 호출 메서드를 구현해야 합니다. 대상 개체를 호출하면 호출 메서드가 먼저 호출되고 구현자는 이 메서드에서 피호출자 메서드를 적극적으로 호출해야 합니다.
//FruitInvocationHandler.java/** * 调用方法拦截器 */public class FruitInvocationHandler implements InvocationHandler { private Fruit mFruit; public FruitInvocationHandler(Fruit fruit) { this.mFruit = fruit; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { String result = (String) method.invoke(mFruit, args);//需要在这个方法里面,主动调用被代理的对象。 return "去皮的" + result; } }
실행:
//Main.Javapublic class Main { public static void main(String[] args) { Apple apple = new Apple(); Fruit proxyApple = (Fruit) Proxy.newProxyInstance(Fruit.class.getClassLoader(), new Class[]{Fruit.class}, new FruitInvocationHandler(apple)); System.out.println(proxyApple.getClass().getName()); System.out.println(proxyApple.getName()); Banana banana = new Banana(); Fruit proxyBanana = (Fruit) Proxy.newProxyInstance(Fruit.class.getClassLoader(), new Class[]{Fruit.class}, new FruitInvocationHandler(banana)); System.out.println(proxyApple.getClass().getName()); System.out.println(proxyBanana.getName()); } }
이 방법은 위에서 언급한 대로 PeelFruitProxy를 생성하는 것입니다(물론 우리가 본 것은 그의 이름은 com.sun.proxy.$Proxy0)이며 매번 작성할 필요가 없도록 동적으로 생성됩니다. 이는 런타임에 모든 클래스를 프록시할 수 있기 때문에 동적 프록시라고 불리는 이유이기도 합니다. 많은 프로그램에서 AOP가 이런 방식으로 구현되지만 몇 가지 특징을 발견했습니다. newProxyInstance()의 두 번째 매개변수는 인터페이스 목록입니다.
동적으로 생성된 프록시 클래스도 인터페이스를 구현해야 하기 때문에 쉽게 하향 변환되어 메소드를 사용할 수 있습니다. 그렇지 않으면 생성된 클래스의 클래스 이름이 com.sun.proxy입니다. $Proxy0 이 방법으로 메모리에 있으면 생성된 메서드를 호출할 수 없습니다. ** 따라서 이 동적 프록시 메서드에는 치명적인 단점이 있습니다. 즉, 프록시된 클래스가 인터페이스를 구현해야 한다는 것입니다. **
CGLib 프록시cglib is a powerful, high performance and quality Code Generation Library, It is used to extend JAVA classes and implements interfaces at runtime.
사용 방법을 간단히 소개하겠습니다. 우선 이 CGLib은 타사 라이브러리이므로 이에 의존해야 합니다.
compile 'cglib:cglib :3.2.8'#🎜 🎜#
최신 버전은 여기(새 버전)에서 볼 수 있습니다. [https://github.com/cglib/cglib/releases] 그럼 한번 시도해 보세요. 위의 프록시를 구현합니다.# 🎜🎜#
//FruitMethodInterceptor.java/** * CGLib代理的方法拦截器 */public class FruitMethodInterceptor implements MethodInterceptor{ @Override public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable { String result = (String) proxy.invokeSuper(obj, args);//主要,这里调用的是父类,也就是说, 生成的类和原始类是继承关系 return "去皮的"+result; } }//Main.javapublic class Main { public static void main(String[] args) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(Apple.class); enhancer.setCallback(new FruitMethodInterceptor()); Apple apple = (Apple) enhancer.create(); System.out.println(apple.getClass().getName()); System.out.println(apple.getName()); } }
첫 번째 유형의 프록시는 여기서 언급되지 않으며 단일 인터페이스 프록시에만 적합하며 컴파일 타임에 결정됩니다. . 두 번째와 세 번째 유형의 프록시는 모두 동적 프록시이지만 차이점이 있습니다.
1) JDK의 동적 프록시는 인터페이스 프록시만 구현할 수 있으며, 패키지된 프록시 객체(클래스의 인스턴스) 즉, 프록시 프로세스 중에 프록시 객체와 대상 객체라는 두 개의 객체가 프록시 객체에 패키지됩니다.
2) CGLib의 프록시는 대상 개체를 상속하고 새 클래스를 생성한 후 프록시를 구현합니다. 이렇게 하면 메모리에 프록시 개체가 있고 대상 개체가 없습니다. 상속 방식
런타임에 프록시 클래스를 생성하는데, 이는 컴파일 타임에 클래스를 생성하는 javapoet와 다릅니다.
위 내용은 자바 프록시 란 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!