자바 AOP 원리 및 실례 용법 총결산

7022 단어 자바AOP
AOP :
절단면 프로 그래 밍
프로 그래 밍 에서 우 리 는 높 은 결합 과 낮은 내부 집적 을 만족 시 켜 야 하기 때문에 프로 그래 밍 은 6 대 원칙,하나의 법칙 을 만족 시 켜 야 한다.
AOP 가 절단면 을 대상 으로 프로 그래 밍 하 는 것 은 바로 이러한 원칙 을 만족 시 키 기 위 한 프로 그래 밍 사상 이다.
1.장식 자 모드:
우리 가 대상 에 게 기능 을 추가 해 야 할 때 단일 한 직책 원칙 을 만족 시 키 기 위해 장식 자 모델 로 프로 그래 밍 을 하고 원래 의 종 류 를 장식 할 수 있 는 종 류 를 만 들 수 있다.이런 종 류 는 원래 의 기능 에 추가 해 야 하 는 기능 이다.
예 를 들 어 한 가지 유형 안에 도 서 를 추가 하 는 기능 이 있다.

@Service
public class BookSericeImpl implements BookSerice {
 @Override
 public void addOne(BokBean bokBean) {
  System.out.println("    :     ");
 }
 @Override
 public void deletOne(Long bookId) {
  System.out.println("    :     ");
 }
}
이 를 바탕 으로 인쇄 로 그 를 추가 하 는 기능 이 필요 합 니 다.

public class BooklogServiceImpl implements BookSerice {
 private BookSerice bookSerice;
 public BooklogServiceImpl(BookSerice bookSerice) {
  this.bookSerice = bookSerice;
 }
 @Override
 public void addOne(BokBean bokBean) {

  System.out.println("       ");
  this.bookSerice.addOne(bokBean);
  System.out.println("       ");
 }
 @Override
 public void deletOne(Long bookId) {

  System.out.println("       ");
  this.bookSerice.deletOne(323L);
  System.out.println("       ");
 }
}
다음은 이 증강 후의 대상 을 호출 하 겠 습 니 다.

public void test1(){

  //Aop :      

  //           
  BookSerice bookSerice = new BookSericeImpl();
  //                     ,                
  //                      .
  bookSerice = new BooklogServiceImpl(bookSerice);
  //          ,                        
  bookSerice.addOne(new BokBean());
 }
이렇게 해서 우 리 는 원래 코드 를 바 꾸 지 않 는 토대 에서 기능 을 추 가 했 고 단일 직책 의 원칙 을 만족 시 켜 코드 의 결합 성 을 낮 추 었 다.
그러나 인터페이스 에 여러 가지 방법 이 있다 면 모든 방법 이 로그 기능 을 추가 해 야 한다 면 중복 코드 가 많이 나타 나 고 장식 자 모드 는 여러 개의 관계 가 없 는 클래스 를 동시에 강화 할 수 없다.
그래서 자바 는 동적 에이전트 기술 을 도입 하여 기능 을 증가 시 켰 다.
동적 에이전트
자바 에서 동적 대 리 는 두 가지 실현 방식 이 있 습 니 다.
① 인터페이스 가 있 는 클래스 의 대 리 를 대상 으로 jdk 에서 가방 을 반사 하 는 동적 대 리 를 사용 합 니 다.
② 인터페이스 가 없 는 클래스 의 프 록 시 에 대해 제3자 jar 패키지 Enhancer 를 사용 합 니 다.
인터페이스 도 없고 final 도 없다 면 강화 할 수 없다.
1.첫 번 째 실현:
인터페이스 기반 동적 에이전트,자바 내부 반사 팩 사용 강화
이런 방식 으로 대상 을 만 드 는 것 은 목표 대상 의 형제 대상 이다.
마찬가지 로 위 는 인터페이스의 두 가지 기능 을 실현 한 유형 이다.

@Service
public class BookSericeImpl implements BookSerice {
 @Override
 public void addOne(BokBean bokBean) {
  System.out.println("    :     ");
 }
 @Override
 public void deletOne(Long bookId) {
  System.out.println("    :     ");
 }
}
대상 을 통 해 위의 두 가지 방법 을 호출 합 니 다.

public void test2(){

 //         
 BookSerice bookSerice = new BookSericeImpl();
 //            
 ClassLoader classLoader = bookSerice.getClass().getClassLoader();
 //               
 Class<?>[] interfaces = bookSerice.getClass().getInterfaces();
 //      ,      (    ,          ,InvocationHandler      )
 bookSerice = (BookSerice) Proxy.newProxyInstance(classLoader, interfaces, new LogHandler(bookSerice)); 
 bookSerice.addOne(new BokBean());
 bookSerice.deletOne(232L);
}
프 록 시 대상 을 만 들 때 InvocationHandler 인터페이스 클래스 의 대상 이 필요 합 니 다.다음은 이러한 구현 클래스 를 만 듭 니 다.

