spring의 핵심하면 떠오르는 그림이 있을 거 같다.
난 밑의 그림이 떠오른다.
삼각형 !!
여기에서 가장 중요한 특성을 뽑으라고 하면
난 IOC/DI 와 AOP라고 생각한다.
IOC : 제어 역전 원칙
주체가 사용자에게 있는 게 아닌, 스프링에게 있다.
즉, 난 내 비즈니스 로직만 신경쓰면 된다는 뜻이다.
DI는 위 링크를 참고하자 !
그럼 AOP는 뭘까 ??
@Configuration
public class HeroesConfig {
@Bean
public IronMan ironMan() {
return new IronMan("토니 스타크");
}
@Bean
public Hulk hulk() {
return new Hulk();
}
@Bean
public HulkBuster hulkBuster() {
return new HulkBuster();
}
@Bean
public Avengers avengers() {
Avengers a = new Avengers(ironMan(), hulk());
a.setHulk(hulk()); // aop 개입
a.setName("뉴욕");
return a;
}
}
config 파일에서 보면
conponent scan으로 bean을 싱글톤으로 등록한다.
근데 뭔가 이상하지 않은가 ?
@Bean
public Avengers avengers() {
Avengers a = new Avengers(ironMan(), hulk());
a.setHulk(hulk()); // aop 개입
a.setName("뉴욕");
return a;
}
여기에서 setHulk 부분에서 새로운 객체가 생성되어야 하지 않은가 ?
근데 container는 싱글톤으로 관리하기 때문에 새로운 객체를 생성하지 않는다.
근데 난 그런 설정을 한 적이 없다!!!
그럼 어떻게 ?
그게 바로 AOP를 적용한 것이다.
객체를 생성하기 전에 container에 빈이 있는지 확인하고 생성할지 안할지 결정하는 것!
그럼 AOP에 대해서 좀 더 알아보자
AOP 영어로 풀어 쓰면 Aspect Oriented Programming
이 말 그대로 관점 지향 프로그래밍이다 !!
그럼 관점 지향 프로그래밍은 뭘까 ???
우리는 핵심 로직과 공통 로직이 있다.
핵심은 말 그대로 서비스를 동작하기 위해 필요한 로직이다.
그럼 공통 로직은 ?
내가 무언 갈 하기전에 필요한 설정등을 해주는 공통 로직이 있다.
위에서 예시를 든 객체를 생성하기 전에 contatiner에서 빈을 확인한다는 지
, 로그인을 예로 들면 session에 로그인 정보가 있는지 없는지 확인해서 로직을 처리한다는지
등등 다양한 예시를 들 수 있다.
그런 것을 분리해서 알아서 관리해준다면 ?
우리는 핵심 로직에만 집중 할 수 있다!!
스프링은 우리에게 필요한 공통 로직등을 이미 미리 설정되어 있다.
그래서 우리가 핵심 로직에만 집중 할 수 있는 것이다.
대표적으로
등등 이 있다.
구구단으로 예시를 들어보자
Maven 프로젝트이고, 단순한 테스트이다.
@Component
@Slf4j
public class TimesTablesBean {
// 구구단의 합을 반환
public int getMultiSum(int num) {
log.debug("getmultiSum 호출됨 = {}", num);
int sum = 0;
for(int i = 1; i < 10; i++) {
sum += num * i;
}
return sum;
}
}
예를 들어 3이 들어오면 3단에 관한 모든 모든 값의 합을 반환하는 코드이다.
@Aspect
@Component
@Slf4j
public class AdviceTypeAspect {
// 메서드 호출 시 전달받은 파라미터는 1 ~ 9 사이
@Before("execution(int com..*.*CheckNum(..))")
public void checkNum(JoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
List<Integer> numbers = new ArrayList<>();
// 숫자 담기
for(Object arg : args) {
numbers.add(Integer.parseInt(arg.toString()));
}
// 범위체크
for(int number : numbers) {
if(number < 1 || number > 9) {
throw new RuntimeException("구구단의 범위 초과");
}
}
}
}
@Before("execution(int com..*.*CheckNum(..))")
여기에서 com 밑에 패키지에 모든 클래스에서 CheckNum문자가 뒤에 포함된 모든 메서드에 관하여 실행하기 전에
위의 코드를 실행시켜 범위를 확인할 수 있는 코드이다.
이 코드가 제대로 동작하는 지 확인해 보자
@Test
public void getMultiSumTest() {
int num = 3;
// 정상흐름
int result = sbean.getMultiSumCheckNum(num);
assertEquals(result, 135);
// 예외발생 ( 1 ~ 9 사이의 값이 아닌 다른 값 )
assertThrows(RuntimeException.class, () ->{
sbean.getMultiSumCheckNum(10);
});
}
결과는
성공 ~~
참고 자료
https://velog.io/@j_user0719/Spring-%ED%95%B5%EC%8B%AC-%EA%B5%AC%EC%A1%B0-POJOPSA
아저씨 오타가 너무 많아요.. 코드에 심취한 나머지 코드는 멋지지만, 글이 잘 안읽혀집니다. . . 😢