Spring-Annotaion,AOP

4 minute read

Annotation

AOP를 들어가기 앞서 사전지식이 필요한 개념이다.
Annotaion으로 인하여 데이터의 유효성 검사 등을 쉽게 할 수 있고, 이에 관련된 코드가 깔끔해지게 된다.
Annotaion으로 인하여 AOP를 편리하게 구성할 수 있게 하며 실제 데이터가 아닌 Data를 위한 데이터, 즉, Meta Data이다.

Java의 기본적인 Annotation

Annotaion설명
@Override
  • 선언한 Method가 Override되었다는 것을 나타냄
  • 부모 클래스에서 해당 메서드를 찾을 수 없다면 Error 발생
@Deprecated
  • 해당 메서드가 더 이상 사용되지 않음
  • 만약 사용할 경우 컴파일 경고를 발생
@Suppress Warnings
  • 선언한 곳의 컴파일 경고를 무시하도록 함
@SafeVarargs
  • 제너릭 같은 가변인자의 매개변수를 사용할 때의 경고를 무시한다.
@FunctionalInterface
  • 함수형 인터페이스를 지정
  • 메서드가 존재하지 않거나, 1개 이상의 메서드가 존재할 경우 컴파일 오류 발생


Meta Annotation

Annotaion설명
@Retention
  • 자바 컴파일러가 어노테이션을 다루는 방법을 기술, 특정 시점까지 영향을 미치는지를 결정
@Target
  • 어노테이션이 적용할 위치를 선택
@Documented
  • 해당 어노테이션을 Javadoc에 포함
@Inherited
  • 어노테이션의 상속을 가능하게 한다.
@Repeatable
  • 연속적으로 어노테이션을 선언


Spring Annotation

Annotaion설명
@Component
  • component-scan을 선언에 의해 특정 패키지 안의 클래스들을 스캔하고 @Component Annotaion이 있는 클래스에 대하여 bean인스턴스를 생성
  • @Controller: Presentation Layer에서 Controller를 명시하기 위해 사용
  • @Service: Business Layer에서 Service를 명시하기 위해 사용
  • @Repository: Presentation Layer에서 DAO를 명시하기 위해 사용
@RequestMapping
  • Class Level Mapping: 특정 요청에 대한 처리를 해당 클래스에서 한다는 것
  • Handler Level Mapping: 특정 요청이 Post, Get인지를 구분하고 해당하는 요청에 맞을때 수행
@Required
  • setter Method에 사용. property를 채워야 한다.
@Autowired
  • Type에 따라 알아서 Bean을 주입
  • Type을 확인하후 못찾으면 Name에 따라 주입
@Qualifier
  • 같은 타입의 빈이 두 개 이상이 존재하는 경우에 Spring이 어떤 빈을 주입해야 할지 알 수 없어서 명확히 지시
@RequestParam
  • GET요청에 대해 매칭되는 request parameter값이 자동으로 들어감
  • URL 뒤의 문자열이 실제 전달되는 이름 값이다.
@Path Variable
  • HTTP 요청에 대해 매칭되는 request parameter값이 자동으로 들어감
  • URL 에서 각 구분자에 들어오는 값을 처리할 때 사용
@RequestBody
  • POST요청에 대해 매칭되는 request message값이 자동으로 들어감
@ModelAttribute
  • Form 값이 자동으로 Mapping 된다.


AOP(Aspect Oriented Programming)

AOP란 관점지향 프로그래밍 이다.
공통적인 기능을 모든 모듈에 적용하기 위한 방법으로 상속을 이용한다.
JAVA에서는 다중상속이 불가능하기 때문에 AOP로서 한계를 극복한다.
이러한 AOP의 핵심기능은 공통 기능을 분리시키고 공통 기능을 필요로 하는 기능들에서 사용하는 방식이다.

AOP Annotaion

구성 요소설명
JoinPoint관심 모듈의 기능이 삽입되어 동잘 할 수 있는 실행 가능한 특정 위치
Pointcut어떤 클래스의 어느 조인포인트를 사용할 것인지를 선택 가능
Weaving포인트컷에 의해서 결정된 조인포인트에 지정된 어드바이스를 삽입하는 과정
AspectPointcut에서 Advice를 할 것인지


그림참조:I’s Stroy 블로그

init.xml

AOP를 사용하기 위한 환경 설정 이다.
< aop:aspectj-autoproxy />: Java AOP를 사용하기 위하여 선언
< context:component-scan base-package=”pack” />: 일일이 Bean을 등록하지 않고 사용하기 위하여 선언

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

	<context:component-scan base-package="pack" />
	
	<aop:aspectj-autoproxy />
