AOP는 무엇입니까?
AOP (Aspect-Oriented Programming, Aspect-Oriented Programming)는 OOP (Object-Oriented Programming)의 보충 및 개선이라고 할 수 있습니다. OOP는 캡슐화, 상속 및 다형성과 같은 개념을 소개하여 대중 행동 모음을 시뮬레이션하기 위해 객체 계층을 설정합니다. 흩어진 물체에 대중의 행동을 도입해야 할 때 OOP는 무력한 것 같습니다. 즉, OOP를 사용하면 관계를 위에서 아래로 정의 할 수 있지만 왼쪽에서 오른쪽으로 관계를 정의하는 데 적합하지 않습니다. 예를 들어 로깅 기능. 로그 코드는 종종 산란 된 객체의 핵심 기능과 관련이없이 모든 객체 수준에 걸쳐 수평으로 흩어져 있습니다. 보안, 예외 처리 및 투명성과 같은 다른 유형의 코드에 대해서도 마찬가지입니다. 모든 곳에서 흩어져있는 이러한 종류의 관련없는 코드를 크로스 절단 코드라고합니다. OOP 설계에서는 많은 코드 복제를 유발하며 각 모듈의 재사용에는 도움이되지 않습니다.
소개
내가 얼마 전에 쓴 Java 디자인 패턴 - 프록시 패턴. 최근 Spring AOP를 살펴보면 프록시 패턴에 밀접한 연결이 있어야한다고 느꼈으므로 Spring AOP의 구현 원리를 이해하기로 결정했습니다.
AOP에 대해 말하면, 우리는 OOP에 대해 이야기해야합니다. 캡슐화, 상속 및 다형성의 개념은 OOP에 도입되어 대중 행동 모음을 시뮬레이션하기위한 객체 계층 구조를 확립합니다. 그러나 일부 객체에 공통 부품을 소개 해야하는 경우 OOP는 많은 중복 코드를 소개합니다. 예를 들어 : 로깅 함수.
AOP 기술은 "크로스 컷팅"이라는 기술을 사용하여 캡슐화 된 객체의 내부를 해부하고 여러 클래스에 영향을 미치는 일반적인 동작을 재사용 가능한 모듈로 캡슐화하여 시스템의 코드 복제를 줄이고 모듈 간의 커플 링을 줄이며 향후 작동 가능성 및 유지 보수를 용이하게 할 수 있습니다. AOP는 소프트웨어 시스템을 핵심 관심사와 크로스 컷주의의 두 부분으로 나눕니다. 비즈니스 처리의 주요 프로세스는 핵심 초점이며, 이와 관련하여 거의 관련이없는 부분은 단면 초점입니다. 교차 절단 문제의 특징 중 하나는 종종 여러 핵심 문제에서 발생하며 기본적으로 모든 곳에서 유사하다는 것입니다. 예를 들어, 허가 인증, 로깅 및 거래 처리.
구현 원리
프록시 모드를 학습 할 때 프록시 모드가 동적 프록시 및 정적 프록시로 나뉘어져 있음을 알게되었습니다. 이제 먼저 프록시 모델을 기반으로 자체 AOP 프레임 워크를 구현 한 다음 Spring의 AOP의 구현 원리를 연구합니다.
먼저 정적 프록시로 구현됩니다. 정적 프록시의 키는 프록시 객체와 대상 객체 사이의 공통 인터페이스를 구현하는 것입니다. 프록시 객체는 대상 객체에 대한 참조를 유지합니다.
공개 인터페이스 코드 :
공개 인터페이스 ihello {/*** 비즈니스 방법*@param str*/void sayhello (string str);} 대상 클래스 코드 : 공개 클래스 hello 구현 ihello {@overridepublic void sayhello (string str) {system.out.println ( "hello"+str);}} 프록시 클래스 코드의 경우 로깅 기능을 추가하고 메소드가 시작되기 전후에 특정 메소드를 실행합니다. AOP와 특히 비슷하지 않습니까?
공개 클래스 ProxyHello는 IHELLO {Private IHello Hello; public proxyhello (ihello hello) {super (); this.hello = hello;}@attrementpublic void sayhello (string str) {logger.start (); // 특정 메소드 추가 hello.sayhello (str); logger.end ();}} 로그 클래스 코드 :
public class logger {public static void start () {System.out.println (new Date ()+ "Hello Start ...");} public static void end () {System.out.println (새 날짜 ()+ "hello end");}} 테스트 코드 :
public class test {public static void main (String [] args) {ihello hello = new proxyHello (new Hello ()); // 로깅 함수가 필요한 경우 프록시 클래스를 사용해야합니다. // iHello hello = new Hello (); // 로지 기능이 필요하지 않으면 대상 클래스 hello.sayhello ( "TOMARTH"); }}이런 식으로, 우리는 가장 간단한 AOP를 구현하지만 문제가있을 것입니다. Hello와 같은 수업이 많으면 HelloProxy와 같은 많은 수업을 작성해야합니까? 사실, 그것은 또한 매우 번거로운 일입니다. JDK1.3 이후 JDK는 API java.lang.reflect.invocationHandler 클래스를 제공합니다. 이 클래스를 사용하면 JVM이 특정 클래스의 메소드를 호출 할 때 일부 방법에 대해 동적으로 무언가를 할 수 있습니다. 동적 프록시 구현을 구현하겠습니다.
동적 프록시 구현은 주로 invocationhandler를 구현하고 반사 메커니즘을 사용하여 대상 객체 메소드를 실행하여 대상 객체를 프록시 객체에 주입합니다.
인터페이스 구현은 정적 프록시, 프록시 클래스 코드와 동일합니다.
공개 클래스 DynaproxyHello는 invocial helller를 구현합니다 {private 객체 대상; // target 객체/*** 반사를 통해 대상 객체를 인스턴스화합니다* @param 객체* @return*/public 객체 바인드 (객체 객체) {this.target = object; return prox.newproxyinstance (this.target.get.getclass (). this);}@reverridepublic 객체 호출 (객체 프록시, 메소드 메소드, 오브젝트 [] args) 던지기 가능 {object result = null; logger.start (); // 반사 메커니즘을 통해 대상 객체를 실행하는 메소드 추가 // 메소드 추가 // 메소드 추가 방법 = method.invoke (this.target, args); logger.end ()}}}}}}}. 테스트 클래스 코드 :
public class dynatest {public static void main (string [] args) {ihello hello = (ihello) new dynaproxyhello (). bind (new Hello ()); // 로깅 함수가 필요한 경우 프록시 클래스를 사용해야합니다. 위의 코드를 읽은 후 Spring AOP와 비교하여 문제가있을 수 있습니다. 로그 클래스는 메소드 전후에만 인쇄 할 수 있지만 조건이 충족되면 AOP를 실행할 수 있어야합니다. 모든 Dynapoxyhello 객체와 로그 작동 객체 (로거)를 분리 할 수 있습니까?
다음 코드 구현을 살펴보면 DynapoxyHello 객체와 로그 작동 오브젝트 (로거)를 분리합니다.
프록시 오브젝트의 메소드 전후에 로그 작동 코드 (또는 기타 조작 코드)를 추가해야합니다. 그런 다음 두 가지 방법 만있는 인터페이스를 추상화 할 수 있습니다. 하나는 프록시 객체가 메소드를 실행하기 전에 실행 된 메소드입니다. 우리는 그것을 시작했고, 두 번째 방법은 프록시 객체가 메소드를 실행 한 후 실행 된 메소드이며, 우리는 그것을 끝이라고 명명했습니다.
로거 인터페이스 :
public Interface ilogger {void start (메소드 메소드); void end (method method);} 로거 인터페이스 구현 :
public class dlogger는 ilogger를 구현합니다 {@overridepublic void start (method method) {system.out.println (new date () + method.getname () + "hello start ...");}@overridepublic void end (method.fublic void end (method) {system.out.println () + method.getname () + " +") 동적 프록시 클래스 :
공개 클래스 DynaproxyHello는 호출 핸들러를 구현합니다 {// 객체 개인 객체 프록시 호출; // 대상 객체 개인 객체 대상; 공개 객체 바인드 (개체 대상, 개체 프록시) {this.target = target; this.proxy = proxy; return prox.NewProxyInstance (this.target.getclass (). this.target.getClass (). getInterfaces (), this);}}}@atrivePublic Object invoke (개체 프록시, 메소드 메소드, 오브젝트 [] args) 던질 수있는 {object result = null; // 반사자 인스턴스 클래스 클래스 Clazz = this.proxy.getclass (); // reflector의 시작 방법을 가져옵니다. class [] {method.class}); // 반사는 시작 메소드 시작을 실행합니다. invoke (this.proxy, new object [] {this.proxy.getclass ()}); // 객체 메소드를 처리하기 위해 원래 메소드를 실행하여 invoke (the.target, args); "", clazz.getdecleThod (ggetdecledmeThod)를 얻습니다. class [] {method.class}); // 반사는 end method end.invoke (this.proxy, new Object [] {method}); return result;}}을 실행합니다. 테스트 코드 :
public class dynatest {public static void main (string [] args) {ihello hello = (ihello) new dynaproxyhello (). bind (new Hello (), new dlogger ()); // 로깅 함수가 필요하다면 프록시 클래스 // ihello hello = new Hello (); // Target Class를 사용하지 않으면 대상 클래스를 사용하십시오. hello.sayhello ( "내일");}} 위의 예를 통해 동적 프록시 및 전송 기술을 통해 AOP의 기능이 기본적으로 구현되었음을 알 수 있습니다. 메소드가 실행되기 전에 로그를 인쇄 해야하는 경우 인쇄 타이밍을 제어 할 수 있도록 end () 메소드를 구현할 수 없습니다. 지정된 메소드가 로그를 인쇄하려는 경우 invoke () 메소드에 메소드 이름에 대한 판단 만 추가하면됩니다. 메소드 이름은 XML 파일로 작성하여 구성 파일로 분리하여 간단한 스프링 AOP 프레임 워크를 구현할 수 있습니다.
위의 내용은 편집자가 귀하에게 소개 한 Spring AOP 구현 원리입니다. 나는 그것이 당신에게 도움이되기를 바랍니다!