Java 반사 메커니즘과 동적 프록시는 Java를 더욱 강력하게 만듭니다. Spring의 핵심 개념 IOC 및 AOP는 반사 메커니즘과 동적 프록시를 통해 구현됩니다.
1 자바 반사
예:
사용자 user = new user (); user.settime5flag ( "테스트"); class <?> cls = class.forname ( "com.test.user"); // 인터페이스는이 클래스에서 내부적으로 사용되는지 여부에 관계없이 공개되어야합니다! cls.getDeclaredMethod ()를 사용하거나 Traverse를 사용하여 접근성 방법을 수정하여 방법 = cls.getMethod ( "gettime5flag"); 문자열 res1 = (string) method.invoke (사용자); System.out.println (Res1); // int와 같은 기본 유형이 포함 된 경우 int.class를 사용하십시오! integer.class! = int.class! method = cls.getMethod ( "settime5flag", String.class); method.invoke (user, "rollen"); 메소드 = cls.getMethod ( "gettime5flag"); 문자열 res2 = (string) method.invoke (user); system.out.println (res2);
개체를 통해 전체 패키지 및 클래스 이름을 얻으십시오.
user.getClass (). getName (); // 전체 경로 클래스 이름 user.getClass (). getSimplename (); // 패키지 이름이없는 클래스 이름
수업 받기 :
class.forname ( "com.test.user"); com.test.user.class; user.getClass ();클래스를 통해 개체를 인스턴스화하십시오
사용자 user = (사용자) cls.newinstance (); // 매개 변수 생성자가 있어야합니다.모든 생성자를 얻으십시오
생성자 <?> cons [] = cls.getConstructors (); // 선언 순서에서 return cons [0] .newinstance (); // 디스플레이 선언이 없으면 기본 생성자가 있습니다클래스에서 구현 한 모든 인터페이스를 가져옵니다
클래스 <?> intes [] = cls.getInterfaces ();부모 수업을 받으십시오
cls.getSuperClass ();수정자를 얻으십시오
int mo = cls.getModifiers (); int mo = cons [0] .getModifiers (); int mo = method.getModifiers (); modifier.toString (mo);메소드 매개 변수를 얻습니다
method.getParameters (); cons [0] .getParameters ();메소드 매개 변수 유형을 가져옵니다
Method.getParametortypes (); cons [0] .getParametortypes ();메소드 선언에 따라 모든 예외 유형을 가져옵니다
method.getexceptionTypes ();이 클래스에서 모든 속성을 선언하십시오
필드 [] 필드 = cls.getDeclaredFields (); // privatefield [0] .getModifiers (); 필드 [0] .getType ();
부모 클래스 선언, 인터페이스 선언 및이 클래스 선언의 모든 공개 속성을 포함 하여이 클래스의 모든 공개 속성을 얻으십시오.
cls.getFields ();
지정된 속성을 액세스하도록 설정하십시오
field.setAccessible (true); field.set (obj, 'ces'); field.get (obj);
* getFields ()와 getDeclaredFields ()의 차이점은 클래스에서 공개로 선언 된 필드 만 액세스 할 수 있습니다. 개인 분야에 액세스 할 수 없으며 다른 클래스에서 상속 된 공공 분야에 액세스 할 수 있습니다. getDeclaredFields ()는 클래스의 모든 필드에 액세스 할 수 있으며,이 필드는 공개, 개인 및 보호와 관련이 없지만 다른 클래스에서 상속 된 필드에 액세스 할 수는 없습니다.
* getMethods ()와 getDeclaredMethods ()의 차이점은 클래스에서 공개로 선언 된 메소드에만 액세스 할 수 있으며 개인 방법에 액세스 할 수 없으며 다른 클래스에서 상속 된 공개 메소드에 액세스 할 수 있습니다. getDeclaredMethods ()는 클래스의 모든 필드에 액세스 할 수 있으며,이 필드는 공개, 개인 및 보호와 관련이 없으며 다른 클래스에서 상속 된 메소드에 액세스 할 수 없습니다.
* getConstructors ()와 getDeclaredConstructors ()의 차이점 : GetConstructors ()는 클래스에서 공개로 선언 된 생성자 만 액세스 할 수 있습니다. getDeclaredConstructors ()는 클래스의 모든 생성자에 액세스 할 수 있으며 공개, 개인 및 보호와 관련이 없습니다.
반사를 통해 배열의 정보를 얻고 수정하십시오.
int [] temp = {1,2,3,4,5}; class <?> demo = temp.getClass (). getComponentType (); system.out.println ( "array type :"+demo.getName ()); // intsystem.out.println ( "array length :" "+array.getLength (temp)); // 5system.out.println ("배열의 첫 번째 요소 : "+array.get (temp, 0)); // 1array.set (temp, 0, 100); system.out.out.println ("수정 후 배열의 첫 번째 요소는 : "+array.get); // 100); 배열 유형을 가져옵니다cls.getComponentType ();배열 유형인지 확인하십시오
cls.isarray ();
2 자바 에이전트
프록시 모델은 일반적으로 사용되는 Java 디자인 모델입니다. 그 특성은 프록시 클래스와 대의원 클래스가 동일한 인터페이스를 가지고 있다는 것입니다. 프록시 클래스는 주로 전처리 메시지, 메시지 필터링, 대의원 클래스로 메시지 전달 및 이벤트 후 메시지를 처리 할 책임이 있습니다. 프록시 클래스와 대의원 클래스 사이에는 일반적으로 연관성이 있습니다. 프록시 클래스의 객체는 대의원 클래스의 객체와 관련이 있습니다. 프록시 클래스 자체의 객체는 실제로 서비스를 구현하지는 않지만 대의원 클래스 객체의 관련 방법을 호출하여 특정 서비스를 제공합니다.
에이전트 생성 기간에 따르면, 에이전트 클래스는 두 가지 유형으로 나눌 수 있습니다.
• 정적 프록시 : 프로그래머가 생성하거나 특정 도구별로 소스 코드를 자동으로 생성 한 다음 컴파일합니다. 프로그램이 실행되기 전에 프록시 클래스의 .class 파일이 이미 존재합니다.
• 동적 프록시 : 프로그램이 실행될 때 바이트 코드는 Java 반사 메커니즘에 의해 동적으로 생성됩니다.
2.1 정적 프록시
public interface count {public void querycount ();} public class countimpl emplements count {public void querycount () {system.out.println ( "보기 계정 메소드 ..."); }} // 프록시 클래스 공개 클래스 COUNTPROXY는 COUNT {private countimpl countimpl; public countproxy (countimpl countimpl) {this.countimpl = countimpl; } @override public void QueryCount () {System.out.println ( "트랜잭션 처리 전"); countimpl.queryCount (); // 델리게이트 클래스 메소드를 호출합니다. System.out.println ( "트랜잭션 처리 후"); }} // 테스트 클래스 공개 클래스 testCount {public static void main (string [] args) {countimpl countimpl = new countimpl (); COUNTPROXY COUNTPROXY = NEW COUNTPROXY (COUNTIMPL); countproxy.queryCount (); }}코드를 관찰하고 각 프록시 클래스가 하나의 인터페이스 만 제공 할 수 있으므로 너무 많은 프록시가 프로그램 개발에서 필연적으로 발생할 수 있음을 찾으십시오. 또한 다른 호출 방법을 제외한 모든 프록시 작업은 다른 모든 작업이 동일하므로 현재 코드를 반복해야합니다. 이 문제를 해결하는 가장 좋은 방법은 프록시 클래스를 통해 모든 프록시 기능을 완료하는 것이므로 현재 동적 프록시를 사용하여 수행해야합니다.
2.2 동적 에이전트
동적 프록시 클래스의 바이트 코드는 프로그래머가 수동으로 소스 코드를 작성할 필요없이 프로그램이 실행될 때 Java 반사 메커니즘에 의해 동적으로 생성됩니다. 동적 프록시 클래스는 프로그래밍을 단순화 할뿐만 아니라 소프트웨어 시스템의 확장 성을 향상시킵니다. Java 반사 메커니즘은 모든 유형의 동적 프록시 클래스를 생성 할 수 있기 때문입니다.
2.2.1 JDK 동적 프록시
java.lang.reflect 패키지의 프록시 클래스 및 호출 핸들러 인터페이스는 동적 프록시 클래스를 생성 할 수있는 기능을 제공합니다.
InvocationHandler 인터페이스 :
공개 인터페이스 invocationHandler {
공개 객체 호출 (객체 프록시, 메소드 메소드, 개체 [] args) 던지기 가능;
}
매개 변수 설명 :
객체 프록시 : 대상이 프록시되는 객체를 나타냅니다.
방법 방법 : 호출되는 방법
Object [] args : 메소드를 호출 할 때 필요한 매개 변수
invocationhandler 인터페이스의 서브 클래스를 프록시의 최종 조작 클래스로 생각할 수 있으며 proxysubject를 대체 할 수 있습니다.
프록시 클래스 :
프록시 클래스는 프록시를 전문으로하는 운영 클래스입니다. 이 클래스를 통해 하나 이상의 인터페이스에 대한 구현 클래스를 동적으로 생성 할 수 있습니다. 이 클래스는 다음 작업 방법을 제공합니다.
public static 객체 NewProxyInstance (클래스 로더 로더, 클래스 <?> [] 인터페이스, invocationHandler h)는 불법 행위를 던졌습니다.
매개 변수 설명 :
클래스 로더 로더 : 클래스 로더
클래스 <?> [] 인터페이스 : 모든 인터페이스를 가져옵니다
InvocationHandler H : invocationHandler 인터페이스의 서브 클래스 인스턴스를 가져옵니다
동적 프록시를 완료하려면 먼저 프록시의 특정 작동을 완료하려면 호출 핸들러 인터페이스의 서브 클래스를 정의해야합니다.
인터페이스 주제 {public String sayment (문자열 이름, int age);} class realsubject impless and {@override public string (문자열 이름, int age) {return name + "" + age; }} // jdk 동적 프록시 클래스 MyInvocationHandler는 invocationHandler {private 객체 target = null; // 대의원 객체를 바인딩하고 프록시 클래스 공개 객체 바인드 (객체 대상) {this. 대상 = 대상; return proxy.newproxyInstance (target.getClass (). getClassLoader (), target.getClass (). getInterfaces (), this); // 인터페이스를 바인딩합니다 (cglib 구성)} @override public object invoke (개체 프록시, 메소드 메소드, 객체 [] args) 던질 가능 {system.out.println ( "이전 메소드!"); 객체 temp = method.invoke (target, args); System.out.println ( "Method!"); 반환 온도; }} class hello {public static void main (String [] args) {myinVocationHandler demo = new MyInvocationHandler (); 제목 sub = (주제) demo.bind (new RealSubject ()); 문자열 정보 = sub.say ( "rollen", 20); System.out.println (정보); }} 그러나 JDK의 동적 프록시는 인터페이스 구현에 의존합니다. 일부 클래스가 인터페이스를 구현하지 않으면 JDK 프록시를 사용할 수 없으므로 CGLIB Dynamic Proxy를 사용해야합니다.
2.2.2 CGLIB 동적 프록시
JDK의 동적 프록시 메커니즘은 인터페이스를 구현하는 프록시 클래스 만 가능하지만 인터페이스를 구현하지 않는 클래스는 JDK의 동적 프록시를 구현할 수 없습니다.
CGLIB는 클래스의 프록시를 구현합니다. 그 원칙은 지정된 대상 클래스에 대한 서브 클래스를 생성하고 메소드 구현 향상을 무시하는 것입니다. 그러나 상속이 사용되기 때문에 최종 수정 된 클래스를 파악할 수 없습니다.
공개 인터페이스 BookFacade {public void addbook (); } public class bookfacadeimpl1 {public void addbook () {System.out.println ( "책을 추가하는 일반 방법 ..."); }} import java.lang.reflect.method; import net.sf.cglib.proxy.enhancer; import net.sf.cglib.proxy.methodinterceptor; import net.sf.cglib.proxy.methodproxy; // cglib dynamic proxy class public class public class bookfacadecglib emplements methodinterceptor {private 객체 대상; // 대의원 객체를 바인딩하고 프록시 클래스 공개 객체 getInstance (객체 대상) {this.target = target; Enhancer Enhancer = New Enhancer (); Enhancer.setSuperClass (this.target.getClass ()); // 콜백 메소드 Enhancer.setCallback (this); // 프록시 객체 작성 return Enhancer.create (); } @override // 콜백 메소드 공개 객체 인터셉트 (오브젝트 obj, 메소드 메소드, 오브젝트 [] args, methodProxy proxy) 던지기 가능 {system.out.println ( "function start"); Object temp = proxy.invokesuper (obj, args); System.out.println ( "함수 종료"); 반환 온도; }} public class testcglib {public static void main (String [] args) {bookfacadecglib cglib = new BookFacadeCglib (); BookFacadeImpl1 bookcglib = (BookFacadeImpl1) cglib.getInstance (new BookFacadeImpl1 ()); bookcglib.addbook (); }}Java Reflection and Proxy에 대한 위의 간단한 논의는 내가 당신과 공유하는 모든 내용입니다. 나는 당신이 당신에게 참조를 줄 수 있기를 바랍니다. 그리고 당신이 wulin.com을 더 지원할 수 있기를 바랍니다.