wannaqueen
  • Initial page
  • Spring boot
    • 스프링부트의 소개
      • 8. 스프링 부트 소개 by ks
      • 9. 시스템 요구사항 by ks
      • 10. 스프링 부트 설치 by ks
      • 11. 첫 번째 Spring Boot 애플리케이션 개발하기 by ys
        • 11.1 POM 만들기
        • 11.2 클래스 패스 의존성 추가하기
        • 11.3 코드 작성하기
        • 11.4 예제 실행하기
        • 11.5 실행 가능한 jar 만들기
      • 12. 다음에 읽을 내용 by ys
      • 13. 빌드 시스템 by sh
        • 13.1 의존성 관리
        • 13.2 Maven
        • 13.3 Gradle
        • 13.4 Ant
        • 13.5 Starters
    • 스프링부트의 기능
      • 23. Spring Application by ys
        • 23.1 startup 실패
        • 23.2 배너를 내가 원하는 대로 바꾸기
        • 23.3 SpringApplication 커스터마이징하기
        • 23.4 Fluent Builder API
        • 23.5 어플리케이션 이벤트와 리스너들
        • 23.6 웹 환경
        • 23.7 Application 인자에 접근하기
        • 23.8 ApplicationRunner 또는 CommandLineRunner 사용
        • 23.9 어플리케이션 종료
        • 23.10 관리자 기능
      • 24. 외부화된 구성 by ys
        • 24.1 임의의 값 구성
        • 24.2 명령행 특성 액세스
        • 24.3 응용 프로그램 속성 파일
        • 24.4 프로파일 관련 프라퍼티들
        • 24.5 프라퍼티들에서 플레이스홀더들
        • 24.6 속성의 암호화
        • 24.7 속성대신 yaml 사용하기 - 다시
        • 24.8 Type-safe Configuration Properties
      • 25. 프로파일 by ks
        • 25.1 Active 프로파일 더하기
        • 25.2 프로그램적으로 프로파일 세팅
        • 25.3 프로파일 별 구성파일
      • 26. 로깅 by ks
        • 26.1 로그 형식
        • 26.2 콘솔 출력
        • 26.3 파일 출력
        • 26.4 로거 레벨
        • 26.5 로그 그룹
        • 26.6 사용자 정의 로그 설정
        • 26.7 로그백 확장
      • 27 국제화 by ks
      • 28. SQL 데이터베이스 작업 by sh
      • 29. NoSQL 기술 사용 by sh
      • 30. 메시징 by sh
      • 31. 이메일 전송 by sh
      • 28. JSON by sh (다시 시작!)
        • 28.1 Jackson
        • 28.2 Gson
        • 28.3 JSON-B
      • 29. 웹 응용 프로그램 개발 by sh
        • 29.1 The “Spring Web MVC Framework”
        • 29.2 The “Spring WebFlux Framework”
        • 29.3 JAX-RS and Jersey
        • 29.4 내장된 서블릿 컨테이너 지원
        • 29.5 내장된 반응형 서버 지원
        • 29.6 반응형 서버 리소스 구성
      • 30. Security by ys
        • 30.1 MVC 보안
        • 30.2 WebFlux 보안
        • 30.3 OAuth2
        • 30.4 Actuator 보안
      • 31. SQL 데이터베이스 작업 by ys
        • 31.1 Configure a DataSource
        • 31.2 JdbcTemplate 사용
        • 31.3 JPA와 스프링 데이터 JPA
        • 31.4 스프링 데이터 JDBC
        • 31.5 H2의 웹 콘솔 사용
        • 31.6 jOOQ 사용하기
      • 32. NoSQL 기술로 작업하기 by ks
      • 33 Caching by ks
      • 34. 메시징
        • 34.1 JMS by sh
        • 34.2 AMQP by sh
        • 34.3 Apache Kafka Support by ys
      • 35.REST 서비스 호출 RestTemplate
        • 35.1 RestTemplate 사용자 정의
      • 36. REST 서비스 호출 WebClient by ys
      • 37. 유효성 확인 by ys
      • 38. 이메일 보내기 by ys
      • 39. JTA를 이용한 분산 트랜잭션 by ys
      • 40.하젤캐스트(Hazelcast) by ys
      • 41. Quartz Scheduler by ys
      • 42. 작업 실행 및 스케줄링 by ys
      • 43. 스프링 통합 by ys
      • 44. Spring 세션 by ys
      • 45. JMX를 통한 모니터링 및 관리 by ys
      • 46. Testing by sh
        • 46.3 Testing Spring Boot Applications
          • 46.1~46.3.10
          • 46.3.11 자동 구성된 Spring WebFlux 테스트
          • 46.3.12 자동 구성된 Data JPA 테스트들
          • 46.3.13 자동 구성된 JDBC 테스트들
          • 46.3.14 자동 구성된 Data JDBC 테스트들
          • 46.3.15 자동 구성된 JOOQ 테스트들
          • 46.3.16 자동 구성된 Data MongoDB 테스트들
          • 46.3.17 자동 구성된 Data Neo4j 테스트
          • 46.3.18 자동 구성된 Data Redis 테스트들
          • 46.3.19 자동 구성된 Data LDAP 테스트들
          • 46.3.20 자동 구성된 REST 클라이언트
          • 46.3.21자동 구성된 Spring REST Docs 테스트
          • 46.3.22 추가적인 자동 구성 및 슬라이스
          • 46.3.23 사용자 구성 및 분할
          • 46.3.24 Spock을 사용하여 스프링 부팅 응용 프로그램 테스트
      • 47. 웹 소켓 by sh
      • 48. 웹 서비스 by sh
        • 48.1WebServiceTemplate로 웹 서비스 호출하기
      • 49. 자신만의 자동 구성 생성
        • 49.1 자동 구성된 빈 이해하기 by sh
        • 49.2 자동 구성 후보 찾기 by sh
        • 49.3 Condition 어노테이션들 by sh
        • 49.4 자동구성 테스팅 by ks
        • 49.5 자신만의 스타터 생성하기 by ks
      • 50. Kotlin support by ys
      • 51. What to Read Next by ys
      • 52. Production-ready 기능 활성화 by ys
      • 53. Endpoints
        • 53.1 엔드 포인트 활성화 by ys
        • 53.2 엔드 포인트 노출 by ys
        • 53.3 HTTP endpoints 보안 by ys
        • 53.4 Endpoints 구성
        • 53.5 액츄에이터 웹 엔드 포인트 용 하이퍼 미디어 by ys
        • 53.6 CORS 지원 by ys
        • 53.7 커스텀 엔드포인트 확장 by ks
        • 53.8 Health 정보 by ks
        • 53.9 어플리케이션 정보 by sh
      • 54. HTTP를 통한 모니터링 및 관리 by sh
        • 54.1 관리 엔드 포인트 경로 사용자 정의
        • 54.2 관리 서버 포트 사용자 정의
        • 54.3 관리 관련 SSL 구성
        • 54.4 관리 서버 주소 사용자 정의
        • 54.5 HTTP 끝점 사용안하기
  • spring 5.0
    • 1. IoC 컨테이너
      • 1.1 스프링 IoC 컨테이너와 빈의 도입 by sh
      • 1.2 컨테이너 by ys
      • 1.3 빈 개요 by ks
      • 1.4 의존성 by ks, ys, sh
        • 1.4.1 의존성 주입 by ks
        • 1.4.2 의존성과 configuration by ks
        • 1.4.3 depends-on 사용 by ys
        • 1.4.4 게으른-초기화된 bean by ys
        • 1.4.5 Autowiring Collaborators by ys
        • 1.4.6 메소드 주입 by sh
      • 1.5. 빈의 범위 by sh
      • 1.6 빈의 특성 커스터마이징하기 by ys
        • 1.6.1 라이프 사이클 콜백
        • 1.6.2 ApplicationContextAware과BeanNameAware
        • 1.6.3 기타 Aware인터페이스
      • 1.7 빈 정의 상속by ys
        • 1.7.1 빈 정의 상속
      • 1.8 컨테이너 확장 포인트 by ks
      • 1.9 어노테이션 기반의 컨테이너 구성 by sh
      • 1.10 클래스패스 스캔 및 관리 by ys
        • 1.10.1 @Component 및 추가 스테레오 타입 어노테이션
        • 1.10.2 meta-annotation 및 composed annotation 사용
        • 1.10.3 자동으로 클래스 검색 및 Bean 정의 등록
        • 1.10.4 스캐닝을 커스터마이징 하기위해 필터를 사용
        • 1.10.5 component 내에 Bean 메타 데이터 정의
        • 1.10.6 이름으로 자동탐지되는 컴포넌트
        • 1.10.7 범위로 자동 감지되는 컴포넌트
        • 1.10.8 annotation과 함께 한정된 메타데이터 제공
        • 1.10.9 후보 component의 index 생성
      • 1.11 JSR 330 표준 어노테이션 사용하기 by sh
      • 1.12 자바 기반의 컨테이너 구성 by sh, ks
        • 1.12.1 기본 개념: @Bean 및 @Configuration by sh
        • 1.12.2 AnnotationConfigApplicationContext를 사용한 스프링 컨테이너 인스턴스화 by sh
        • 1.12.3 @Bean 사용 by ks
        • 1.12.4 @Configuration 어노테이션 by ks
        • 1.12.5 자바 기반 Configuration구성 by ks
      • 1.13 환경 추상화 by ys
        • 1.13.1 빈 정의 프로파일
        • 1.13.2 PropertySource추출
        • 1.13.3 @PropertySource 사용
        • 1.13.4 Placeholder Resolution in Statements
      • 1.14 LoadTimeWeaver 등록 by ks
      • 1.15 ApplicationContext의 부가 수용가능성들 by ks, sh
        • 1.15.1 MesageSource를 사용한 국제화 by ks
        • 1.15.2 표준과 커스텀 이벤트 by ks
        • 1.15.3 로우 레벨 리소스에 대한 편리한 접근 by sh
        • 1.15.4 웹 어플리케이션에 대한 간편한 Application 인스턴스화 by sh
        • 1.15.5 스프링 ApplicationContext를 Java EE RAR 파일로 배포하가ㅣ by sh
        • 1.15.3 Low-level 리소스로 편리한 접근
        • 1.15.4 웹 어플리케이션을 위한 편리한 ApplicationContext 인스턴스화
      • 1.16 BeanFactory by sh
    • 2. Resource by ks
      • 2.1 소개
      • 2.2 Resource interface
      • 2.3 내장 리소스 확장
      • 2.4 ResourceReader
      • 2.5 ResourceLoaderAware 인터페이스
      • 2.6 Resources 의존성
      • 2.7 어플리케이션 컨텍스트와 리소스 경로
    • 3. 유효성 검사, 데이터 바인딩 및 유형 변환 by ys, sh
      • 3.1. Spring의 Validator 인터페이스를 사용하여 유효성 검사 by ys
      • 3.2. 오류 메시지로 코드 해결 by ys
      • 3.3. bean 조작과 BeanWrapper by ys
        • 3.3.1. 기본 및 중첩 된 프로퍼티를 설정 및 가져 오기
        • 3.3.2. 내장 된 PropertyEditor구현
      • 3.4 스프링 타입 변환 by sh
        • 3.4.1 Converter SPI
        • 3.4.2 ConverterFactory 사용하기
        • 3.4.3 GenericConverter 사용하기
        • 3.4.4 ConversionService API
        • 3.4.5 ConversionService 구성
        • 3.4.6 프로그래밍 방식으로 ConversionService 사용하기
      • 3.5 스프링 필드 포맷팅 by sh
        • 3.5.1 Formatter SPI
        • 3.5.2 Annotation 기반의 포맷팅
        • 3.5.3 FormatterRegistry SPI
        • 3.5.4 FormatterRegistrar SPI
        • 3.5.5 스프링 MVC에서 포맷팅 구성하기
      • 3.6 전역 Date and Time 포맷 구성 by sh
      • 3.7 스프링 유효성 검사 by sh
        • 3.7.1 by sh
        • 3.7.2 by sh
        • 3.7.3 by sh
    • 4 스프링 표현식 언어 (SpEL)
      • 4.1 평가 by sh
      • 4.2 빈 정의에 있는 표현식 by sh
      • 4.3 Language Reference
        • 4.3.1 리터럴 표현식 by ys
        • 4.3.2 프로퍼티,배열,목록,지도 및 인덱서 by ys
        • 4.3.3 인라인 목록 by ys
        • 4.3.4 인라인 Maps by ys
        • 4.3.5 배열 구성 by ys
        • 4.3.6 행동 양식 by ys
        • 4.3.7 연산자 by ys
        • 4.3.8 유형 by ys
        • 4.3.9 생성자 by ys
        • 4.3.10 변수 by ks
        • 4.3.11 함수 by ks
        • 4.3.12 빈 참조 by ks
        • 4.3.13 삼항 연산자 (If-Then-Else) by ks
        • 4.3.14 엘비스 연산자 by ks
        • 4.3.15 안전한 네비게이션 연산자 by ks
        • 4.3.16 컬렉션 셀렉션 by ks
        • 4.3.17 컬렉션 프로젝션 by ks
        • 4.3.18 표현 템플릿 by ks
    • 5 spring을 이용한 aspect 지향 프로그래밍
      • 5.1 AOP 개념 by ys
      • 5.2 Spring AOP 기능 및 목표 by ys
      • 5.3 AOP 프록시 by ys
      • 5.4 @AspectJ 지원 by ys,ks
        • 5.4.1 @AspectJ 지원 활성화 by ys
        • 5.4.2 Aspect 선언하기 by ys
        • 5.4.3 Pointcut 선언하기 by ys
        • 5.4.4 Advice 선언 by ks
        • 5.4.5 소개 by ks
        • 5.4.6 Aspect 초기화 모델 by ks
        • 5.4.7 AOP 예제 by ks
      • 5.5 스키마 기반 AOP 지원 by sh
        • 5.5.1 Aspect 선언 by sh
        • 5.5.2 Pointcut 선언 by sh
        • 5.5.3 Advice 선언 by sh
        • 5.5.4 인트로덕션 by sh
        • 5.5.5 Aspect 인스턴스화 모델 by sh
        • 5.5.6 Advisors by sh
        • 5.5.7 AOP 스키마 예제 by sh
    • 6 Spring AOP API
      • 6.1 Spring의 Pointcut API
        • 6.1.1 개념들 by ys
        • 6.1.2 Pointcuts에 대한 작업 by ys
        • 6.1.3 AspectJ Expression Pointcuts by ys
        • 6.1.4 편리한 Pointcut 구현 by ys
        • 6.1.5 포인트 컷 수퍼 클래스 by ys
        • 6.1.6. 사용자 정의 Pointcut by ys
      • 6.2 Spring의 Advice API
        • 6.2.1. 조언 라이프 사이클 by ys
        • 6.2.2 Spring의 advice 유형 by ys
      • 6.3 Spring의 Advisor API by ks
      • 6.4 ProxyFactoryBean을 사용해서 AOP 프록시 생성 by ks
        • 6.4.1 기본
        • 6.4.2 자바빈 프로퍼티
        • 6.4.3 JDK 및 CGLIB 기반 프록시
        • 6.4.4 프록시 인터페이스
        • 6.4 5 프록시 클래스
        • 6.4.6 "Global" advisor 사용
      • 6.5 간결한 프록시 정의 by sh
      • 6.6 ProxyFactory를 사용하여 프로그래밍 방식으로 AOP 프록시 만들기 by sh
      • 6.7 Advised 객체들 조작하기 by sh
      • 6.8 "자동 프록시" 기능 사용 by sh
      • 6.9 TargetSource구현체 사용하기 by sh
      • 6.10 새로운 Advice 타입 정의하기 by sh
    • 7. 데이터 버퍼와 코덱 by ks
