빡코

스프링 3.0 + APO 셋팅 및 실습 본문

Java

스프링 3.0 + APO 셋팅 및 실습

chris.djang 2019. 11. 14. 19:46

스프링 3.0에서의 APO 개념.

 

AOP(Aspect Oriented Programming : 관점지향프로그래밍) 
OOP(Object Oriented Programming :객체지향프로그래밍) //클래스 단위로 프로그래밍

불특정 다수의 객체(클래스,메소드)에 코드를 탈부착할수있게 만드는 기능
공통적으로 사용되는 부분(공통화해서 라이브러리 할수있는 부분 트랜젝션이나 에외부분)을 별도로 분리하는 기술

**********************************************************
용어설명
**클래스를 벗어나서~~ 

[횡단 관심사] 
모든 영역에 공통적으로 적용되는 코딩 어플리케이션 여러부분에 영향을 주는 기능
클래스들이 있고, 해당 각 클래스안에는 다수의 메소드들이 있는데, 이 메소드를 한번에 엮어서 검사가능함

[조인포인트]
애플리케이션 실행의 특정 지점을 의미
AOP에서 Aspect(횡단 관심사)를 적용하는 위치(메소드)?를 표시하는데 사용


[어드바이스]
특정 조인포인트에 적용(실행)할 코드
실행시점에 따라 Before Advice, After Advice 등으로 구현

[포인트컷]
여러 조인포인트의 집합으로 언제 어드바이스를 실행하는 위치 표시

[애스팩트]
어드바이스(동작)와 포인트컷(동작을적용하는조건)을 조합해서 
횡단 관심사에 대한 코드와 그것을 적용할 지점을 정의한 것

[위빙]
애스팩트를 실제 적용하는 과정 (정적 / 동적 방식이 구분되는 조건)

[타겟]
어드바이스가 적용된 객체


Aspect :무엇을(Advice) 언제(Point) 할지 정의

 

●은 메소드 여기다가 advice 를 하나준다. 예를들어 김씨성을 가진 사람들 반응해!!
이 advice의 위치를 지정해주는게 Pointcut 이고 두개를 합쳐놓은 것이 바로 Apspect 
JointPoints는 aspect가 적용되는 객체를 의미한다.

 

지금부터 셋팅을 하고 실습을 해보겠다.

 

 

SpringAOP 프로젝트 생성하고(simpe Spring Utiliy Project 선택) com.exe.aop 패키지를 생성해준다.

 

 

 

 

https://mvnrepository.com/

 

사이트에서 총4개의 Maven tag를 pom.xml에 추가해 준다. 

 

1.Spring AOP » 5.1.11.RELEASE

https://mvnrepository.com/artifact/org.springframework/spring-aop/5.1.11.RELEASE

2.AspectJ Runtime » 1.8.13
https://mvnrepository.com/artifact/org.aspectj/aspectjrt/1.8.13

 

3. AspectJ Weaver » 1.8.13
https://mvnrepository.com/artifact/org.aspectj/aspectjweaver/1.8.13


4.CGLib » 3.2.5

https://mvnrepository.com/artifact/cglib/cglib/3.2.5

 

