1. profile 속성
- 개발 환경에 따라 bean 설정을 달리 적용하고 싶을 때 사용하는 속성이다.
1) Profile 지정하기
(1) XML 방식
- <beans>의 profile 속성을 이용하여 bean을 나눌 수 있다.
<beans ....
<beans profile="dev, test">
<bean ...>
<property .../>
</bean>
</beans>
<beans profile="production">
<bean ...>
<property .../>
</bean>
</beans>
</beans>
(2) Annotation 방식
- 설정 클래스에 @Profile 어노테이션을 추가하여 profile을 지정할 수 있다.
- 아래 예시에서 profile 이름은 test로 설정했으며, profile이 지정되어 있지 않은 bean 설정은 default profile로 취급한다.
@Configuration
@Profile("test")
public class TestApplicationContext {
...
}
- 여러 설정 클래스들을 대표 설정 클래스의 내부 static 클래스로 만들어 한 파일에 모으는 방법도 있다. 내부 static 클래스마다 똑같이 @Configuration과 @Profile을 적용해주면 된다.
2) Profile 활성화 하기
- 활성 프로파일 목록에 profile 이름을 등록하지 않으면 profile을 설정한 클래스는 무시된다. 특정 profile을 설정한 Bean 설정을 가져와서 사용하고 싶다면 해당 profile을 활성 profile로 만들어야 한다.
- 하나의 profile의 이름이 2개 이상으로 설정되었다면 그 중 하나의 profile만 활성화 시켜도 인식된다.
(1) Xml 방식
- <context-param> 또는 <init-param>의 spring.profiles.active 프로퍼티를 이용한다. <context-param>의 경우에는 루트 컨텍스트와 서블릿 컨텍스트 모두에 지정된다.
<context-param>
<param-name>spring.profiles.active</param-name>
<param-value>dev, test</param-value>
</context-param>
(2) Annotation 방식
- 다음과 같이 @ActiveProfiles 어노테이션을 사용한다.
- @ContextConfiguration에는 설정 클래스를 지정하거나 설정 클래스들이 모여있는 패키지를 지정해도 된다.
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles("test")
@ContextConfiguration(classes=TestApplicationContext.class)
public class ATest {
...
}
(3) JVM의 커맨드라인 파라미터 방식
-Dspring.profiles.active=dev
3) 테스트 코드
- 지정한 profile의 bean 설정만 잘 적용되었는지 테스트하기 위해 DefaultListableBeanFactory 클래스를 이용할 수 있다.
@Autowired
DefaultListableBeanFactory bf;
@Test
public void beansTest(){
for(String s : bf.getBeanDefinitionNames()) {
System.out.println(n+" "+bf.getBean(n).getClass().getName()); // Bean 이름과 구현 클래스를 출력
}
}
2. AOP(관점 지향 프로그래밍)
Aspect Oriented Programming
애플리케이션에 흩어져 있는 부가적인 공통 기능들을 독립적으로 모듈화하는 프로그래밍 모델이다.
Advice라고 하는 모듈화된 공통 기능과 Pointcut이라고 하는 적용 대상의 조합을 통해 공통 기능을 편리하게 관리할 수 있다.
1) 관련 용어
- Aspect : 관점, 공통 기능
- Advice : 공통 부가 기능을 담은 모듈
- Joinpoint : 공통 기능을 적용해야 되는 부분
- Pointcut : 적용 대상
- Weaving : 공통 기능을 핵심 기능에 적용 하는 것
2) Advice 종류
- <aop:before> : 메소드 실행 전에 advice 실행
- <aop:after-returning> : 정상적으로 메소드에서 반환값이 return되고 advice 실행
- <aop:after-throwing> : 메소드 실행 중에 예외 발생 시 advice 실행
- <aop:after> : 메소드 실행 후 및 예외 발생 시 advice 실행
- <aop:around> : 메소드가 호출되는 전 과정 동안 advice 실행
3) Pointcut 표현식
- 포인트컷 표현식을 통해 AOP를 적용할 메소드를 선정할 수 있다.
- 포인트컷 표현식을 아래 포스팅에 정리해놓았으니 참고하길 바란다.
https://kimcoder.tistory.com/543
4) xml 이용 예제 - while문과 for문 시간 차이 구하기
여기서 핵심 기능은 각각 while문, for문으로 연산하는 것이고
공통 기능은 시간를 구하는 것이다.
<pom.xml>
aop라이브러리를 추가 하기 위해 dependency를 다음과 같이 추가해줘야 한다.
<dependencies>
...
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.7.4</version>
</dependency>
</dependencies>
<WhileOperation.java>
while문으로 1부터 num까지의 누적합을 구하는 클래스이다.
package com.example.demo;
public class WhileOperation {
private int num;
private int sum = 0;
public void setNum(int num) {
this.num = num;
}
public void addTonum() {
int i=1;
while(i<=num) {
sum+=i;
i++;
}
}
}
<ForOperation.java>
for문으로 1부터 num까지의 누적합을 구하는 클래스이다.
package com.example.demo;
public class ForOperation {
private int num;
private int sum = 0;
public void setNum(int num) {
this.num = num;
}
public void addTonum() {
for(int i=1;i<=num;i++) sum+=i;
}
}
<LogAop.java>
공통 기능 클래스이다.
joinpoint.getSignature().toShortString() 메소드는 현재 적용하고 있는 핵심 기능 메소드를 "클래스.메소드" 형태로 반환해준다.
ProceedingJoinPoint.proceed() 메소드는 클라이언트가 보낸 파라미터를 그대로 사용해서 AOP 적용 대상 메소드를 실행해준다.
package com.example.demo;
import org.aspectj.lang.ProceedingJoinPoint;
public class LogAop {
public Object loggerAop(ProceedingJoinPoint joinpoint) throws Throwable {
String str = joinpoint.getSignature().toShortString();
System.out.println("start - "+str);
long start = System.currentTimeMillis();
try {
Object obj = joinpoint.proceed();
return obj;
} finally {
long end = System.currentTimeMillis();
System.out.println("end - "+str);
System.out.println("Time : "+(end-start));
}
}
}
<application.xml>
aop 스키마 경로를 beans에 추가해주고, <aop:config> 태그에 공통 기능을 적용할 핵심 기능을 지정해줘야 한다.
<aop:aspect>의 id는 공통 기능 이름이고, ref는 공통 기능 객체이다.
<aop:pointcut>의 expression에는 포인트컷 표현식을 지정하면 된다. 예시에서는 com.example.demo 패키지의 모든 메소드에 적용하였고, pointcut의 이름은 publicTimer로 지정하였다.
<aop:around>에서는 "publicTimer" 포인트컷에 해당하는 객체들에 대하여, 공통 기능 클래스의 내부 메소드인 loggerAop메소드를 수행하도록 지정하면 된다.
만약 공통 기능 메소드를 추가하고 싶다면 추가할 때마다 <aop:aspect> 태그를 더 만들어주면 된다.
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
">
<bean id="logAop" class="com.example.demo.LogAop"/>
<aop:config>
<aop:aspect id="logger" ref="logAop">
<aop:pointcut expression="within(com.example.demo.*)" id="publicTimer"/>
<aop:around pointcut-ref="publicTimer" method="loggerAop"/>
</aop:aspect>
</aop:config>
<bean id="whileoperation" class="com.example.demo.WhileOperation">
<property name="num" value="100"/>
</bean>
<bean id="foroperation" class="com.example.demo.ForOperation">
<property name="num" value="100"/>
</bean>
</beans>
<DemoApplication.java>
실행 클래스이다.
xml 설정 파일을 GenericXmlApplicationContext로 받고 해당 id의 Bean들을 생성해주고,
두 Bean의 addTonum() 메소드를 실행해주는 것 뿐이다.
package com.example.demo;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:application.xml");
WhileOperation wfo = ctx.getBean("whileoperation",WhileOperation.class);
wfo.addTonum();
ForOperation foro = ctx.getBean("foroperation",ForOperation.class);
foro.addTonum();
ctx.close();
}
}
실행 결과
@(Annotation)을 이용하는 기법은 다음 포스팅에서 살펴볼 것이다.
'Spring Series > Spring Framework' 카테고리의 다른 글
[Spring] AOP(2) - @(Annotation) 이용 (0) | 2020.12.30 |
---|---|
STS에 Spring Legacy Project가 없을 경우?? (5) | 2020.12.30 |
[Spring] properties 파일(2) (0) | 2020.12.23 |
[Spring] Bean의 생명주기 / properties 파일 (0) | 2020.12.22 |
[Spring] IOC 컨테이너 설정(3) - xml, @(Annotation) 혼용 (0) | 2020.12.22 |
댓글