Powered by GitBook
On this page

Was this helpful?

  1. spring 5.0
  2. 6 Spring AOP API
  3. 6.2 Spring의 Advice API

6.2.2 Spring의 advice 유형 by ys

Previous6.2.1. 조언 라이프 사이클 by ysNext6.3 Spring의 Advisor API by ks

Last updated 6 years ago

Was this helpful?

Spring은 여러 가지 advice 타입을 제공하며 임의의 advice 타입을 지원하기 위해 확장 가능하다. 이 절에서는 기본 개념과 표준 조언 유형에 대해 설명합니다.

interception around advice

Spring에서 가장 근본적인 조언 유형은 interception around advice입니다.

스프링은 메서드 인터셉션을 사용해서 around advice의 AOP Alliance interface와 호환성이 있다. around advice를 구현한 MethodInterceptor는 다음 인터페이스를 구현해야 한다.

public interface MethodInterceptor extends Interceptor {

    Object invoke(MethodInvocation invocation) throws Throwable;
}

invoke()메서드의 MethodInvocation 인자는 호출되는 메서드, 대상 조인 포인트, AOP 프록시, 메서드의 인자를 노출한다.invoke()메서드는 호출의 결과(조인포인트(join point)의 반환값)를 반환해야 한다.

다음 예제는 간단한 MethodInterceptor구현을 보여줍니다 .

