Spring 의 사무 관리 난점 분석 (6): 특수 한 방법 으로 그물 에서 빠 진 물고기 가 된다.

7094 단어 spring사무 관리
더 읽 기
어떤 방법 으로 Spring AOP 사 무 를 실시 할 수 없 습 니까?
   Spring 사무 관 리 는 인터페이스 에이전트 나 동적 바이트 코드 기술 을 바탕 으로 AOP 를 통 해 업 무 를 강화 합 니 다.Spring 은 또한 AspectJ LTW 가 클래스 로드 기간 에 강 화 를 실시 하 는 것 을 지원 하지만 이런 방법 은 거의 사용 되 지 않 기 때문에 우 리 는 주목 하지 않 는 다.
    인터페이스 동적 대 리 를 바탕 으로 하 는 AOP 사무 강화 에 있어 인터페이스의 방법 은 모두 Public 이기 때문에 실현 류 의 실현 방법 도 반드시 Public (proctected, private 등 이 아 닌) 이 어야 하 며 static 의 장식 자 를 사용 할 수 없습니다.따라서 인터페이스 동적 대 리 를 실시 할 수 있 는 방법 은 'Public' 또는 'Public final' 수식 자 를 사용 하 는 방법 일 수 밖 에 없다. 다른 방법 은 동적 대 리 를 받 을 수 없고 그 에 상응하는 AOP 강 화 를 실시 할 수 없다. 다시 말 하면 Spring 사 무 를 강화 할 수 없다 는 것 이다.
    CGLib 바이트 코드 동적 에이 전 트 를 기반 으로 하 는 방안 은 피 증강 클래스 를 확장 하고 하위 클래스 를 동적 으로 만 드 는 방식 으로 AOP 증강 식 입 을 하 는 것 이다.final, static, private 수식 자 를 사용 하 는 방법 은 하위 클래스 에 덮어 쓸 수 없 기 때문에 이에 따라 AOP 강 화 를 실시 할 수 없습니다.따라서 방법 서명 은 이러한 수정자 의 사용 에 특히 주의해 야 하 며, 방법 이 부주의 로 사무 관리의 그물 에서 빠 진 물고기 가 되 지 않도록 해 야 한다.
트 랜 잭 션 강화 누락 사례
   이 절 에서 저 희 는 구체 적 인 실례 를 통 해 CGLib 바이트 코드 동적 에이 전 트 를 바탕 으로 Spring AOP 업무 의 강 화 를 누 릴 수 없 는 특수 한 방법 을 설명 합 니 다.
  
package com.baobaotao.special;
import org.springframework.stereotype.Service;
@Service("userService")
public class UserService {

    //① private          ,       
    private void method1() {
        System.out.println("method1");
    }

    //② final         
    public final void method2() {
        System.out.println("method2");
    }

    //③ static       ,       
    public static void method3() {
        System.out.println("method3");
    }

    //④ public         ,            
    public void method4() {
        System.out.println("method4");
    } 
}

   Spring 은 CGLib 동적 에이전트 기술 을 통 해 UserService Bean 에 대해 AOP 사무 강화 의 관건 적 인 설정 을 실시 합 니 다. 구체 적 으로 다음 과 같 습 니 다.


        
        
        
    
    
        
            
        
    

   ① 에서 저 희 는 proxy - target - class = "true" 디 스 플레이 를 통 해 CGLib 동적 프 록 시 기술 을 사용 하고 ② 에서 AspjectJ 절 점 표현 식 을 통 해 UserService 의 모든 방법 을 표현 하 며 UserService 의 모든 방법 에 Spring AOP 사무 강 화 를 실시 하고 자 합 니 다.
   UserService 에 실행 가능 한 방법 을 추가 합 니 다. 다음 과 같 습 니 다.
package com.baobaotao.special;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;

@Service("userService")
public class UserService {
    …
    public static void main(String[] args) {
        ApplicationContext ctx = 
             new ClassPathXmlApplicationContext("user/special/applicationContext.xml");
        UserService service = (UserService) ctx.getBean("userService");

        System.out.println("before method1");
        service.method1();
        System.out.println("after method1");

        System.out.println("before method2");
        service.method2();
        System.out.println("after method2");

        System.out.println("before method3");
        service.method3();
        System.out.println("after method3");

        System.out.println("before method4");
        service.method4();
        System.out.println("after method4");

    }
}

   UserService 를 실행 하기 전에 Log4J 로그 단 계 를 DEBUG 로 설정 하고 상기 코드 를 실행 하여 출력 로 그 를 봅 니 다. 다음 과 같 습 니 다.
