Java 반사 및 동적 에이전트
8851 단어 java 반사
반사
반사 메커니즘은 자바 언어가 제공하는 기초 기능으로 프로그램이 실행할 때 자성(introspect, 공식 용어)을 할 수 있는 능력을 부여한다.반사를 통해 우리는 클래스나 대상을 직접 조작할 수 있다. 예를 들어 특정한 대상의 클래스 정의를 얻고, 클래스 성명의 속성과 방법을 얻고, 호출 방법이나 구조 대상을 사용하며, 심지어 실행할 때 클래스 정의를 수정할 수 있다.
1. 클래스 획득(Class) 대상
클래스 객체를 가져오는 방법은 다음과 같습니다.
2. 클래스의 상용 방법
3. 유형 방법 호출
클래스의 방법을 반사하려면 관건적인 방법인'invoke()'를 통해 이루어져야 하며 방법 호출도 세 가지로 나뉜다.
//
interface People {
int parentAge = 18;
public void sayHi(String name);
}
class PeopleImpl implements People {
private String privSex = " ";
public String race = " ";
@Override
public void sayHi(String name) {
System.out.println("hello," + name);
}
private void prvSayHi() {
System.out.println("prvSayHi~");
}
public static void getSex() {
System.out.println("18 ");
}
}
3.1 정적 메서드 호출
// ( )
public static void main(String[] args) {
Class myClass = Class.forName("example.PeopleImpl");
// (static)
Method getSex = myClass.getMethod("getSex");
getSex.invoke(myClass);
}
정적 방법의 호출은 비교적 간단하다. getMethod(xx)를 사용하여 대응하는 방법을 얻고 invoke(xx)를 직접 사용하면 된다.3.2 일반 메서드 호출
일반적인 비정상적인 방법이 호출되려면 먼저 클래스 예시를 가져와야 합니다. 'newInstance ()' 방법으로 가져오면 핵심 코드는 다음과 같습니다.
Class myClass = Class.forName("example.PeopleImpl");
Object object = myClass.newInstance();
Method method = myClass.getMethod("sayHi",String.class);
method.invoke(object," ");
getMethod 획득 방법, 전달할 매개 변수의 종류를 설명할 수 있습니다.3.3 사유 방법을 사용한다
개인 메서드를 호출하려면 "getDeclaredMethod(xx)"를 사용하여 이 클래스의 모든 메서드를 가져와야 합니다. 코드는 다음과 같습니다.
Class myClass = Class.forName("example.PeopleImpl");
Object object = myClass.newInstance();
Method privSayHi = myClass.getDeclaredMethod("privSayHi");
privSayHi.setAccessible(true); //
privSayHi.invoke(object);
'getDeclaredMethod(xx)'를 제외하고 개인 방법을 호출하는 관건은 setAccessible(true) 속성을 설정하고 접근 제한을 수정하는 것이다. 이렇게 설정하면 호출할 수 있다.4. 총결산
1. 반사에서 핵심적인 방법은 newInstance()에서 클래스 실례를 가져오고 getMethod(..)획득 방법, invoke(..) 사용setAccessible을 통해 개인 변수/메소드의 액세스 제한을 수정하는 메소드 호출
2. 속성/방법을 얻을 때'Declared'가 있는지 없는지의 차이점은 Declared가 수식한 방법이나 속성이 있으면 본 클래스의 모든 방법이나 속성(private에서public까지)을 얻을 수 있으나 부류에 대한 정보를 얻을 수 없다는 것이다.Declared 수식 방법이나 속성이 아닌 경우,public 수식 방법이나 속성만 얻을 수 있고, getMethod (...) 와 같은 부모 클래스의 정보를 얻을 수 있습니다.getDeclaredMethod(...)
2. 동적 에이전트
동적 에이전트는 실행할 때 동적 구축 에이전트, 동적 처리 에이전트 방법이 호출되는 메커니즘으로 많은 장면이 유사한 메커니즘을 이용하여 이루어진다. 예를 들어 RPC 호출을 포장하고 절단면을 위한 프로그래밍(AOP)을 한다.
동적 에이전트를 실현하는 방식이 매우 많다. 예를 들어 JDK 자체가 제공하는 동적 에이전트는 위에서 언급한 반사 메커니즘을 주로 이용했다.전설에서 더 높은 성능을 가진 바이트 코드 조작 메커니즘을 이용하여 ASM, cglib(ASM 기반) 등과 같은 다른 실현 방식도 있다.
동적 에이전트가 해결한 문제?
우선, 그것은 대리 메커니즘이다.디자인 모델 중의 에이전트 모델을 잘 알면 에이전트는 호출 목표에 대한 포장으로 볼 수 있다. 그러면 우리가 목표 코드에 대한 호출은 직접적으로 발생하는 것이 아니라 에이전트를 통해 이루어진다.에이전트를 통해 호출자와 실현자 간의 결합을 해소할 수 있다.예를 들어 RPC 호출을 하면 에이전트를 통해 더욱 우호적인 인터페이스를 제공할 수 있다.에이전트를 통해 전체적인 차단기를 만들 수도 있다.
1. JDK Proxy 동적 에이전트
JDK Proxy는 InvocationHandler 인터페이스를 구현하는 것으로 코드는 다음과 같습니다.
interface Animal {
void eat();
}
class Dog implements Animal {
@Override
public void eat() {
System.out.println("The dog is eating");
}
}
class Cat implements Animal {
@Override
public void eat() {
System.out.println("The cat is eating");
}
}
// JDK
class AnimalProxy implements InvocationHandler {
private Object target; //
public Object getInstance(Object target) {
this.target = target;
//
return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println(" ");
Object result = method.invoke(target, args); //
System.out.println(" ");
return result;
}
}
public static void main(String[] args) {
// JDK
AnimalProxy proxy = new AnimalProxy();
Animal dogProxy = (Animal) proxy.getInstance(new Dog());
dogProxy.eat();
}
위 코드와 같이 우리는 동적 에이전트를 통해 모든 요청 전과 후에 간단한 정보를 출력할 수 있습니다.주의: JDK Proxy는 인터페이스의 클래스만 프록시할 수 있습니다. (extends 계승 클래스라도 프록시할 수 없습니다.)
JDK Proxy는 왜 인터페이스의 클래스만 프록시할 수 있습니까?
이 질문은 동적 프록시 구현 방법인 newProxyInstance 소스에서 시작합니다.
@CallerSensitive
public static Object newProxyInstance(ClassLoader loader,
Class>[] interfaces,
InvocationHandler h)
throws IllegalArgumentException
{
//
다음 두 가지 소스 매개변수 설명을 참조하십시오.* @param loader the class loader to define the proxy class
* @param interfaces the list of interfaces for the proxy class to implement
Exception in thread “main” java.lang.ClassCastException: com.sun.proxy.$Proxy0 cannot be cast to xxx
2, Cglib 동적 에이전트
JDK 동적 에이전트 메커니즘은 인터페이스의 클래스만 에이전트할 수 있고 Cglib는 클래스를 대상으로 에이전트를 실현한다. 그의 원리는 지정된 목표 클래스에 하위 클래스를 생성하고 그 중에서 덮어쓰는 방법으로 강화를 실현하는 것이다. 그러나 계승을 사용하기 때문에final 수식의 클래스에 대한 에이전트를 할 수 없다.
Cglib은 Maven을 통해 버전 참조를 직접 수행할 수 있습니다. Maven 버전 주소:https://mvnrepository.com/artifact/cglib/cglib
본 논문은 최신 버전 3.2.9의 Cglib를 사용했습니다.pom.xml에서 다음 참조를 추가합니다.
cglib
cglib
3.2.9
Cglib 코드는 다음과 같이 구현됩니다.class Panda {
public void eat() {
System.out.println("The panda is eating");
}
}
class CglibProxy implements MethodInterceptor {
private Object target; //
public Object getInstance(Object target) {
this.target = target;
Enhancer enhancer = new Enhancer();
//
enhancer.setSuperclass(this.target.getClass());
//
enhancer.setCallback(this);
//
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println(" ");
Object result = methodProxy.invokeSuper(o, objects); //
System.out.println(" ");
return result;
}
}
public static void main(String[] args) {
// CGLIB
CglibProxy proxy = new CglibProxy();
Panda panda = (Panda)proxy.getInstance(new Panda());
panda.eat();
}
cglib의 호출은 MethodInterceptor 인터페이스를 실현하는intercept 방법을 통해 invokeSuper를 호출하여 동적 에이전트를 할 수 있으며 일반 클래스에 직접 동적 에이전트를 할 수 있다.3. JDK Proxy VS Cglib
JDK Proxy의 장점:
이 문서의 모든 예제 코드:https://github.com/vipstone/java-core-example.git
저는 위챗 공식계정이 하나 있는데 자바 기술과 관련된 건제품들을 자주 공유합니다.만약 당신이 나의 공유를 좋아한다면 위챗으로'java 단장'또는'javatuanzhang'팔로우를 검색할 수 있습니다.
4. 참고 문서
Java Core Technology 36 강의:http://t.cn/EwUJvWA
Java 반사 및 동적 프록시:https://www.cnblogs.com/hanganglin/p/4485999.html
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Java 반사 및 동적 에이전트예를 들어 특정한 대상의 클래스 정의를 얻고, 클래스 성명의 속성과 방법을 얻고, 호출 방법이나 구조 대상을 사용하며, 심지어 실행할 때 클래스 정의를 수정할 수 있다. 2. 속성/방법을 얻을 때'Declared'가...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.