public class DebugInterceptor implements MethodInterceptor {

    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("Before: invocation=[" + invocation + "]");
        Object rval = invocation.proceed();
        System.out.println("Invocation returned");
        return rval;
    }
}

MethodInvocation의 proceed() 메서드의 호출을 봐라. 이는 인터셉터 체인을 따라 조인포인트로 진행한다. 대부분의 인터셉터는 이 메서드를 호출하고 그 반환 값을 반환할 것이다. 하지만 다른 around advice처럼 MethodInterceptor는 다른 값을 반환하거나 proceed 메서드를 호출하지 않고 예외를 던질 수 있다. 그렇지만 그럴듯한 이유가 없다면 이렇게 할 이유가 없다!

NOTE

MethodInterceptor는 다른 AOP Alliance 호환 AOP 구현체와 상호운용성이 있다. 이번 장의 뒷부분에 나오는 어드바이스 타입들은 공통의 AOP 개념을 구현했지만, 스프링에 특화된 방법으로 구현했다. 가장 구체적인 어드바이스 타입을 사용하는 이점을 누리면서 다른 AOP 프레임워크의 관점을 사용하고자 한다면 MethodInterceptor around advice를 사용해라. 포인트컷은 현재 프레임워크간의 상호운용성이 없고 AOP Alliance는 포인트컷 인터페이스를 정의하지 않았다.