인용 하 다.
① 트 랜 잭 션 을 사용 하지 않 음
before method1
in method1
after method1
② 트 랜 잭 션 을 사용 하지 않 음
before method2
in method2
after method2
③ 트 랜 잭 션 을 사용 하지 않 음
before method3
in method3
after method3
④ 트 랜 잭 션 사용
before method4
Creating new transaction with name [com.baobaotao.special.UserService.method4]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

in method4
Initiating transaction commit
Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver]
Releasing JDBC Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver] after transaction
Returning JDBC Connection to DataSource
after method4
⑤ 미사 용
before method5
in method5
after method5
⑥ 트 랜 잭 션 사용
before method6
Creating new transaction with name [com.baobaotao.special.UserService.method6]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT

in method6
Initiating transaction commit
Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost, MySQL-AB JDBC Driver]

after method6
  이상 의 출력 로 그 를 관찰 하면 method 1 ~ method 3 및 method 5 라 는 네 가지 방법 이 모두 Spring 의 트 랜 잭 션 강화 되 지 않 았 고 method 4 와 method 6 는 트 랜 잭 션 강화 되 었 음 을 쉽게 발견 할 수 있 습 니 다.이 결 과 는 우리 앞의 논술 을 검증 하 였 다.
  우 리 는 다음 표를 통 해 어떤 특수 한 방법 이 Spring AOP 업무 강화 의 그물 에서 벗 어 나 는 물고기 가 될 지 설명 한다.
순서.    번호.
동적 에이전트 정책
트 랜 잭 션 에 의 해 강화 되 지 않 는 방법
1
인터페이스 기반 동적 에이전트
Public 를 제외 한 모든 방법, 그 밖 에 Public static 도 강화 되 지 않 습 니 다.
2
CGLib 기반 동적 에이전트
private, static, final 방법
   그러나 특히 스프링 사무 에 의 해 강화 되 지 못 하 는 특수 한 방법 은 업무 환경 에서 일 하지 않 는 것 이 아니 라 는 점 을 지적 해 야 한다.외부 트 랜 잭 션 방법 에 의 해 호출 되 기만 하면 Spring 트 랜 잭 션 관리의 전파 단계 로 인해 내부 방법 도 외부 방법 으로 시 작 된 트 랜 잭 션 컨 텍스트 에서 작 동 할 수 있 습 니 다.우 리 는 이러한 방법 들 이 Spring 에 의 해 AOP 사 무 를 강화 할 수 없다 는 것 은 이러한 방법 으로 사 무 를 시작 할 수 없 지만 외부 방법의 사무 문맥 은 여전히 이러한 방법 으로 순조롭게 전 파 될 수 있다 는 것 을 말한다.
   이러한 Spring 사무 에 의 해 강화 되 지 못 하 는 방법 과 Spring 사무 에 의 해 강화 되 는 방법 은 유일한 차이 점 은 '새로운 사 무 를 주동 적 으로 시작 할 수 있 는 지' 이다. 전 자 는 할 수 없고 후 자 는 할 수 있다.사무 전파 행위 에 있어 서 양 자 는 완전히 같 고 전자 도 후자 와 마찬가지 로 데이터 연결 의 누설 문 제 를 일 으 키 지 않 는 다.다시 말 하면 이런 '특수 한 방법' 이 사무 상하 문 이 없 는 방법 으로 호출 되면 사무 상하 문 에서 일한다.반면 트 랜 잭 션 컨 텍스트 가 있 는 방법 으로 호출 되면 트 랜 잭 션 컨 텍스트 에서 작 동 합 니 다.
   private 의 방법 은 최종 적 으로 Public 방법 에 의 해 봉 인 된 후에 외부 호출 에 개방 되 기 때문에 Public 방법 은 업무 에 의 해 강 화 될 수 있 기 때문에 기본적으로 문제 가 없다.실제 개발 에서 가장 위험 을 초래 하기 쉬 운 것 은 CGLib 의 동적 대 리 를 바탕 으로 하 는 'Public static' 과 'Public final' 이라는 두 가지 특수 한 방법 이다.그 이 유 는 그 자체 가 Public 이기 때문에 외부 클래스 (예 를 들 어 웹 계층 의 Controller 류) 에 직접 호출 될 수 있 습 니 다. 호출 자가 트 랜 잭 션 컨 텍스트 가 없 으 면 이런 특수 한 방법 들 은 트 랜 잭 션 이 없 는 방식 으로 작 동 합 니 다.
주의: 상기 내용 은 에서 발췌 한 것 입 니 다.

좋은 웹페이지 즐겨찾기