[목차]

5. AOP (Aspect Oriented Program)

* 스프링 AOP에서 용어
① AOP 구현

 


 

[내용]

5. AOP (Aspect Oriented Program)

 

: 핵심 로직에서 임의의 동작을 진행할 경우 사용. 
: 별도의 클래스로 정의하여 메소드를 탈부착식으로 사용한다.

: ex) 시큐리티, 로그인, 트랜잭션

 

 1) 설정

 ⓛ 사이트 접속 - search.maven.org/

 ② search창에 aspectjweaver 검색

 ③ version 선택

 ④ Apache Maven 내용 copy & paste

 ⑤ search창에 cglib 검색

 ⑥ version 선택

 ⑦ Apache Maven 내용 copy & paste

 ⑧ pom.xml에 Code 추가

<!-- aop -->
<dependencies>
	<dependency>
		<groupId>aspectj</groupId>
		<artifactId>aspectjweaver</artifactId>
		<version>1.5.4</version>
	</dependency>
	<dependency>
		<groupId>cglib</groupId>
		<artifactId>cglib</artifactId>
		<version>3.3.0</version>
	</dependency>
</dependencies>

 ⑨ 경로에 생성됨. C:\Users\wonh\.m2\repository\

 

2) code

- HelloInter

public interface HelloInter {
	void hello();
	void hi();	
}

 - HelloInterImpl

public class HelloInterImpl implements HelloInter{
	
	public HelloInterImpl() {
		System.out.println("HelloInterImpl 생성자");
	}
	
	public void hello() {
		System.out.println("hello 처리");
	}

	public void hi() {
		System.out.println("hi 처리");
	}
}

 - WriteInter

public interface WriteInter {
	void write();
}

 - WriteInterImpl

public class WriteInterImpl implements WriteInter{ // 핵심 로직을 가진 클래스
	
	public WriteInterImpl() {
		System.out.println("WriteInterImpl 생성자");
	}

	public void write() {
		System.out.println("write 수행");
	}
}

 - MyAspect

public class MyAspect { // 관심사항을 가진 클래스
	public void myLogOn() {
		System.out.println("핵심 메소드 수행전 로그온 작업");
	}
	
	public void myLogOut() {
		System.out.println("핵심 메소드 수행후 로그아웃 작업");
	}
	
	public void mySecurity() {
		System.out.println("핵심 메소드 수행전 보안설정");
	}
}

 - AspectProcess

public class AspectProcess { // 여러개의 관심사항들을 모아 처리하는 클래스
	private MyAspect myAspect; // 관심사항 클래스. 여러개 가능
	
	public void setMyAspect(MyAspect myAspect) {
		this.myAspect = myAspect;
	}
	
	public Object logging(ProceedingJoinPoint joinPoint) throws Throwable{
		Object object = null;
		
		myAspect.myLogOn();
		object = joinPoint.proceed(); // 메타파일에서 설정한 핵심 메소드 수행.
		myAspect.myLogOut();
		
		return object;
	}
	
	public Object logging2(ProceedingJoinPoint joinPoint) throws Throwable{
		Object object = null;
		
		myAspect.mySecurity();
		object = joinPoint.proceed(); // 메타파일에서 설정한 핵심 메소드 수행.
		return object;
	}
}

 => logging() 메소드는 myLogOn() -> 핵심로직 -> myLogOut() 순 호출

 => logging2() 메소드는 mySecurity() -> 핵심로직 순 호출

 - main

public static void main(String[] args) {
	//String[] configs = new String[] {"aop1core.xml"}; // 핵심만 수행
	String[] configs = new String[] {"aop1core.xml", "aop1.xml"}; // 핵심 + Aop 수행.
	
	ApplicationContext context = new ClassPathXmlApplicationContext(configs);
	
	WriteInter writeInter = (WriteInter)context.getBean("writeInterImpl");
	writeInter.write();
	System.out.println();
	
	HelloInterImpl helloInter = (HelloInterImpl)context.getBean("helloInterImpl"); // 방법 1
	HelloInter helloInter = context.getBean("helloInterImpl", HelloInter.class); // 방법 2
	helloInter.hi();
	helloInter.hello();
}

 - aop1core.xml