Before advice

더 간단한 어드바이스 타입은 before advice다. 이는 메서드에 진입하기 전에만 호출되므로 MethodInvocation 객체가 필요없다.

before advice의 주요 이점은 proceed() 메서드를 호출할 필요가 없으므로 인터셉터 체인을 따라가다가 실패할 가능성이 없다는 점이다.

MethodBeforeAdvice 인터페이스가 아래 나와 있다.

public interface MethodBeforeAdvice extends BeforeAdvice {

    void before(Method m, Object[] args, Object target) throws Throwable;
}

(일반적인 객체가 필드 가로채기를 할 수 있고 스프링이 이를 구현할 것 같지는 않지만, Spring의 API 디자인은 필드 before advice를 허용 할 것이다.)

반환타입은 void이다. before advice는 조인포인트를 실행하기 전에 임의의 동작을 추가할 수 있지만 반환 값은 바꿀 수 없다. before advice가 예외를 던지면 인터셉터 체인을 추가로 실행하지 않는다. 예외는 인터셉터 체인을 다시 전파합니다. 예외가 unchecked 예외이면(아니면 호출된 메서드의 시그니처에서) 클라이언트에게 직접 전달될 것이다. 그렇지 않으면 unchecked 예외에서 AOP 프락시가 감쌀 것이다.