public class LogHandler implements InvocationHandler {

 //                     
 //                     
 private Object target;
 public LogHandler(Object target) {
  this.target = target;
 }
 //             ,      invoke  
 @Override
 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
  String classname = target.getClass().getName();
  String methodName = method.getName();
  System.out.println(classname+"."+methodName+"      ");
  //     Method              (addone)
  Object value = method.invoke(target, args);
  System.out.println(classname+"."+methodName+"      ");
  return value;

 }
}
이렇게 동적 대 리 를 실현 한 후에 실현 되 는 인터페이스 에 몇 가지 방법 이 있 든 지 간 에 당신 은 이 방법 을 호출 하면 이 방법 을 강화 할 것 입 니 다.모든 방법 에 대해 증강 기능 을 한 번 쓰 지 않 아 도 됩 니 다.
또한 이 증강 류 LogHandler 류 와 원래 의 실현 류 BookSericeImpl 류 는 결합 성 이 없습니다.이것 은 당신 이 어떤 인터페이스 류 의 실현 류 든 지 간 에 이러한 대상 을 대리 하면 이러한 방법 에 이 새로운 기능 을 추가 할 수 있다 는 것 입 니 다.
전체적으로 보면 이런 동적 대리 실현 방식 은 반사 기술 을 이용 하여 호출 된 방법 명 을 찾 아 이 방법 에 대해 강화 하 는 것 이다.
어떤 방법 에 기능 을 추가 할 필요 가 없 을 때 는 가지 고 있 지 않 아 도 된다.
2.두 번 째 실현:
클래스 기반 동적 에이전트,cglib 프레임 워 크 사용.
이 방식 으로 만 든 프 록 시 대상 은 대상 의 하위 클래스 대상 입 니 다.
두 번 째 방식 은 제3자 jar 패 키 지 를 이용 하여 CGLIB 패 키 지 를 다운로드 하 는 것 입 니 다.

jar 패키지 의 Enhancer 클래스 를 이용 하여 증강 대상 을 만 듭 니 다.
증강 대상 을 만 들 려 면 원래 대상 의 클래스 이름 에 따라 클래스 증강 기 를 만 들 고 원래 대상 의 유형 에 따라 하위 프 록 시 대상 을 만들어 야 합 니 다.
속성 은 증강 대상 set 방법 을 통 해 값 을 부여 합 니 다.이전 방식 은 호출 방법 Proxy.newProxy Instance 를 통 해 전 참 됩 니 다.

public void test3(){

  //           
  BookSerice bookSerice = new BookSericeImpl();
  Enhancer enhancer = new Enhancer();
  //            
  enhancer.setClassLoader(bookSerice.getClass().getClassLoader());

  //                 ,              
  enhancer.setSuperclass(bookSerice.getClass());

  //      ,        Callback     ,              .
  enhancer.setCallback(new TimeMethodInterceptor(bookSerice));
  //          
  bookSerice = (BookSerice) enhancer.create();
  bookSerice.addOne(new BokBean());
  bookSerice.deletOne(1l);
  
 }
Callback 인터페이스의 실현 클래스,즉 기능 강화 부분 을 만 듭 니 다.
이 부분 은 첫 번 째 방식 의 실현 과 마찬가지 로 반 사 를 통 해 기능 을 추가 하 는 과정 에서 원래 의 방법 을 호출 하 는 것 이다.

//Callback        ,             
public class TimeMethodInterceptor implements MethodInterceptor {

 private Object target;

 public TimeMethodInterceptor(Object target) {
  this.target = target;
 }

 @Override
 public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
  //        
  //      1970 1 1  0 0        
  long start = System.currentTimeMillis();
  Object value = method.invoke(target, objects);
  long time = System.currentTimeMillis() - start;
  System.out.println("    "+time+"  ");
  return null;
 }
}
요약:
두 가지 방법의 차이:
첫 번 째 는 jdk 내부 방법 으로 프 록 시 대상 을 만 드 는 것 입 니 다.생 성 과정 에서 대상 의 인터페이스 가 필요 하기 때문에 인터페이스 류 가 있 는 대상 에 게 만 프 록 시 를 할 수 있 습 니 다.
두 번 째 는 제3자 jar 패키지 의 인 텐 시파 이 어(Enhancer)를 이용 하여 프 록 시 대상 을 만 들 고 set 방법 으로 필요 한 속성 값 을 부여 합 니 다.인터페이스 가 없 기 때문에 대상 의 하위 프 록 시 대상 을 만 듭 니 다.

좋은 웹페이지 즐겨찾기