Spring의 aop 실현 원리를 깊이 있게 분석하다

6543 단어 springaop
AOP
AOP(Aspect-Oriented Programming, 방면 프로그래밍)는 OOP(Object-Oriented Programming, 대상 프로그래밍)의 보완과 보완이라고 할 수 있다.OOP는 봉인, 계승, 다태성 등 개념을 도입하여 하나의 대상 차원 구조를 구축하고 공공 행위를 모의하는 집합을 사용한다.우리가 분산된 대상을 위해 공공 행위를 도입해야 할 때 OOP는 무력해 보인다.즉, OOP는 위에서 아래까지의 관계를 정의할 수 있지만 왼쪽에서 오른쪽까지의 관계를 정의하기에 적합하지 않다는 것이다.예를 들어 로그 기능.로그 코드는 종종 모든 대상 차원에 수평적으로 흩어져 있지만, 그것이 흩어진 대상의 핵심 기능과는 아무런 관계가 없다.보안, 이상 처리, 투명한 지속성 등 다른 유형의 코드도 마찬가지다.여기저기 흩어져 있는 무관한 코드를 횡단(cross-cutting) 코드라고 하는데 OOP 디자인에서 대량의 코드의 중복을 초래하여 각 모듈의 중용에 불리하다.
소개
얼마 전에 쓴 자바 디자인 모델인 프록시 모델은 최근에 Spring Aop을 볼 때 프록시 모델과 밀접한 관계가 있어야 한다고 생각해서 Spring Aop의 실현 원리를 이해하기로 했다.
AOP하면 OOP를 말할 수 밖에 없다. OOP에는 봉인, 계승과 다태성 등 개념을 도입하여 대상 차원 구조를 구축하고 공공 행위를 모의하는 집합을 사용한다.그러나 만약에 우리가 일부 대상을 위해 공공 부분을 도입해야 할 때 OOP는 대량의 중복된 코드를 도입한다.예: 로그 기능.
AOP 기술은'가로절단'이라고 불리는 기술을 이용하여 봉인된 대상 내부를 해부하고 여러 종류의 공공 행위를 중용 모듈로 봉인한다. 그러면 시스템의 중복 코드를 줄이고 모듈 간의 결합도를 낮추며 미래의 조작성과 유지보수성에 유리하다.AOP는 소프트웨어 시스템을 핵심 관심사와 횡단 관심사 두 부분으로 나눈다.업무 처리의 주요 절차는 핵심 관심사이고 그와 관계가 크지 않은 부분은 횡단 관심사이다.횡단 관심점의 특징 중 하나는 그들이 핵심 관심점의 여러 곳에서 자주 발생하고 곳곳이 기본적으로 비슷하다는 것이다.예를 들어 권한 인증, 로그, 사무 처리 등이다.
실현 원리
앞에서 대리 모델을 배울 때 대리 모델은 동적 대리와 정적 대리로 나뉜다는 것을 알게 되었다.이제 우리는 프록시 모델을 바탕으로 우리 자신의 AOP 프레임워크를 먼저 실현하고 스프링의 AOP 실현 원리를 연구한다.
먼저 정적 에이전트로 실현하고 정적 에이전트의 관건은 에이전트 대상과 목표 대상이 공통된 인터페이스를 실현하고 에이전트 대상이 목표 대상의 인용을 가지는 것이다.
공통 인터페이스 코드:

public interface IHello {
/**
*  
* @param str
*/
void sayHello(String str);
} 
   :

public class Hello implements IHello{
@Override
public void sayHello(String str) {
System.out.println("hello "+str);
}
} 
프록시 코드, 우리는 그것에 로그 기록 기능을 추가하여 방법이 시작되기 전후에 특정한 방법을 실행합니다. 이것은 AOP와 매우 비슷하지 않습니까?

public class ProxyHello implements IHello{ 
private IHello hello; 
public ProxyHello(IHello hello) {
super();
this.hello = hello;
}
@Override
public void sayHello(String str) {
Logger.start();// 
hello.sayHello(str);
Logger.end();
}
}
로그 클래스 코드:

public class Logger {
public static void start(){
System.out.println(new Date()+ " say hello start...");
}
public static void end(){
System.out.println(new Date()+ " say hello end");
}
}
테스트 코드:

