Spring 소스 코드 분석의 4 --- AOP 원리 와 소스 코드 분석
12690 단어 Spring
공교롭게도 나 에 게 도 있다.
JDK 의 동적 에이전트 의 실현 과 소스 코드 분석, 나의 이 두 글 참조
JDK 의 동적 에이전트 소스 분석 중 하나 ( http://blog.csdn.net/weililansehudiefei/article/details/73655925 )
JDK 의 동적 에이전트 소스 분석 2 ( http://blog.csdn.net/weililansehudiefei/article/details/73656923 )
위의 두 개 는 알 아 보 았 으 니 이 글 을 볼 수 있 습 니 다. 자바 반사 에 대해 서 는 알 면 됩 니 다. 하지만 더욱 공교롭게도 제 블 로그 에 자바 반 사 를 소개 하 는 한 편 이 있 습 니 다.
자바 반사 의 실현 과 기본 원리, 나의 이 글 참조
자바 반사 메커니즘 (http://blog.csdn.net/weililansehudiefei/article/details/70194940)
그럼 AOP 로 넘 어 가 는 코너 로 넘 어가 도록 하 겠 습 니 다.
AOP 는 절단면 을 대상 으로 프로 그래 밍 을 하 는 것 입 니 다. AOP 를 처음 배 웠 을 때 각종 AOP 의 개념 만 얼떨떨 하 게 만 들 었 습 니 다. 어떤 절단면, 접점, 알림, 짜 임, 연결 점, 목표 대상... AOP 의 원 리 를 보지 도 않 았 는데 이런 단어의 뜻 은 이미 사람들 이 보고 싶 지 않 습 니 다. 본인 은 AOP 를 실현 할 때 제 가 이해 하 는 AOP 의 용어, 대응 하 는 AOP 의 코드 와 움직임 을 설명 할 것 입 니 다.하 다
본 고 는 먼저 코드 에서 AOP 를 실현 하 는 데 착안 한 다음 에 AOP 의 바 텀 코드 와 그 원 리 를 분석 할 것 이다.
나중에 모든 프로젝트 구현 코드 를 GitHub 에 올 려 놓 고 그 때 는 글 을 업데이트 하 겠 습 니 다.
AOP 의 데모
만약 우리 대상 의 상속 관계 가 수직 관계 로 간주 된다 면, 마치 한 그루 의 나무 와 같다. 여러 개의 서로 다른 상속 관 계 는 한 줄 의 나무 와 같다. AOP 의 장점 은 바로 이 나무 들 에 대해 같은 조작 을 하고 싶다 는 것 이다. 이 럴 때, 세로 로 모든 나무 에 대해 조작 방법 을 정의 하지 않 고, 가로로 한 칼 로 잘라 서 그들 에 게 공 통 된 조작 방법 을 주어 야 한 다 는 것 이다.
Spring 의 AOP 는 JDK 의 동적 에이전트 와 Cglib 의 동적 에이 전 트 를 지원 합 니 다. JDK 의 동적 에이 전 트 는 인 터 페 이 스 를 위 한 것 이 고, Cglib 는 클래스 를 위 한 것 입 니 다. 본 고 는 JDK 의 동적 에이 전 트 를 위 한 것 입 니 다.
먼저 인 터 페 이 스 를 정의 합 니 다. 이름 을 지 을 때 이 인터페이스 이름 에 특별히 인 터 페 이 스 를 가 져 왔 습 니 다. 그러면 뒤에 더욱 주 의 를 끌 수 있 습 니 다. 인 터 페 이 스 는 간단 합 니 다. 그 안에 추상 적 인 방법 eat () 가 있 습 니 다.
package com.weili.cn;
/**
* Created by weili on 17/6/27.
*/
public interface AnimalInterface {
public abstract void eat();
}
실현 클래스: 하나의 먹 방 으로서 실현 클래스 에 당연히 chi 를 인쇄 해 야 합 니 다. chi 치.. 배 불 러 죽 겠 어!!!
이 실현 류 에는 오직 한 가지 방법 이 있 습 니 다. 이 방법 이 바로 AOP 의 절 점 입 니 다. 절 점 이라는 개념 자체 가 반드시 Method 는 아니 지만 Spring 에 서 는 모든 절 점 이 Method 입 니 다. 우리 가 강화 하 는 것 은 방법 입 니 다.
package com.weili.cn;
/**
* Created by weili on 17/6/27.
*/
public class Animal implements AnimalInterface{
public void eat() {
System.out.println("Animal chi chi chi");
}
}
절단면 류 는 증강 류 라 고도 부른다. 우 리 는 이러한 방법 으로 원래 의 절 점 방법 을 강화 해 야 하기 때문이다. 절단면 류 에서 우리 가 실행 해 야 할 방법 을 통지 라 고 한다. 이른바 짜 서 통지 하 는 것 은 절단면 류 안의 방법 을 절 점 하 는 방법 과 연계 하 는 것 이다.
package com.weili.cn;
import org.aopalliance.intercept.Joinpoint;
/**
* Created by weili on 17/6/27.
*/
public class AdviceAnimal {
public void animalEmpty(){
//System.out.println("joint before "+ joinPoint.getClass().getName());
System.out.println(" ");
}
public void animalFull(){
System.out.println(" ");
}
public void animalEat(){
System.out.println(" ");
}
}
다음은 xml 설정 을 통 해 xml 파일 에 AOP 를 설정 합 니 다.
설정 할 때 expressi 표현 식 을 통 해 com. weili. cn 이 가방 에 있 는 모든 종류의 방법 을 착안점 으로 정의 합 니 다. 즉, 이 가방 에 있 는 모든 방법 은 호출 이 실 행 될 때 Spring 에 의 해 강 화 됩 니 다. 구체 적 으로 이 절 점 방법 을 실행 하기 전과 그 후에 각각 animalEmpty 와 animalFull 방법 을 실행 합 니 다.
마지막 으로 호출 하 는 방법 입 니 다.
우리 가 spring - op. xml 분석 을 할 때 op 은 아직 실현 되 지 않 았 습 니 다. 두 번 째 줄 getBean 에서 야 진정 으로 op 을 진행 할 수 있 습 니 다. 구체 적 인 소스 코드 에 대해 서 는 설명 하 겠 습 니 다.
package com.weili.cn;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Hello world!
*
*/
public class App
{
public static void main( String[] args )
{
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-aop.xml");
AnimalInterface animal = (AnimalInterface) ctx.getBean("animal");
animal.eat();
}
}
이 어 Output 입 니 다. 그래서 얻 은 bean 은 확실히 강 화 된 bean 입 니 다. 그럼 소스 코드 를 보 세 요.
Animal chi chi chi
2. AOP 소스 코드 분석
원본 코드 는 이것 을 분석 합 니 다. 우선 bean 로 딩 입 니 다. 앞서 말 했 듯 이 AOP 탭 도 사용자 정의 탭 입 니 다. 이 탭 의 해석 도 이전 사용자 정의 탭 과 마찬가지 로 사용자 정의 탭 의 해석 절 차 를 밟 습 니 다. 다른 것 은 AOP 가 AOP 자체 의 해석 기 를 호출 하기 때 문 입 니 다. Spring 소스 코드 분석 2 - 사용자 정의 태그 분석 및 등록 사용자 정의 탭 의 분석 절 차 를 상세 하 게 설명 하 였 기 때문에 bean 탭 의 분석 등록 을 일일이 보지 않 습 니 다.
따라서 AOP 의 소스 코드 분석 은 호출 클래스 의 두 번 째 줄 인 ctx. getBean ("animal") 부터 시작 합 니 다. 디 버 깅 을 통 해 여기까지 왔 을 때 ctx 에서 분석 과 등 록 된 bean 을 볼 수 있 습 니 다. 먼저 살 펴 보 겠 습 니 다.
다음 그림 입 니 다. 이것 은 첫 번 째 줄 코드 가 실 행 된 후, ctx 의 각 속성 입 니 다. 다음 그림 에서 볼 수 있 습 니 다. singlenton Objects 에는 이미 대리 생 성 된 animal 이 저장 되 어 있 습 니 다. 생 층 bean 의 과정 은 이전의 과정 에서 비교적 명확 하 게 설명 되 었 습 니 다. 여 기 는 더 이상 설명 하지 않 습 니 다. AOP 잖 아 요. 우 리 는 그것 이 우리 가 실행 해 야 할 방법 전후 에 우 리 를 어떻게 하 는 지 알 아야 합 니 다.실행 할 방법 이 필요 합 니 다.
ctx. getBean ("animal") 에서 animal bean 을 가 져 온 다음 eat () 방법 을 사용 합 니 다. 이때 JdkDynamicAopProxy 류 의 invoke 방법 에 들 어 갑 니 다. 이 invoke 방법 에 서 는 프 록 시 targetClass 를 가 져 온 다음 method 와 targetClass 에 따라 이 방법 에 대응 하 는 차단 기 를 가 져 와 체인 체인 체인 을 실행 합 니 다.
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class> targetClass = null;
Object target = null;
Boolean var10;
try {
if(this.equalsDefined || !AopUtils.isEqualsMethod(method)) {
if(!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
Integer var18 = Integer.valueOf(this.hashCode());
return var18;
}
Object retVal;
if(!this.advised.opaque && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) {
retVal = AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
return retVal;
}
if(this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
if(target != null) {
targetClass = target.getClass();
}
List
이 chain 의 내용 은 다음 과 같 습 니 다. 이름 을 통 해 알 수 있 듯 이 하 나 는 after Advice 이 고 하 나 는 before Advice 입 니 다. chain 을 가 져 온 후 MethodInvoke 방법 을 만 들 고 proceed 방법 을 실행 합 니 다.
proceed 방법 에 들 어 갑 니 다. current InterceptorIndex 의 초기 화 값 은 - 1 입 니 다. 이 어 invoke 방법 과 같 습 니 다. 여기 this 는 우리 의 eat 방법 입 니 다.
public Object proceed() throws Throwable {
if(this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return this.invokeJoinpoint();
} else {
Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if(interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;
return dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)?dm.interceptor.invoke(this):this.proceed();
} else {
return ((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);
}
}
}
invoke 방법 에서 여기 미 는 우리 인터페이스 에 있 는 eat 방법 입 니 다. 그리고 미의 proceed () 방법 을 실행 합 니 다. public Object invoke(MethodInvocation mi) throws Throwable {
MethodInvocation oldInvocation = (MethodInvocation)invocation.get();
invocation.set(mi);
Object var3;
try {
var3 = mi.proceed();
} finally {
invocation.set(oldInvocation);
}
return var3;
}
이 럴 때 는 계속 시작 하 는 proced 방법 으로 돌아 갑 니 다. 이때 얻 은 것 은?interceptorOrInterceptionAdvice, list ,after 。 , before 。
before ,
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
invokeJoinpoint ,
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args) throws Throwable { try { ReflectionUtils.makeAccessible(method); return method.invoke(target, args); } catch (InvocationTargetException var4) { throw var4.getTargetException(); } catch (IllegalArgumentException var5) { throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", var5); } catch (IllegalAccessException var6) { throw new AopInvocationException("Could not access method [" + method + "]", var6); } } }
after 。
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
[MeU] Hashtag 기능 개발➡️ 기존 Tag 테이블에 존재하지 않는 해시태그라면 Tag , tagPostMapping 테이블에 모두 추가 ➡️ 기존에 존재하는 해시태그라면, tagPostMapping 테이블에만 추가 이후에 개발할 태그 기반 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.