다음은 스프링에서 모든 메서드의 호출 횟수를 세는 before advice 예시이다.

public class CountingBeforeAdvice implements MethodBeforeAdvice {

    private int count;

    public void before(Method m, Object[] args, Object target) throws Throwable {
        ++count;
    }

    public int getCount() {
        return count;
    }
}

TIP

before advice를 어떤 포인트컷과도 사용할 수 있다.

Throws advice

Throws advice는 조인 포인트가 예외를 던지면 조인포인트의 반환 후에 호출된다. 스프링은 타입이 있는 throws advice를 제공한다. 이는 org.springframework.aop.ThrowsAdvice인터페이스가 아무런 메서드도 가지지 않는 다는 것을 의미한다. 주어진 객체가 하나 이상의 타입이 있는 throws advice 메서드를 구현했는지 구별하는 태그 인터페이스이다. 이는 다음과 같은 형식이 되어야 한다.

afterThrowing([Method, args, target], subclassOfThrowable)

마지막 인자만 필수값이다. 어드바이스 메서드가 메서드와 인자에 관심있냐에 따라 메서드 시그니처는 한 인자나 네 개의 인자를 가질 수 있다. 다음 클래스는 throws advice의 예시이다.

RemoteException가 던져질 때(하위 클래스를 포함해서) 아래 어드바이스를 호출한다.