public class Test {
public static void main(String[] args) {
IHello hello = new ProxyHello(new Hello());// , 
//IHello hello = new Hello();// 
hello.sayHello(" "); 
}
}
이렇게 하면 우리는 가장 간단한 AOP를 실현할 수 있다. 그러나 이렇게 하면 문제가 존재한다. 만약에 우리가 Hello와 같은 종류가 많다면, 우리는 Hello Proxy와 같은 종류를 많이 써야 하지 않겠는가.사실 그것도 매우 번거로운 일이다.jdk1.3 이후에 jdk는 우리에게 APIjava를 제공했다.lang.reflect.InvocationHandler의 클래스입니다. 이 클래스는 JVM이 어떤 클래스의 방법을 호출할 때 어떤 방법을 위해 어떤 일을 동적으로 할 수 있도록 합니다.다음은 동적 에이전트의 실현을 실현하겠습니다.
동적 에이전트 구현은 주로 InvocationHandler를 실현하고 목표 대상을 에이전트 대상에 주입하여 반사 메커니즘을 이용하여 목표 대상을 집행하는 방법이다.
인터페이스는 정적 에이전트와 동일합니다. 에이전트 클래스 코드:

public class DynaProxyHello implements InvocationHandler{
private Object target;// 
/**
*  
* @param object
* @return
*/
public Object bind(Object object){
this.target = object;
return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
Logger.start();// 
// 
result = method.invoke(this.target, args);
Logger.end();
return result;
}
}
테스트 클래스 코드:

public class DynaTest {
public static void main(String[] args) {
IHello hello = (IHello) new DynaProxyHello().bind(new Hello());// , 
//IHello hello = new Hello();// 
hello.sayHello(" ");
}
}
위의 코드를 보시면 Spring AOP에 비해 문제가 있을 수 있습니다. 로그 클래스는 방법 전후로만 인쇄할 수 있지만, AOP는 조건을 충족시키면 실행할 수 있을 것입니다. 모든 DynaPoxyHello 대상과 로그 작업 대상(Logger)을 결합시킬 수 있습니까?
다음 코드를 보면 DynaPoxyHello 객체와 로그 작업 객체(Logger)가 결합됩니다.
우리는 피프록시 대상의 방법 앞이나 뒤에 로그 조작 코드(또는 다른 조작 코드)를 추가해야 한다. 그러면 우리는 하나의 인터페이스를 추상화할 수 있다. 이 인터페이스에는 단지 두 가지 방법이 있다. 하나는 피프록시 대상이 방법을 실행하기 전에 실행하는 방법이다. 우리는 start라고 이름을 지었고 두 번째 방법은 피프록시 대상이 집행하는 방법 다음에 실행하는 방법이다. 우리는end라고 이름을 지었다.
Logger 커넥터:

public interface ILogger {
void start(Method method);
void end(Method method);
}
Logger 인터페이스 구현:

public class DLogger implements ILogger{
@Override
public void start(Method method) {
System.out.println(new Date()+ method.getName() + " say hello start...");
}
@Override
public void end(Method method) {
System.out.println(new Date()+ method.getName() + " say hello end");
}
}
동적 프록시 클래스:

public class DynaProxyHello implements InvocationHandler{
// 
private Object proxy;
// 
private Object target;
public Object bind(Object target,Object proxy){
this.target=target;
this.proxy=proxy;
return Proxy.newProxyInstance(this.target.getClass().getClassLoader(), this.target.getClass().getInterfaces(), this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Object result = null;
// 
Class clazz = this.proxy.getClass();
// Start 
Method start = clazz.getDeclaredMethod("start", new Class[]{Method.class});
// start 
start.invoke(this.proxy, new Object[]{this.proxy.getClass()});
// 
method.invoke(this.target, args);
// end 
Method end = clazz.getDeclaredMethod("end", new Class[]{Method.class});
// end 
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();// 
hello.sayHello(" ");
}
} 
상기 예를 통해 동적 에이전트와 발사 기술을 통해 AOP의 기능이 기본적으로 실현되었음을 알 수 있다. 만약에 우리가 방법이 실행되기 전에 로그를 인쇄하기만 하면 end () 방법을 실현하지 않고 인쇄의 시기를 제어할 수 있다.지정한 방법으로 로그를 인쇄하려면 invoke () 방법에 method 이름에 대한 판단을 추가하면 됩니다. method의 이름은 xml 파일에 쓸 수 있습니다. 그러면 프로필로 결합을 풀 수 있습니다. 이렇게 하면 간단한spring aop 프레임워크를 실현할 수 있습니다.
위의 내용은 여러분께 소개된 Spring의 aop 실현 원리입니다. 여러분께 도움이 되었으면 합니다!

좋은 웹페이지 즐겨찾기