<bean id="writeInterImpl" class="aop1.WriteInterImpl"/>
<bean id="helloInterImpl" class="aop1.HelloInterImpl"/>

 - aop1.xml

<!-- Aspect(Advice) -->
<bean id="aspectProcess" class="aop1.AspectProcess">
	<property name="myAspect" ref="myAspect"/>
</bean>
<bean id="myAspect" class="aop1.MyAspect"/>

<!-- Aop 설정 -->
<aop:config>
	<aop:pointcut expression="execution(public void wri*(..))" id="poi1"/>
	// wri로 시작하고 매개변수가 0개 이상인 메소드
	// <aop:pointcut expression="execution(public void write())" id="poi1"/>
	<aop:aspect ref="aspectProcess">
		<aop:around method="logging" pointcut-ref="poi1"/>
	</aop:aspect>
</aop:config>
<aop:config>
	<aop:pointcut expression="execution(public void hel*(..)) or execution(public void hi*(..))" id="poi2"/>
	// or || and &&
	<aop:aspect ref="aspectProcess">
		<aop:around method="logging2" pointcut-ref="poi2"/>
	</aop:aspect>
</aop:config>

 => 핵심 로직의 wri로 시작하고 메개변수가 0개 이상인 메소드가 호출될때 AspectProcess(Aspect를 처리하는) 클래스의 logging() 메소드가 실행된다.

 => 핵심 로직의 hel로 시작하고 메개변수가 0개 이상인 메소드 또는 hi로 시작하는 메소드가 호출될때 AspectProcess클래스의 logging2() 메소드가 실행된다.

 


 - ArticleInter

public interface ArticleInter {
	void select();
}

 

- ArticleDao

//@Component
//@Repository
@Repository("articleDao")

public class ArticleDao implements ArticleInter{

	public void select() {
		System.out.println("db의 상품 자료를 read");
	}
}

 - LogicInter

public interface LogicInter {
	void selectData_process();
}

 - LogicImpl

public class LogicImpl implements LogicInter{
	private ArticleInter articleInter; 
    
	public LogicImpl() {
	}
	
	public LogicImpl(ArticleInter articleInter) {
		this.articleInter = articleInter; 
	}
	
	public void selectData_process() {
		System.out.println("selectData_proces 수행");
		articleInter.select();
	}
}
@Service
public class LogicImpl implements LogicInter{

	@Autowired
	//@Qualifier("aticleDao")
	private ArticleInter articleInter; 
	
	public void selectData_process() {
		System.out.println("selectData_proces 수행");
		articleInter.select();
	}
}

 

 - ProfileAdvice

public class ProfileAdvice { // Advice, Aspect
	public Object abc(ProceedingJoinPoint joinPoint) throws Throwable{
		//핵심 메소드 이름 얻기
		String methodName = joinPoint.getSignature().toString();
		
		System.out.println(methodName+" 시작 전 작업");
		Object object = joinPoint.proceed(); // 핵심 메소드
		System.out.println(methodName+" 처리 후 작업");
		
		return object;
	}
}
@Aspect
@Component
public class ProfileAdvice { // Advice, Aspect
	@Around("execution(public void selectData_process())")
	public Object abc(ProceedingJoinPoint joinPoint) throws Throwable{
		//핵심 메소드 이름 얻기
		String methodName = joinPoint.getSignature().toString();
		
		System.out.println(methodName+" 시작 전 작업");
		Object object = joinPoint.proceed(); // 핵심 메소드
		System.out.println(methodName+" 처리 후 작업");
		
		return object;
	}
}

 

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("aop2.xml");
	LogicInter inter = (LogicInter)context.getBean("logicImpl");
	inter.selectData_process();
}

 - aop2.xml

<!-- 핵심 로직 처리용 클래스 -->
<bean id="logicImpl" class="aop2.LogicImpl">
	<constructor-arg>
		<ref bean="articleDao"/>
	</constructor-arg>