</beans>


pack.model

DB와 연관되는 작업을 하는 곳이다.
ArticleInter: Interface를 사용하여 공동 작업시 충돌 방지
ArticleDAO: 실제 DB와 연결하여 작업(현재는 DB와 연결되어 있지 않으므로 간단한 출력형식을 사용하였다.)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//ArticleInter
package pack.model;

public interface ArticleInter {
	void selectAll();
}

//ArticleDao
package pack.model;

import org.springframework.stereotype.Repository;

@Repository("articleDao")
public class ArticleDao implements ArticleInter{
	
	@Override
	public void selectAll() {
		System.out.println("직원 테이블 전체자료 조사");
		
	}

}

pack.BL

실제 Logic이 구현되는 곳이다.
LogicInter: Interface를 사용하여 공동 작업시 충돌 방지
LogicImpl: 실제 Logic이 실행되는 곳이다.

  • Qualifier를 통하여 ArticleDao를 객체화 하여 사용
  • articleInter.selectAll()를 통하여 DB와 연동되어 작업 Main: 실제 수행을 위하여 실행을 하는 곳
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
//LogicInter
package pack.BL;

public interface LogicInter {
	void selectdataProcess();
}

//LogicImpl
package pack.BL;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import pack.model.ArticleInter;

@Service
public class LogicImpl implements LogicInter {
	@Autowired
	@Qualifier("articleDao")
	private ArticleInter articleInter;

	
	@Override
	public void selectdataProcess() {
		System.out.println("selectdataProcess 작업하는 중...");
		articleInter.selectAll();
	}
	
}

//Main
package pack.BL;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Main {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("init.xml");
		LogicInter inter = context.getBean("logicImpl",LogicInter.class);
		inter.selectdataProcess();

	}

}

pack.Aspect

AOP를 사용하는 곳 이다.
ASPECT는 다음과 같은 형태로 정리될 수 있다.

// AspectJ의 Pointcut 표현식 정리

execution([접근자제어패턴], 리턴타입패턴 [패키지패턴]메서드이름패턴(파라메터패턴)) [ ] 안의 패턴은 생략 가능

execution(public void set*(..))
public에 리턴값이 없으며, 패키지명은 없고, 메서드는 set으로 시작하며 인자값은 0개 이상인 메서드 호출

execution(* com.people.*.*())
리턴타입에 상관없이 com.people패키지의 인자값이 없는 모든 메서드 호출

execution(* com.people..*.*(..))
리턴타입에 상관없이 com.people 패키지 및 하위 패키지에 있는, 인자값이 0개 이상인 메서드 호출

execution(Integer com.people.WriteService.write(..))
리턴 타입이 Integer인 WriteServlce의 인자값이 0개 이상인 write() 호출

execution(* get*(*))
메서드 이름이 get으로 시작하는 인자값이 1개인 메서드 호출

execution(* get*(*,*))
메서드 이름이 get으로 시작하는 인자값이 2개인 메서드 호출

execution(* get*(Integer, ..))
메서드 이름이 get으로 시작하고 첫번째 인자값의 데이터타입이 Integer이며, 1개 이상의 인자값을 갖는 메서드 호출

execution(* com..*(..)) && @annotation(@annotation)
@annotation이 있는 모든 메소드 호출

execution(* *(..,@annotation (*), ..))
@annotation을 파라메터로 갖고 있는 모든 메소드 호출


@Around(“execution(public * pack.BL..* ( . . ) ) “)를 통하여 pack.BL에서 어떤한 작업이 일어날 경우 잡아오는 역할을 한다.
System.out.println(“Hello CheckPoint1”); => 작업 수행전 실행 Object object = joinPoint1.proceed(); => 잡아온 작업 수행 System.out.println(“Hello CheckPoint2”); => 작업 수행 후 실행

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package pack.Aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class OurAdvice {
	@Around("execution(public * pack.BL..*(..))")
	public Object kbs(ProceedingJoinPoint joinPoint1) throws Throwable {

		System.out.println("Hello CheckPoint1");
		Object object = joinPoint1.proceed();
		System.out.println("Hello CheckPoint2");
		return object;
	}
}

실행결과




내용참조:I’s Story 블로그
내용참조:MHLab 블로그
내용참조:gmlwjd9405 블로그
내용참조:천프로 블로그
참조:원본코드
코드에 문제가 있거나 궁금한 점이 있으면 wjddyd66@naver.com으로 Mail을 남겨주세요.

Categories:

Updated:

Leave a comment