public class RemoteThrowsAdvice implements ThrowsAdvice {

    public void afterThrowing(RemoteException ex) throws Throwable {
        // Do something with remote exception
    }
}

ServletException가 던져질 때 다음 어드바이스를 호출한다. 앞의 어드바이스와는 달리 4개의 인자를 선언했으므로 호출한 메서드, 메서드 인자, 대상 객체에 접근한다

public class ServletThrowsAdviceWithArguments implements ThrowsAdvice {

    public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
        // Do something with all arguments
    }
}

마지막 예제에서 RemoteException와 ServletException를 모두 처리하는 한 클래스에서 이 두 메서드를 어떻게 사용할 수 있는지 설명한다. 하나의 클래스에 다수의 throws advice 메서드를 합칠 수 있다.

public static class CombinedThrowsAdvice implements ThrowsAdvice {

    public void afterThrowing(RemoteException ex) throws Throwable {
        // Do something with remote exception
    }

    public void afterThrowing(Method m, Object[] args, Object target, ServletException ex) {
        // Do something with all arguments
    }
}

NOTE

throws advice 메서드가 예외를 던진다면 원래의 예외를 오버라이드할 것이다.(예: 사용자에게 던지는 예외를 바꾼다.) 보통 오버라이딩된 예외는 RuntimeException가 될 것이고 이는 어떤 메서드 시그니처와도 호환성을 가진다. 하지만 throws advice 메서드가 체크드 예외를 던진다면 대상 메서드에서 선언된 예외와 일치해야 하므로 특정 대상 메서드 시그니처와 결합이 생길 것이다. 대상 메서드 시그니처와 호환되지 않고 선언되지 않은 체크드 예외를 던지지 마라!

TIP

Throws advice는 임의의 pointcut과 함께 사용될 수 있습니다.

After Returning advice

Spring에서 after returning advice는 다음 목록과 같은 org.springframework.aop.AfterReturningAdvice인터페이스 를 구현해야한다 .

public interface AfterReturningAdvice extends Advice {

    void afterReturning(Object returnValue, Method m, Object[] args, Object target)
            throws Throwable;
}

after returning advice는 리턴 값 (수정할 수없는), 호출 된 메소드, 메소드의 인수 및 대상에 대한 액세스 권한을가집니다.