</bean>
<bean id="articleDao" class="aop2.ArticleDao"></bean>

<!-- Aop 설정 -->
<bean id="profileAdvice" class="aop2.ProfileAdvice"/>
<aop:config>
	<aop:aspect ref="profileAdvice">
		<aop:pointcut expression="execution(public void selectData_process())" id="poi"/>
		<aop:around method="abc" pointcut-ref="poi"/>
	</aop:aspect>
</aop:config>	

 => 핵심로직의 selectData_process()메소드 호출 시 profileAdvice클래스의 abc()메소드가 호출.

<!-- 객체 생성 : 어노테이션 -->
<context:component-scan base-package="aop3"/>
<!-- Aop 설정 -->
<aop:aspectj-autoproxy/>

 

 

 

* 스프링 AOP에서 용어


 - Joinpoint : ‘클래스의 인스턴스 생성 시점’, ‘메소드 호출 시점’ 및 ‘예외 발생 시점’ 과 같이 어플리케이션을 실행할 때 특정 작업이 시작되는 시점을 의미.

 - Advice : 조인포인트에 삽입되어 동작할 수 있는 코드를 말함.

 - Pointcut : 여러 개의 조인포인트를 하나로 결합한(묶은) 것을 말함.

 - Advisor : 어드바이스와 포인트컷을 하나로 묶어 취급한 것을 말함.

 - Weaving : 어드바이스를 핵심 로직 코드에 삽입하는 것을 말함.

 - Target : 핵심 로직을 구현하는 클레스.

 - Aspect : 여러 객체에 공통으로 적용되는 공통 관점 사항을 말함.

 

 

1) AOP 구현

 - LogicInter

public interface LogicInter {
	void startProcess();
}

 

 - LogicImpl

@Service // @Component와 동일하지만 가독성을 위해 Service기능을 사용하면 @Service를 사용.
public class LogicImpl implements LogicInter{
	
	public LogicImpl() {
	}
	
	public void startProcess() {
		System.out.println("핵심 로직 수행");
	}
}

 

 - aop4.xml

<!-- 어노테이션을 사용하여 객체 생성 -->
<context:component-scan base-package="aop4"/>
<!-- aop를 사용하도록 설정 -->
<aop:aspectj-autoproxy/>

    <context:component-scan base-package="패키지명"/>
    <aop:aspectj-autoproxy/>

 

 - main

public static void main(String[] args) {
	ApplicationContext context = new ClassPathXmlApplicationContext("aop4.xml");
	LogicInter inter = (LogicInter)context.getBean("logicImpl");
	// getBean의 매개변수 : @객체 생성할 클래스명을 첫글자 소문자로 변경하여 생성. 
	inter.startProcess();
}

 

 - RunAspect

// 아이디가 같으면 핵심로직 수행, 다르면 수행하지않도록 구현.
@Component
@Aspect // 독립적으로 동작할 관심 로직 클래스에 사용
public class RunAspect {
	
	@Around("execution(public void startProcess())")
	// 핵심로직의 메소드를 선택. 해당메소드 호출시 관심 메소드 호출.
	//@Around는 핵심로직 실행 전/후 모두 기능을 추가할 수 있다.
	public Object trace(ProceedingJoinPoint joinPoint) throws Throwable{
		
		System.out.println("AOP 시작 : 핵심 로직 처리전 id 검증");
		System.out.print("input id : ");
		Scanner scanner = new Scanner(System.in);
		String id = scanner.nextLine();
		if(! id.equalsIgnoreCase("aa")) { //equalsIgnoreCase() 대소문자 구분하지않고 비교.
			System.out.println("id 불일치하여 작업을 종료합니다.");
			return null;
		}
		
		Object obj = joinPoint.proceed(); // 핵심 로직 수행.
		
		return obj;
	}
}

    @Component

    @Aspect

    @Around("excution(핵심 로직의 메소드)")

    public Object 관심메소드명(ProceedingJoinPoint joinPoint) throws Throwable{ .. }

    Object obj = joinPoint.proceed();

    str1.equalsIgnoreCase(str2)

 

 

 

 

+ Recent posts