자바 의 프 록 시 동적 에이전트
자바 동적 대 리 를 말 하기 전에 Jvm 로 딩 대상 의 과정 을 말 해 야 합 니 다.이것 은 동적 대 리 를 이해 하 는 기본 적 인 원리 입 니 다.
자바 류 는 소스 코드 프로그램
.java
형식 파일 로 컴 파일 러 를 통 해 컴 파일 된 후에 바이트 코드.class
형식 파일 로 바 뀌 었 습 니 다.클래스 로 더 는 바이트 코드 를 읽 고 자바.lang.Class 대상 으로 바 뀌 었 습 니 다.메타 데이터 공간 에 있 는 데이터 구 조 를 설명 하고 클래스 가 예화 되 었 을 때 더미 에 예화 된 대상 정 보 를 저장 합 니 다.또한 대상 형식 데이터 의 지침 을 통 해 클래스 를 찾 습 니 다.프로 세 스 설명:원본->.자바 파일->.class 파일->Class 대상->인 스 턴 스 대상
그래서 New 창설 대상 을 통 해 그 배후 에 많은 세부 사항 을 독단 하고 상술 한 과정 을 이해 한 후에 자주 사용 하 는 디자인 모델,즉 대리 모델 을 이해한다.
2.대리 모드
2.1 기본 설명
프 록 시 모드 는 특정한(목표)대상 에 게 프 록 시 대상 을 제공 하고 프 록 시 대상 이 대상 의 인용 을 가지 고 있 습 니 다.대리 란 한 대상 이 다른 대상 을 대표 하여 해당 하 는 동작 절 차 를 수행 하 는 것 이다.한편,대리 대상 은 클 라 이언 트 와 목표 대상 사이 에서 중개 역할 을 할 수 있다.
대리 모델 은 실제 생활 에서 장면 이 매우 많다.예 를 들 어 중개,변호사,대리 구 매 등 업 종 은 모두 간단 한 대리 논리 로 이 모델 에서 두 가지 관건 적 인 역할 이 존재 한다.
대상 역할:즉 대리 대상 이 대표 하 는 대상 입 니 다.
대리 대상 역할:내부 에 목표 대상 의 인용 이 포함 되 어 있 고 목표 대상 을 조작 할 수 있 습 니 다.AOP 프로 그래 밍 은 바로 이 사상 에 기초 한 것 이다.
2.2 정적 모드
상기 정적 에이전트 의 개념 을 바탕 으로 코드 로 설명 하여 실현 합 니 다.기본 논 리 는 다음 과 같 습 니 다.
public class Proxy01 {
public static void main(String[] args) {
TargetObj targetObj = new TargetObj() ;
ProxyObj proxyObj = new ProxyObj(targetObj) ;
proxyObj.invoke();
}
}
class TargetObj {
public void execute (){
System.out.println(" ...");
}
}
class ProxyObj {
private TargetObj targetObj ;
/**
*
*/
public ProxyObj (TargetObj targetObj){
this.targetObj = targetObj ;
}
/**
*
*/
public void invoke (){
before () ;
targetObj.execute();
after () ;
}
/**
*
*/
public void before (){
System.out.println(" ...");
}
public void after (){
System.out.println(" ...");
}
}
정적 프 록 시 는 프 록 시 대상,즉 하나의 프 록 시 대상.java
파일 을 JVM 에 불 러 오 는 과정 을 명확 하 게 정의 했다.분명 한 문 제 는 실제 개발 과정 에서 모든 목표 대상 에 게 하나의 프 록 시 클래스 를 정의 할 수 없고 한 대리 대상 이 여러 목표 대상 을 대리 하 게 할 수 없다.이 두 가지 방식 의 유지 비용 이 매우 높다.프 록 시 모델 의 본질은 목표 대상 의 방법 전후 에 증강 작업 을 하 는 것 이지 만 목표 류 를 수정 하고 싶 지 않다.앞의 반사 체 제 를 통 해 알 수 있 듯 이 운행 할 때 대상 의 구조 정 보 를 얻 을 수 있 고 Class 정 보 를 바탕 으로 프 록 시 대상 을 동적 으로 만 드 는 것 이 바로 동적 프 록 시 체제 이다.
참고 로 기술 의 밑바닥 실현 논리 가 이해 하기 어 려 운 것 은 잘 알려 져 있 지만 기초 지식 점 은 복잡 하지 않다.예 를 들 어 대리 모델 의 기본 원리 이지 만 실제 복잡 한 응용(AOP 모델)과 결합 하면 반사 와 동태 대 리 를 바탕 으로 하 는 방식 으로 이 루어 진 것 이 라 고 생생 하 게 이해 하기 어렵다.
동적 에이전트
4.1 장면 묘사
한 장면 을 바탕 으로 동태 대리 와 정태 대리 의 차 이 를 묘사 합 니 다.즉,최근 몇 년 동안 핫 한 개념,해외 대리 구 매:
대리 구 매가 막 일어 난 초기 에는 해외 출장 을 자주 가 는 사람들 이 대리 구 매 수 요 를 받는다.즉,대리인 이 고정한다.그 후에 해외 대리 구 매 플랫폼,해 타 오 등 일련의 제품 이 유행 했다.즉,사용자 대리 구 매 수요(목표 대상)는 대리 구 매 플랫폼 에서 이 루어 졌 다.그러나 구체 적 으로 누가 이 를 조작 하 는 지 는 실시 간 분 배 를 보면 이 장면 은 동태 대리 의 원리 와 유사 하 다.
4.2 기초 API 사례
먼저 두 가지 핵심 유형 을 살 펴 보고 여기 서 개념 을 약술 하고 기본 과정 을 보고 다시 자세하게 이야기 합 니 다.
프 록 시-프 록 시 대상 생 성,핵심 매개 변수:
interface IUser {
Integer update (String name) ;
}
class UserService implements IUser {
@Override
public Integer update(String name) {
Integer userId = 99 ;
System.out.println("UserId="+userId+";updateName="+name);
return userId ;
}
}
에이전트 개체 실행 메커니즘
class UserHandler implements InvocationHandler {
private Object target ;
public UserHandler (Object 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;
}
}
구체 적 인 조합 방식
public class Proxy02 {
public static void main(String[] args) {
/*
* $Proxy0 class
*/
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
/*
*
*/
IUser userService = new UserService();
ClassLoader classLoader = userService.getClass().getClassLoader();
Class<?>[] interfaces = UserService.class.getInterfaces() ;
/*
*
*/
InvocationHandler userHandler = new UserHandler(userService);
/*
*
* proxyClassName=com.java.proxy.$Proxy0
*/
String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();
System.out.println("proxyClassName="+proxyClassName);
/*
*
*/
IUser proxyUser1 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
IUser proxyUser2 = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
proxyUser1.update("cicada") ;
proxyUser2.update("smile") ;
}
}
여기 서 프 록 시 클래스 의 구조 정 보 를 생 성 하려 는 이 유 는 JVM 로 딩 과정 에서 관련 내용 을 볼 수 없 기 때문에 관건 적 인 정 보 는 다시 독단 되 었 습 니 다.javap -v Proxy02.class
프 록 시 클래스 이름 보기
/*
* proxyClassName=com.java.proxy.$Proxy0
*/
String proxyClassName = Proxy.newProxyInstance(classLoader,interfaces,userHandler).getClass().getName();
System.out.println("proxyClassName="+proxyClassName);
무의식 출력 에이전트 의 대상 이름 입 니 다.여 기 는 JVM 체제 에 대응 하여 Class 대상 이름 을 찾 은 다음 에 구 조 를 분석 하면 동적 에이전트 의 구체 적 인 집행 원 리 를 알 수 있 습 니 다.프 록 시 클래스.class 파일 생 성
System.getProperties().put("sun.misc.ProxyGenerator.saveGeneratedFiles", "true");
위의 JVM 로 딩 대상 체 제 를 통 해 알 수 있 듯 이 프 록 시 클래스 를 설명 하 는 Class 대상 은 반드시 존재 합 니 다.실행 할 때 명시 적.class
파일 이 생 성 되 지 않 았 을 뿐 프 록 시 클래스.class
문법 을 통 해 프로젝트 디 렉 터 리/com/java/proxy
경로 에서 파일 을 만 듭 니 다.참고 로 프로그래머 로 서 복잡 함 은 항상 우리 와 둘러싸 여 있 습 니 다.간단하게 말씀 해 주 시 겠 습 니까?
4.3 대리 류 구조
계승 과 실현
class $Proxy0 extends Proxy implements IUser {}
대리 류 의 기능 을 생각해 보면 Proxy 를 계승 하고 IUser 인 터 페 이 스 를 실현 해 야 한 다 는 것 을 알 수 있다.그리고 호출 체 제 를 가 진 구체 적 인 실현 류 를 가지 고 업무 강화 에 사용 해 야 한다.구조 방법
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
구조 적 방법 을 통 해 UserHandler 의 구체 적 인 집행 메커니즘 대상 을 가지 고 있다.인터페이스 구현
final class $Proxy0 extends Proxy implements IUser {
private static Method m3;
public final Integer update(String var1) throws {
try {
return (Integer)super.h.invoke(this, m3, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
}
목표 류 의 기본 수요update()
방법 은 대리 류 를 통 해 인수 하고 UserHandler 를 바탕 으로 구체 적 인 증강 업무 처 리 를 실현 한다.기초 방법
final class $Proxy0 extends Proxy implements IUser {
private static Method m0;
private static Method m1;
private static Method m2;
public $Proxy0(InvocationHandler var1) throws {
super(var1);
}
static {
try {
m1 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));
m2 = Class.forName("java.lang.Object").getMethod("toString");
m3 = Class.forName("com.java.proxy.IUser").getMethod("update", Class.forName("java.lang.String"));
m0 = Class.forName("java.lang.Object").getMethod("hashCode");
} catch (NoSuchMethodException var2) {
throw new NoSuchMethodError(var2.getMessage());
} catch (ClassNotFoundException var3) {
throw new NoClassDefFoundError(var3.getMessage());
}
}
public final boolean equals(Object var1) throws {
try {
return (Boolean)super.h.invoke(this, m1, new Object[]{var1});
} catch (RuntimeException | Error var3) {
throw var3;
} catch (Throwable var4) {
throw new UndeclaredThrowableException(var4);
}
}
public final String toString() throws {
try {
return (String)super.h.invoke(this, m2, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
public final int hashCode() throws {
try {
return (Integer)super.h.invoke(this, m0, (Object[])null);
} catch (RuntimeException | Error var2) {
throw var2;
} catch (Throwable var3) {
throw new UndeclaredThrowableException(var3);
}
}
}
Object 클래스 를 바탕 으로 자바 에서 자주 사용 되 는 방법 인 equals()판단,toString()방법,hashCode()값 을 정의 합 니 다.이것 은 Map 소스 코드 를 분석 할 때 왜 이 몇 가지 방법 이 함께 나타 나 는 지 말 한 적 이 있 습 니 다.4.4,JDK 소스 코드
위 는 사례 수행 의 과정 과 원리 이 고 또 하나의 관건 적 인 점 은 JDK 소스 코드 의 논리 이다.
IUser proxyUser = (IUser) Proxy.newProxyInstance(classLoader,interfaces,userHandler);
Proxy 가 제공 하 는 정적 방법newProxyInstance()
은 각 매개 변수의 입력 을 통 해 새로운 프 록 시 Class 대상,즉$Proxy 0 류 의 구조 정 보 를 구축 합 니 다.여기 서 다음 세 가지 핵심 매개 변 수 를 다시 살 펴 보 겠 습 니 다.5.소스 코드 주소
GitHub/주소
https://github.com/cicadasmile/java-base-parent
GitEE/주소
https://gitee.com/cicadasmile/java-base-parent
이상 은 자바 의 프 록 시 동적 프 록 시 메커니즘 에 대한 상세 한 내용 입 니 다.자바 프 록 시 동적 프 록 시 메커니즘 에 관 한 자 료 는 다른 관련 글 을 주목 하 십시오!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.