다음 after returning advice는 예외를 던지지 않고 성공적으로 이뤄진 모든 메서드 호출의 횟수를 센다.

public class CountingAfterReturningAdvice implements AfterReturningAdvice {

    private int count;

    public void afterReturning(Object returnValue, Method m, Object[] args, Object target)
            throws Throwable {
        ++count;
    }

    public int getCount() {
        return count;
    }
}

이 어드바이스는 실행경로를 바꾸지 않는다. 이 어드바이스가 예외를 던진다면 값을 반환하는 대신 인터셉터 체인에 예외를 던질 것이다.

TIP

After returning advice는 어떤 포인트컷과도 사용할 수 있다.

인트로덕션(introduction) 어드바이스

스프링은 introduction advice를 특별한 종류의 인터셉트 어드바이스로 다룬다.

Introduction은 IntroductionAdvisor와 다음 인터페이스를 구현하는 IntroductionInterceptor를 필요로 한다.

public interface IntroductionInterceptor extends MethodInterceptor {

    boolean implementsInterface(Class intf);
}

AOP Alliance MethodInterceptor 인터페이스에서 상속받은 invoke()메서드는 introduction을 반드시 구현해야 한다. 이 말은 호출된 메서드가 인트로덕션이 적용된 인터페이스에 있을 때 인트로덕션 인터셉터가 메서드 호출을 다루게 된다는 의미이다. 이는 proceed()를 호출할 수 없다.

인트로덕션 어드바이스는 어떤 포인트컷과도 사용할 없고 메서드가 아니라 클래스 수준에만 적용된다. 인트로덕션 어드바이스는 다음 메서드를 가지는 IntroductionAdvisor만 함께 사용할 수 있다.

public interface IntroductionAdvisor extends Advisor, IntroductionInfo {

    ClassFilter getClassFilter();

    void validateInterfaces() throws IllegalArgumentException;
}

public interface IntroductionInfo {

    Class[] getInterfaces();
}

MethodMatcher가 없으므로 인트로덕션 어드바이스와 관련된 Pointcut도 없다. 클래스 필터링만 적합하다.

getInterfaces() 메서드는 이 어드바이저가 인트로덕션한 인터페이스를 반환한다.

구성한 IntroductionInterceptor가 구현할 수 있는 인트로덕션이 된 인터페이스인지 아닌지를 보기 위해 내부적으로 validateInterfaces() 메서드를 사용한다.

스프링 테스트 슈트의 간단한 예시를 보자. 다음 인터페이스를 하나 이상의 객체에 인트로덕션하려고 한다고 가정해보자.

public interface Lockable {
    void lock();
    void unlock();
    boolean locked();
}

이는 mixin을 설명한다. 어드바이즈가 적용된 객체를 Lockable(류의 타입)로 캐스팅해서 lock, unlock 메서드를 호출할 수 있기를 원한다. lock()메서드를 호출하면 모든 setter 메서드가 LockedException를 던지기를 원한다. 그래서 객체에 대해서 전혀 모르더라도 객체를 불변상태로 만들 수 있는 관점을 추가할 수 있다. 이는 AOP의 좋은 예시이다.

우선, 무거운 작업을 하는 IntroductionInterceptor가 필요할 것이다. 이 경우 간편한 org.springframework.aop.support.DelegatingIntroductionInterceptor 클래스를 확장한다. IntroductionInterceptor를 직접 구현할 수도 있지만, 대부분의 경우 DelegatingIntroductionInterceptor를 사용하는 것이 최상의 선택이다.