pom.xml에 추가된 모습은 다음과 같다. 

		<!-- spring-aop -->
		<dependency>
   			 <groupId>org.springframework</groupId>
   		 	<artifactId>spring-aop</artifactId>
   			 <version>${spring.framework.version}</version>
		</dependency>
		
		<!-- aspectjrt -->
		<dependency>
   			 <groupId>org.aspectj</groupId>
    		<artifactId>aspectjrt</artifactId>
    		<version>1.8.13</version>
		</dependency>
		
		<!-- aspectjweaver -->
		<dependency>
    		<groupId>org.aspectj</groupId>
    		<artifactId>aspectjweaver</artifactId>
    		<version>1.8.13</version>
		</dependency>
		
		<!-- cglib(Spring AOP Proxy -->
		<dependency>
    		<groupId>cglib</groupId>
    		<artifactId>cglib</artifactId>
    		<version>3.2.5</version>
		</dependency>

Maven이 설치 되었는지 확이한는 방법은 아래의 경로를 통해서 가능하다.

C:\Users\stu\.m2\repository\org

 

다음은 app-context.xml 파일을 다음과 같이 설정해준다. 

어노테이션 사용시 <aop:aspectj-autoproxy> 태그를 추가하고 하단의 </beans>태그를 제외한 나머지 코드를 주석처리한다. 

<?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 
		https://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/context 
		https://www.springframework.org/schema/context/spring-context-3.0.xsd
		http://www.springframework.org/schema/aop 
		https://www.springframework.org/schema/aop/spring-aop-3.0.xsd">

	<description>Example configuration to get you started.</description>

	<context:component-scan base-package="com.exe.aop" />
	<!-- 어노테이션을 사용할 경우 아래 코딩을 추가하고, 그 하단의 모든 코딩을 주석처리한다 -->
	<aop:aspectj-autoproxy/>
	
	<!-- 어노테이션 사용시 주석 시작 부분 -->
	<!-- execution(메소드접근지정자,반환값,패키지.클래스.메소드명(인수) -->
	<bean id="beforeAdvice"
	class="com.exe.aop.MyBeforeAdvice"/>
	
	<bean id="afterAdvice"
	class="com.exe.aop.MyAfterAdvice"/>
	
	<bean id="aroundAdvice"
	class="com.exe.aop.MyAroundAdvice"/>
	
	<bean id="afterReturningAdvice"
	class="com.exe.aop.MyAfterReturningAdvice"/>
	
	<bean id="afterThrowingAdvice"
	class="com.exe.aop.MyAfterThrowingAdvice"/>
	
	 -->	
	<!-- execution(메소드접근지정자,반환값,패키지.클래스.메소드명(인수) -->
    <!-- beforeMethodCall메소드를 execution(public void com..aop.*.doA*(..))에 적용하겠다라는 의미이다 -->
	<aop:config>
	
	 	<aop:aspect ref="beforeAdvice">
	 		<aop:pointcut id="beforePointcut" 
	 		expression="execution(public void com..aop.*B.doS*(..))" />
	 		<aop:before method="beforeMethodCall"
	 		pointcut-ref="beforePointcut"/>
	 	</aop:aspect>
	  	
	  	<aop:aspect ref="afterAdvice">
	 		<aop:pointcut id="afterPointcut" 
	 		expression="execution(public void com..aop.*.doA*(..))" />
	 		<aop:after method="afterMethodCall"
	 		pointcut-ref="afterPointcut"/>
	 	</aop:aspect>
	
	  
	  	<aop:aspect ref="aroundAdvice">
	  	
	  		<aop:pointcut id="aroundPointcut"
	  		 expression="execution(* com..aop.*.*(..))"/>
	  		 
	  		 <aop:around method="aroundMethodCall"
	  		 pointcut-ref="aroundPointcut"/>	  	
	  		 
	  	</aop:aspect>
	  	
	  	 
	  	  
	  	  <aop:aspect ref="afterReturningAdvice">
	  	
	  		<aop:pointcut id="afterReturningPointcut"
	  		 expression="execution(* com..aop.*.*(..))"/>
	  		 
	  		 <aop:after-returning method="afterReturningMethodCall"
	  		 pointcut-ref="afterReturningPointcut"/>	  	
	  		 
	  	</aop:aspect>
	  	
	  	 
	  	  <aop:aspect ref="afterThrowingAdvice">
	  	
	  		<aop:pointcut id="afterThrowingPointcut"
	  		 expression="execution(* com..aop.*.*(..))"/>
	  		 
	  		 <aop:after-throwing method="afterThrowingMethodCall"
	  		 pointcut-ref="afterThrowingPointcut"/>	  	
	  		 
	  	</aop:aspect>
	  	  
	  
	</aop:config>
 	<!-- 어노테이션 사용시 주석 끝나는 부분 -->


</beans>

AopMain.java 파일(하단)

package com.exe.aop;

import org.springframework.context.support.GenericXmlApplicationContext;

public class AopMain {

	public static void main(String[] args) {
		
		GenericXmlApplicationContext context = 
				new GenericXmlApplicationContext("app-context.xml");
		
		TargetA ta = 
				(TargetA)context.getBean("targetA");
		
		ta.doAnother1();
		ta.doAnother2();
		ta.doSomething1();
		ta.doSomething2();
		
		TargetB tb = 
				(TargetB)context.getBean("targetB");
		
		tb.doAnother1();
		tb.doAnother2();
		tb.doSomething1();
		tb.doSomething2();
	}

}

MyAfterAdvice (하단)

package com.exe.aop;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAfterAdvice {
	
	@After("execution(* com..aop.*.*(..))")
	public void afterMethodCall() {
		
		//체크를하기 위한 공통적인 코드들이 들어간다.
		System.out.println("메소드 실행 후(after)");
		
	}

}

MyAfterReturningAdvice.java 파일(하단)

package com.exe.aop;

import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAfterReturningAdvice {
	
	@AfterReturning("execution(* com..aop.*.*(..))")
	public void afterReturningMethodCall() {
		
		//리턴값이 완료 되었을 때 ==메서드가 잘 실행이 되었을 때
		System.out.println("메소드 실행 완료(Return)");
		
	}

}

MyAfterThrowingAdvice.java 파일(하단)

package com.exe.aop;

import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyAfterThrowingAdvice {
	
	@AfterThrowing("execution(* com..aop.*.*(..))")
	public void afterThrowingMethodCall() {
		
		
		//에러가 발생했을떄 디스크로즈
		System.out.println("메소드 실행 에러(error)");
		
	}

}

MyAroundAdvice.java 파일(하단)

package com.exe.aop;

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 MyAroundAdvice {
	
	//before와 after가 합쳐진것
	@Around("execution(* com..aop.*.*(..))")
	public Object aroundMethodCall(ProceedingJoinPoint jointPoint) {
		
		Object result = null;
	
		try {
			
			System.out.println("메소드 실행전(round)");
			
			result = jointPoint.proceed();
			
			System.out.println("메소드 실행후(round)");
		} catch (Throwable e) {
			
			
		}
		
		return result;
		
	}

}

MyBeforeAdvice.java 파일(하단)

package com.exe.aop;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyBeforeAdvice {
	//내가 해야하는 작업 >>> app-context 로 들어감
	
	@Before("execution(* com..aop.*.*(..))")
	public void beforeMethodCall() {
		
		//체크를하기 위한 공통적인 코드들이 들어간다.
		System.out.println("메소드 실행 전(before)");
		
	}

}

TargetA.java 파일(하단)

package com.exe.aop;

import org.springframework.stereotype.Component;

@Component("targetA") //클래스의 객체가 생성됨
public class TargetA {
	
	public void doSomething1() {
		System.out.println("TargetA.dosomething1");
	}
	
	public void doSomething2() {
		System.out.println("TargetA.doSomething2");
	}
	
	public void doAnother1() {
		System.out.println("TargetA.doAnother1");
	}

	public void doAnother2() {
		System.out.println("TargetA.doAnother2");
	}

}

TargetB.java 파일(하단)

package com.exe.aop;

import org.springframework.stereotype.Component;

@Component("targetB") //클래스의 객체가 생성됨
public class TargetB {
	
	public void doSomething1() {
		System.out.println("TargetB.dosomething1");
	}
	
	public void doSomething2() {
		System.out.println("TargetB.doSomething2");
	}
	
	public void doAnother1() {
		System.out.println("TargetB.doAnother1");
	}

	public void doAnother2() {
		System.out.println("TargetB.doAnother2");
	}

	
}

 

결과 값은 아래와 같이 나타날 것이다.

 

 

 

 

 

 

-exit-

 

 

 

 

 

 

 

 

 

 

 

'Java' 카테고리의 다른 글

Spring 3.0 View 셋팅 실습하기  (0) 2019.11.15
Spring 3.0 + Mybatis 셋팅 && 실습  (0) 2019.11.15
Spring 3.0 + jdbc 셋팅 && 실습  (0) 2019.11.15
스프링 3.0 + 웹 개발  (0) 2019.11.14
스프링 3.0 + MyBatis 셋팅  (0) 2019.11.14