SW/Java

Java : Spring :AspectJ 어노테이션 : 개념, 사용, 방법, 예제, 구현

얇은생각 2020. 6. 14. 07:30
반응형

Java : Spring :AspectJ 어노테이션 : 개념, 사용, 방법, 예제, 구현

 

@AspectJ

@AspectJ 어노테이션을 활용해 Advisor 역할을 할 Bean을 설정할 수 있습니다.

 

지원 어노테이션

@Before : 관심사 동작 이전에 호출됩니다.
@After : 관심사 동작 이후에 호출됩니다.
@Around : 관심사 동작 이전 이후를 의미합니다.
@AfterReturning : 예외 없이 정상적으로 종료되었을 때 호출됩니다.
@AfterThrowing : 예외가 발생하여 종료되었을 때 호출됩니다.

 

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>kr.co.softcampus</groupId>
	<artifactId>AOPJava</artifactId>
	<version>0.0.1-SNAPSHOT</version>

	<!-- xml에서 사용할 속성들 -->
	<properties>
		<!-- 자바 버전 -->
		<java-version>1.8</java-version>
		<!-- 스프링 버전 -->
		<org.springframework-version>5.1.9.RELEASE</org.springframework-version>
		<!--<org.springframework-version>4.3.25.RELEASE</org.springframework-version> -->
		<org.slf4j-version>1.7.26</org.slf4j-version>
		<ch.qos.logback-version>1.2.3</ch.qos.logback-version>
		<javax.annotation-version>1.3.2</javax.annotation-version>
		<org.aspectj-version>1.9.4</org.aspectj-version>
	</properties>

	<!-- 프로젝트에서 사용할 라이브러리 정보 -->
	<dependencies>
		<!-- spring context -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${org.springframework-version}</version>
		</dependency>
		<!-- slf4j -->
		<dependency>
			<groupId>org.slf4j</groupId>
			<artifactId>slf4j-api</artifactId>
			<version>${org.slf4j-version}</version>
		</dependency>
		<!-- logback -->
		<dependency>
			<groupId>ch.qos.logback</groupId>
			<artifactId>logback-classic</artifactId>
			<version>${ch.qos.logback-version}</version>
			<exclusions>
				<exclusion>
					<groupId>org.slf4j</groupId>
					<artifactId>slf4j-api</artifactId>
				</exclusion>
			</exclusions>
			<scope>runtime</scope>
		</dependency>
		<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
		<dependency>
			<groupId>javax.annotation</groupId>
			<artifactId>javax.annotation-api</artifactId>
			<version>${javax.annotation-version}</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
		<dependency>
			<groupId>org.aspectj</groupId>
			<artifactId>aspectjweaver</artifactId>
			<version>${org.aspectj-version}</version>
		</dependency>


	</dependencies>
</project>

 

 

beans.xml

<?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:context="http://www.springframework.org/schema/context"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	                    http://www.springframework.org/schema/beans/spring-beans.xsd
	                    http://www.springframework.org/schema/context
	                    http://www.springframework.org/schema/context/spring-context.xsd
	                    http://www.springframework.org/schema/aop
	                    http://www.springframework.org/schema/aop/spring-aop.xsd">
	                    
	<context:component-scan base-package="kr.co.softcampus.beans"/>
	<context:component-scan base-package="kr.co.softcampus.advisor"/>
	
	<!-- advisor 클래스에 설정되어 있는 Annoation을 분석하여 AOP 셋팅을 해라 -->
	<aop:aspectj-autoproxy/>
</beans>

 

 

AdvisorClass

package kr.co.softcampus.advisor;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class AdvisorClass {
	
	@Before("execution(* method1())")
	public void beforeMethod() {
		System.out.println("beforeMethod 호출");
	}
	
	@After("execution(* method1())")
	public void afterMethod() {
		System.out.println("afterMethod 호출");
	}
	
	@Around("execution(* method1())")
	public Object aroundMethod(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("aroundMethod 호출 1");
		Object result = pjp.proceed();
		System.out.println("aroundMethod 호출 2");
		return result;
	}
	
	@AfterReturning("execution(* method1())")
	public void afterReturningMethod() {
		System.out.println("afterReturning 호출");
	}
	
	@AfterThrowing("execution(* method1())")
	public void afterThrowingMethod() {
		System.out.println("afterThrowing 호출");
	}
}

 

 

TestBean1.java

package kr.co.softcampus.beans;

import org.springframework.stereotype.Component;

@Component
public class TestBean1 {
	
	public void method1() throws Exception{
		System.out.println("TestBean1의 method1 호출");
		
		//int a1 = 10 / 0;
	}
}

 

 

BeanConfigClass.java

package kr.co.softcampus.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@ComponentScan(basePackages = {"kr.co.softcampus.beans", "kr.co.softcampus.advisor"})
@EnableAspectJAutoProxy
public class BeanConfigClass {

}

 

 

MainClass.java

package kr.co.softcampus.main;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import kr.co.softcampus.beans.TestBean1;
import kr.co.softcampus.config.BeanConfigClass;

public class MainClass {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		ClassPathXmlApplicationContext ctx1 = new ClassPathXmlApplicationContext("kr/co/softcampus/config/beans.xml");
		
		TestBean1 xml1 = ctx1.getBean(TestBean1.class);
		try {
			xml1.method1();
		}catch(Exception e) { 
			
		}
		
		ctx1.close();
		
		System.out.println("========================================");
		
		AnnotationConfigApplicationContext ctx2 = new AnnotationConfigApplicationContext(BeanConfigClass.class);
		
		TestBean1 java1 = ctx2.getBean(TestBean1.class);
		try {
			java1.method1();
		}catch(Exception e) {
			e.printStackTrace();
		}
		
		ctx2.close();
	}

}

 

정리

이번 시간에는 xml 파일이 아닌 어노테이션을 활용해, AOP 기능을 활용해보았습니다. 어노테이션 설정만 유의해서 적용한다면, 큰 어려움 없이, AOP 기능을 메소드에 적용할 수 있다는 것을 알 수 있었습니다.

이 기능은 세션 확인, 로깅 등등 다양한 반복되는 로직에 활용한다면 유의미한 기능이 될 수 있을 것 같습니다. 다만, 불필요한 로직을 넣어놓는다면, 서버에 불필요할 로직을 타서 성능 저하를 일으킬 수 도 있을 것 같다는 생각이 들었습니다. 

구체적인 내용에 대해서는 아래 강좌에서 확인할 수 있습니다. 향후에 배울 내용들에 대해서도 기대가 큽니다.

https://www.udemy.com/course/sooftcampus-sfb/

 

초보 Spring Framework 개발자를 위한 실습을 통한 입문 과정 윤재성

Spring Framework 입문을 위한 주제별 실습 및 상세 설명( beginner step1)

www.udemy.com

 

반응형