[Annotation] Spring Bean Annotations
https://www.baeldung.com/spring-bean-annotations
애노테이션 시리즈 마지막~~!!
Spring 컨테이너에서 빈을 구성하는 방법
1. XML 구성을 사용하여 선언
2. 구성 클래스에서 @Bean 애노테이션 사용
3. org.springframework.stereotype 패키지 의 주석 중 하나로 클래스를 표시 (leave the rest to component scanning)
Component Scanning
Spring은 Component Scanning이 활성화된 경우 bean에 대한 패키지를 자동스캔할 수 있다
@ComponentScan은 어노테이션 구성으로 클래스를 검색할 패키지를 구성한다
// basePackages 또는 값 인수 중 하나를 사용하여 기본 패키지 이름을 직접 지정할 수 있다
@Configuration
@ComponentScan(basePackages = "com.baeldung.annotations")
class VehicleFactoryConfig {}
// basePackageClasses 인수 를 사용하여 기본 패키지의 클래스를 지정할 수 있다
@Configuration
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}
// 위의 두 인수 모두 배열이므로 각각에 대해 여러 패키지 제공이 가능하다.
// 인수 지정이 없으면 @ComponentScan 애노테이션 클래스가 있는 동일 패키지에서 스캔된다
// Java 8 반복 주석 기능을 활용하여 클래스를 여러 번 표시가 가능하다
@Configuration
@ComponentScan(basePackages = "com.baeldung.annotations")
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
class VehicleFactoryConfig {}
//@ComponentScans를 사용하여 여러 @ComponentScan 구성을 지정할 수 있다
@Configuration
@ComponentScans({
@ComponentScan(basePackages = "com.baeldung.annotations"),
@ComponentScan(basePackageClasses = VehicleFactoryConfig.class)
})
class VehicleFactoryConfig {}
XML사용시
<context:component-scan base-package="com.baeldung" />
@Component
@Component 는 클래스 수준 애노테이션으로, @Component로 주석이 달린 클래스를 자동으로 감지한다
@Component
class CarUtility {
// ...
}
기본적으로 이 클래스의 bean instandce는 소문자 이니셜을 가진 클래스와 동일하게 갖는다
can specify a different name using the optional value argument of this annotation.
@Repository , @Service , @Configuration 및 @Controller는 모두 @Component 의 메타 주석으로 동일한 bean 이름 지정 동작을 공유한다
automatically picks them up during the component scanning process.
@Repository
DAO or Repository classes usually represent the database access layer in an application, and should be annotated with @Repository
@Repository
class VehicleRepository {
// ...
}
이 애노테이션은 자동 지속성 예외 변환이 활성화 되어있어, Hibernate와 같은 지속성 프레임워크를 사용 시 해당 @Repository 애노테이션 클래스 내에서 발생하는 기본 예외에 대해 자동으로 Spring의 DataAccessExeption 의 하위 클래스로 변환할 수 있다 .
예외 변환을 활성화하려면 자체 PersistenceExceptionTranslationPostProcessor 빈을 선언해야 한다
@Bean
public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
return new PersistenceExceptionTranslationPostProcessor();
}
// 대부분의 경우 자동으로 수행됨
XML구성방법
<bean class=
"org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
@Service
The business logic of an application usually resides within the service layer, so we’ll use the @Service annotation to indicate that a class belongs to that layer
@Service
public class VehicleService {
// ...
}
@Controller
@Controller is a class level annotation, which tells the Spring Framework that this class serves as a controller in Spring MVC
@Controller
public class VehicleController {
// ...
}
@Configuration
Configuration classes can contain bean definition methods annotated with @Bean
@Configuration
class VehicleFactoryConfig {
@Bean
Engine engine() {
return new Engine();
}
}
Stereotype Annotations and AOP
Spring stereotype 애노테이션을 사용하여 특정 스테레오타입의 모든 클래스를 대상으로 하는 pointcut을 생성할 수 있다
예시: DAO 계층에서 메서드의 실행 시간을 측정
@Repository 스테레오타입 을 활용하여 다음 aspect(AspectJ 주석 사용)를 생성
@Aspect
@Component
public class PerformanceAspect {
@Pointcut("within(@org.springframework.stereotype.Repository *)")
public void repositoryClassMethods() {};
@Around("repositoryClassMethods()")
public Object measureMethodExecutionTime(ProceedingJoinPoint joinPoint)
throws Throwable {
long start = System.nanoTime();
Object returnValue = joinPoint.proceed();
long end = System.nanoTime();
String methodName = joinPoint.getSignature().getName();
System.out.println(
"Execution of " + methodName + " took " +
TimeUnit.NANOSECONDS.toMillis(end - start) + " ms");
return returnValue;
}
}
@Repository 주석 이 달린 클래스의 모든 메서드와 일치하는 포인트컷을 생성했다 .
@Around 어드바이스를 사용하여 해당 포인트컷을 대상으로 지정하고 인터셉트된 메서드 호출의 실행 시간을 정한다.
이 접근 방식을 사용하여 각 애플리케이션 계층에 로깅, 성능 관리, 감사 및 기타 동작을 추가할 수 있다
https://github.com/eugenp/tutorials/tree/master/spring-boot-modules/spring-boot-annotations