이 글은 주로 자바 디자인 패턴의 프록시 모드 노트를 자세하게 소개하고 있으며, 관심 있는 친구들은 참고할 수 있습니다.
프록시(Proxy) 모드:
프록시 모드는 객체 기반 구조 패턴입니다. 프록시 패턴은 객체에 대한 프록시 객체를 제공하고 프록시 객체는 원본 객체에 대한 참조를 제어합니다.
핵심 기능:
프록시를 통해 개체에 대한 액세스를 제어합니다.
특정(특정 유형의) 객체에 접근하는 방법을 세부적으로 제어할 수 있으며, 이 메서드를 호출하기 전 전처리를 하고, 이 메서드를 호출한 후에 후처리를 할 수 있습니다. 즉, AOP의 마이크로 구현입니다.
AOP(Aspect Oriented 프로그래밍)의 핵심 구현 메커니즘입니다.
인생의 시나리오:
소위 기관은 개인이나 기관이 다른 사람이나 기관을 대신하여 조치를 취하는 경우입니다. 어떤 경우에는 클라이언트가 개체를 직접 참조하는 것을 원하지 않거나 참조할 수 없으며 프록시 개체가 클라이언트와 대상 개체 사이의 중개자 역할을 할 수 있습니다.
예를 들어, 고객이 노래할 스타를 찾고 싶다면 먼저 에이전트를 찾아야 하며, 그러면 에이전트가 스타가 노래할 수 있도록 주선해 줄 것입니다.
에이전트는 공연 전 일부 전처리(인터뷰, 계약서 작성, 사인회, 선금 수령, 항공권 및 차량 준비 등)를 처리해야 하고 공연 후 일부 후처리(결제 마감 등)를 처리해야 합니다. 콘서트가 열립니다. 이때 특정 스타(실제 캐릭터)는 노래만 신경 쓰면 되고, 그 외의 모든 사항은 매니저(에이전트)에게 맡겨진다.
핵심 역할:
여기에 그림 설명 쓰기
추상 개체 역할: 프록시 개체와 실제 개체 사이의 공통 인터페이스를 선언하고 프록시 개체와 실제 개체의 공개 외부 메서드를 정의합니다. 이를 통해 실제 객체를 사용할 수 있는 모든 곳에서 프록시 객체를 사용할 수 있습니다.
실제 객체 역할: 프록시 객체가 나타내는 실제 객체를 정의합니다. 추상 객체를 구현하고 프록시 객체 호출을 위해 실제 객체로 구현해야 하는 비즈니스 로직을 정의합니다. 실제 비즈니스 로직에 집중하세요.
프록시 개체 역할: 추상 개체를 구현하고 실제 개체에 대한 프록시입니다. 실제 개체의 비즈니스 논리 메서드를 통해 추상 메서드를 구현하고 자체 작업을 연결합니다. 프록시 개체에 통합 프로세스 제어를 적용합니다.
프록시 객체는 내부적으로 실제 객체에 대한 참조를 포함하므로 언제든지 실제 객체를 조작할 수 있습니다. 프록시 객체는 실제 객체와 동일한 인터페이스를 제공하므로 언제든지 실제 객체를 교체할 수 있습니다. . 프록시 개체는 일반적으로 단순히 호출을 실제 개체에 전달하는 것이 아니라 클라이언트 호출이 실제 개체에 전달되기 전후에 작업을 수행합니다.
응용 시나리오:
보안 프록시: 실제 문자에 대한 직접 액세스를 차단합니다.
원격 프록시: 프록시 클래스를 통해 원격 메서드 호출을 처리합니다.
지연 로딩: 가벼운 프록시 개체를 먼저 로드한 다음 필요할 때 실제 개체를 로드합니다. (이미지 지연 로딩)
카테고리:
정적 프록시: (정적으로 정의된 프록시 클래스)
위 예제의 코드:
1 프록시 객체와 실제 객체 간의 공통 인터페이스를 선언하고 정의합니다. 프록시 객체와 실제 객체의 공개 외부 메소드.
public interface Star { /** * 面谈 */ void confer(); /** * 签合同 */ void signContract(); /** * 订票 */ void bookTicket(); /** * 唱歌 */ void sing(); /** * 收钱 */ void collectMoney(); }
2. 실제 객체의 클래스를 정의하고 추상 인터페이스에서 제공하는 메서드를 구현합니다.
public class RealStar implements Star { @Override public void bookTicket() { System.out.println("RealStar.bookTicket()"); } @Override public void collectMoney() { System.out.println("RealStar.collectMoney()"); } @Override public void confer() { System.out.println("RealStar.confer()"); } @Override public void signContract() { System.out.println("RealStar.signContract()"); } @Override public void sing() { System.out.println("RealStar.sing()"); } }
3. 프록시 객체의 클래스를 정의하고, 추상 인터페이스에서 제공하는 메서드를 구현하고, 실제 객체에 대한 참조를 보유합니다.
public class ProxyStar implements Star{ private Star star; public ProxyStar(Star star) { super(); this.star = star; } @Override public void bookTicket() { System.out.println("ProxyStar.bookTicket()"); } @Override public void collectMoney() { System.out.println("ProxyStar.collectMoney()"); } @Override public void confer() { System.out.println("ProxyStar.confer()"); } @Override public void signContract() { System.out.println("ProxyStar.signContract()"); } @Override public void sing() { star.sing(); } }
4. 테스트 클래스
public class Client { public static void main(String[] args) { //定义真实对象角色 Star realStar = new RealStar(); //定义代理对象角色,内部含有真实对象的引用 Star proxyStar = new ProxyStar(realStar); proxyStar.confer(); proxyStar.signContract(); proxyStar.bookTicket(); proxyStar.sing(); proxyStar.collectMoney(); } }
실행 결과는 다음과 같습니다.
ProxyStar.confer() ProxyStar.signContract() ProxyStar.bookTicket() RealStar.sing() ProxyStar.collectMoney()
위의 예에서 프록시 개체가 클라이언트의 호출을 실제 개체에 위임하는 것을 볼 수 있습니다. 그런 다음 대상 개체의 메서드를 호출합니다. 특정 작업은 전후에 수행될 수 있습니다.
동적 프록시: (동적으로 생성된 프록시 클래스):
정적 프록시에 비해 동적 프록시의 장점:
추상 역할(인터페이스)에 선언된 모든 메서드는 호출 서버 처리의 중앙 집중식 메서드로 전송됩니다. 수많은 메서드를 보다 유연하고 균일하게 처리할 수 있습니다.
JDK 고유의 동적 프록시
java.lang.reflect.Proxy
프록시 클래스 및 객체를 동적으로 생성
java.lang.reflect.InvocationHandler(프로세서 인터페이스)
invoke 메소드를 통해 호출 가능 실제 문자에 대한 프록시 액세스 실현
프록시를 통해 프록시 클래스 개체를 생성할 때마다 해당 프로세서 개체를 지정해야 합니다
테스트 코드는 다음과 같습니다.
1. 프록시 개체와 실제 개체 간의 공통 인터페이스를 선언합니다. 객체를 만들고 프록시 객체와 실제 객체의 공개 외부 메소드를 정의합니다.
public interface Star { /** * 面谈 */ void confer(); /** * 签合同 */ void signContract(); /** * 订票 */ void bookTicket(); /** * 唱歌 */ void sing(); /** * 收钱 */ void collectMoney(); }
2. 실제 객체의 클래스를 정의하고 추상 인터페이스에서 제공하는 메서드를 구현합니다.
public class RealStar implements Star { @Override public void bookTicket() { System.out.println("RealStar.bookTicket()"); } @Override public void collectMoney() { System.out.println("RealStar.collectMoney()"); } @Override public void confer() { System.out.println("RealStar.confer()"); } @Override public void signContract() { System.out.println("RealStar.signContract()"); } @Override public void sing() { System.out.println("RealStar.sing()"); } }
3. InvocationHandler 프로세서 인터페이스를 구현하기 위해 StarHandler 클래스를 정의합니다. Invocation 메소드를 통해 실제 역할에 대한 프록시 액세스를 얻을 수 있으며 Invoke 메소드에서 많은 작업의 통합 처리를 수행할 수도 있습니다.
import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; public class StarHandler implements InvocationHandler{ private Star realStar; public StarHandler(Star realStar) { super(); this.realStar = realStar; } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //返回值 Object object = null; System.out.println("真正的方法执行前!"); System.out.println("面谈,签合同,预付款,订机票"); if(method.getName().equals("sing")){ object = method.invoke(realStar, args); } System.out.println("真正的方法执行后!"); System.out.println("收尾款"); return object; } }
4.客户端测试类
import java.lang.reflect.Proxy; public class Client { public static void main(String[] args) { Star realStar = new RealStar(); StarHandler handler = new StarHandler(realStar); //通过Proxy生成代理类对象并指定对应的处理器对象 Star proxyStar = (Star)Proxy.newProxyInstance(ClassLoader.getSystemClassLoader(), new Class[]{Star.class}, handler); proxyStar.sing(); }
运行结果如下:
真正的方法执行前!
面谈,签合同,预付款,订机票
RealStar.sing()
真正的方法执行后!
收尾款
开发框架中的应用场景
代理模式在开发框架中的应用场景是非常多的,实际上随便选择一个开发框架都有用到代理模式。例如:
mybatis中实现拦截器插件
AspectJ的实现
spring中AOP的实现
위 내용은 Java 디자인 패턴 중 에이전트 패턴에 대한 참고 사항의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!