DelegatingIntroductionInterceptor는 인트로덕션이 된 인터페이스의 실제 구현체에 인트로덕션을 위임하도록 설계되어서 인터셉션의 사용은 감추면서 생성자 인자로 어떤 객체에도 위임을 설정할 수 있다. 이것이 기본적인 위임(인자가 없는 생성자를 사용하는 경우)이다. 그래서 아래 예제에서 위임은 DelegatingIntroductionInterceptor의 하위클래스인 LockMixin이다. 해당 위임(기본 위임)인 DelegatingIntroductionInterceptor 인스턴스는 위임(IntroductionInterceptor)으로 구현된 모든 인터페이스를 찾고 이 인터페이스에 인트로덕션을 지원할 것이다. LockMixin같은 하위클래스가 노출되면 안되는 인터페이스를 감추도록 suppressInterface(Class intf) 메서드를 호출하게 하는 것이 가능하다. 하지만 IntroductionInterceptor가 얼마나 많은 인터페이스를 지원할 준비가 되었는 지와는 관계없이 사용한 IntroductionAdvisor가 실제로 노출되는 인터페이스를 제어할 것이다. 인트로덕션이 된 인터페이스는 같은 인터페이스의 모든 구현체를 대상한테서 감출 것이다.

LockMixin는 DelegatingIntroductionInterceptor를 서브클래스화 하고 Lockable를 구현한다. 슈퍼클래스는 인트로덕션으로 지원할 수 있는 Lockable을 자동으로 선택하므로 지정할 필요가 없다. 이 방법으로 다수의 인터페이스를 인트로듀스할 수 있다.

locked인스턴스 변수 의 사용에 유의하십시오 . 이것은 효과적으로 대상 객체에있는 상태에 추가 상태를 추가합니다.

다음 예제에서는 예제 LockMixin클래스 를 보여줍니다 .

public class LockMixin extends DelegatingIntroductionInterceptor implements Lockable {

    private boolean locked;

    public void lock() {
        this.locked = true;
    }

    public void unlock() {
        this.locked = false;
    }

    public boolean locked() {
        return this.locked;
    }

    public Object invoke(MethodInvocation invocation) throws Throwable {
        if (locked() && invocation.getMethod().getName().indexOf("set") == 0) {
            throw new LockedException();
        }
        return super.invoke(invocation);
    }

}

때로는 invoke() 메서드를 오버라이드 할 필요가 없다. DelegatingIntroductionInterceptor 구현체(메서드가 인트로듀스되었다면 delegate (위임) 메서드를 호출하고 인트로유스되지 않았다면 조인포인트로 진행한다.)로 보통은 충분하다. 이 경우에 locked 모드라면 호출할 수 있는 setter 메서드가 없다는 것을 추가로 확인해야 한다.

필요한 인트로덕션 어드바이저는 간단한데 별도의 LockMixin 인스턴스를 보관하고 인트로듀스된 인터페이스(여기서는 Lockable이다)를 지정하는 것이 해야하는 전부이다. 더 복잡한 예시에서는 인트로덕션 인터셉터(prototype으로 정의될 것이다.)를 참조해야 할 수도 있다. 여기서는 LockMixin과 관련된 설정이 없으므로 new로 생성한다.

다음 예제는 우리 LockMixinAdvisor클래스 를 보여줍니다 :

public class LockMixinAdvisor extends DefaultIntroductionAdvisor {

    public LockMixinAdvisor() {
        super(new LockMixin(), Lockable.class);
    }
}

이 어드바이저를 아주 간단히 적용할 수 있는데 필요한 설정이 없다.(하지만 이는 필수적인데 IntroductionAdvisor없이 IntroductionInterceptor는 사용할 수 없다.) 일반적으로 인트로덕션을 사용할 때처럼 어드바이저는 상태를 가져야 하므로 인스터스마다 존재해야 한다. 다른 LockMixinAdvisor 인스턴스가 필요하므로 어드바이즈된 객체마다 LockMixin가 필요하다. 이 어드바이저가 어드바이즈된 객체의 상태를 구성한다.

다른 어드바이저처럼 Advised.addAdvisor()메서드나 XML 설정(권장하는 방법)을 사용해서 이 어드바이저를 프로그래밍으로 적용할 수 있다. 이후에 나오는 모든 프락시 생성방법("auto proxy creators"를 포함해서)은 인트로덕션과 상태를 가진 믹스인을 제대로 다룬다.