[JAVA]자바와 객체지향(5) - 스프링 삼각형과 설정정보
이 도서를 기반으로 글을 작성하였습니다.
스프링 삼각형과 설정정보
1. IoC/ DI - 제어의 역전/ 의존성 주입
2. AOP - Aspect, 관점, 핵심 관심사, 횡단 관심사
3. PSA - 일관성 있는 서비스 추상화
1. IoC/ DI - 제어의 역전/ 의존성 주입
의존성이라는 것은 new
Car 코드 안에서 new Tire()를 하면 Car는 Tire를 의존한다!
Spring의 Bean 설정을 이용해
서로 의존관계에 있는 Class들의 생성과 의존성 주입을 통해
의존 관계를 느슨하게 할 수 있음
스프링 설정파일을 적용시
ApplicationContext 코드와 getBean 하는 것을 제외하면
메인클래스에서 변화한 것이 없습니다.
ApplicationContext context = new FileSystemXmlApplicationContext("/src/main/java/expert002/expert.xml");
Tire tire = (Tire)context.getBean("tire");
Car car = (Car)context.getBean("car");
car.setTire(tire);
위와 같이 어떠한 bean을 사용할 것인지 xml 파일에 등록된 빈을 통해 특정 인터페이스의 구현클래스를 지정해주었습니다.
1. 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"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
<bean id="koreaTire" class="expert003.KoreaTire"></bean>
<bean id="americaTire" class="expert003.AmericaTire"></bean>
<bean id="car" class="expert003.Car">
<property name="tire" ref="koreaTire"></property>
</bean>
</beans>
위와 같이 빈을 설정하는 xml 파일을 생성해줍니다.
id 속성은 빈을 식별하는 데 사용되고, class 속성은 해당 빈이 어떤 클래스를 인스턴스화할지 지정합니다.
property 속성은
car.setTire(tire) 하던 부분을 xml 파일의 property 태그를 이용해 대체하는 것입니다.
<!-- applicationContext.xml -->
<bean id="myBean" class="com.example.MyBean">
<!-- 생성자를 통한 의존성 주입 -->
<constructor-arg ref="anotherBean" />
</bean>
contructor-arg 태그를 이용하면
다른 bean id를 넣어서 이런식으로 생성자를 통한 의존성 주입도 가능합니다.
2. 어노테이션을 이용한 의존성 주입
package expert004;
import org.springframework.beans.factory.annotation.Autowired;
public class Car {
@Autowired
Tire tire;
public String getTireBrand() {
return "장착된 타이어: " + tire.getBrand();
}
}
위의 예제에서 @Autowired라는 어노테이션을 사용하여
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"
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-3.1.xsd">
<context:annotation-config />
<bean id="tire" class="expert004.KoreaTire"></bean>
<bean id="americaTire" class="expert004.AmericaTire"></bean>
<bean id="car" class="expert004.Car"></bean>
</beans>
위 파일을 보면
<context:annotaion-config /> 을 추가하여 어노테이션 기반으로 의존성 주입을 가능하게 하고
propety 태그가 사라진 것을 확인 할 수 있습니다.
- @ Autowired 빈 지정 우선순위
- 주입받고자하는 타입으로 매칭을 시도한다.
- 타입이 여러 개면 필드 또는 파라미터 이름으로 매칭을 시도한다.
- @ Resource 빈 지정 우선순위
- 필드 또는 파라미터 이름으로 매칭을 시도한다.
- 타입이 여러 개면 주입받고자하는 타입으로 매칭을 시도한다.
public class MyComponent {
@Resource
private MyResource myResource;
// 나머지 코드...
}
이 코드에서 myResource라는 필드이름이 있으니 이러한 이름으로 지정되고
MyResource Class를 구현한 빈 먼저 매치하고
없다면 같은 타입인 빈을 찾아 매치한다는 의미입니다.
@Autowired와 @Resource의 비교
@Autowired | @Resource | |
제공자 | SpringFramework | 표준 Java |
소속 패키지 | org.springframework .beans.factory.annotation .Autowired |
javax.annotation.Resource |
bean 검색 | byType 먼저, 못 찾으면 byName | byName 먼저, 못 찾으면 byType |
특이사항 byName 강제하기 |
@Qualifier("") 협업 @Autowired @Qualifier("tire1") |
name 어트리뷰트 @Resource(name="tire1") |
2. AOP - Aspect, 관점, 핵심 관심사, 횡단 관심사
직역하면 관점 지향 프로그래밍입니다.
스프링의 DI가 의존성에 대한 주입이라면,
스프링 AOP는 로직 주입알고 볼 수 있습니다.
위의 그림처럼 서로 다른 모듈에서 반복적으로 나타나는 부분이 있는데, 이것이 바로 횡단 관심입니다.
DB를 사용할때 insert, update, delete, select 모두 패턴처럼
DB 커넥션 준비
Statement 객체 준비
try {
DB 커넥션 연결
Statement 객체 셋팅
insert / update / delete / select 실행
} catch ... {
예외 처리
} catch ... {
예외 처리
} finaly {
DB 자원 반납
}
일어나는 빨간색 부분이 있는데 이것이 바로 횡단 관심 사항입니다.
이러한 반복되는 코딩을 줄이기 위해 AOP라는 것을 사용해서 하나로 묶을 수 있습니다.
아래의 Boy와 Girl 예제를 통해 알아보겠습니다.
먼저 IPerson이라는 인터페이스는 집에서 공통적으로 일어나는 일들인 housework()라는 메소드를 가지고 있습니
package aop002;
public interface IPerson {
void housework();
}
package aop002;
public class Boy implements IPerson {
public void housework() {
System.out.println("컴퓨터로 게임을 한다.");
}
}
package aop002;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Start {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("/src/main/java/aop002/expert.xml");
IPerson romeo = (IPerson)context.getBean("boy");
romeo.housework();
}
}
만든 Boy클래스를 빈에 등록하고 사용할 수 있게 Start 클래스에 위와같이 설정합니다.
<?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/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<aop:aspectj-autoproxy />
<bean id="myAspect" class="aop002.MyAspect" />
<bean id="boy" class="aop002.Boy" />
</beans>
xml 설정파일에 스프링 AOP를 위한 설정파일 입니다.
<aop:aspectj-autoproxy />
를 톨해 aop 기능을 import 하고
<bean id="myAspect" class="aop002.MyAspect" />
<bean id="boy" class="aop002.Boy" />
Boy 클래스와 AOP클래스인 myAspect라는 클래스를 bean으로 등록합니다.
aop002.MyAspect.java 클래스는 아래와 같습니다.
package aop002;
import org.aspectj.lang.annotation.Aspect;import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.JoinPoint;
@Aspectpublic class MyAspect {
@Before("execution(public void aop002.Boy.housework())")
public void before(JoinPoint joinPoint){
System.out.println("얼굴 인식 확인: 문을 개방하라");
//System.out.println("열쇠로 문을 열고 집에 들어간다.");
}
}
@Aspect 는 이 클래스는 이제 AOP 에서 사용하도록 하겟다는 의미이며,
@Before 는 주어진 메소드의 실행 전에 이 메소드를 실행하겠다는 뜻입니다.
JoinPoint는 @Before에서 선언된 메소드인 aop002.Boy.housework() 입니다.
이제 Start class를 실행하면
INFO : org.springframework.context.support.FileSystemXmlApplicationContext - Refreshing org.springframework.context.support.FileSystemXmlApplicationContext@a981ca: startup date [Tue Jan 22 17:42:47 KST 2013]; root of context hierarchy
INFO : org.springframework.beans.factory.xml.XmlBeanDefinitionReader - Loading XML bean definitions from file [C:\workspace_spring\ExpertSpring30\src\main\java\aop002\expert.xml]
INFO : org.springframework.beans.factory.support.DefaultListableBeanFactory - Pre-instantiating singletons in org.springframework.beans.factory.support.DefaultListableBeanFactory@12b7eea: defining beans [org.springframework.aop.config.internalAutoProxyCreator,myAspect,boy]; root of factory hierarchy
얼굴 인식 확인: 문을 개방하라
컴퓨터로 게임을 한다.
다음과 같이 나오는 것을 확인 할 수 있습니다.
한편 실행결과를 보면 @Before로 만들어진 before 메서드가 실행시간(Runtime)에 위 그림과 같이 주입되는 것을 볼 수 있습니다.
스프링 AOP가 interface를 기반으로 하기때문에 (자바 다이나믹 프록시를 사용)
윈래의 종단 관심사였던 부분이 사라지고 IPerson이라는 클래스를 impliment 하는 코드만 추가 되었습니다.
원래라면 프록시 없이
위 그림과 같이 진행되었어야할 코드가 aop를 적용시킴으로서
위와같이 romeo.homwork()를 호출하면 그 앞의 proxy가 요청을 받아 진짜 remeo 객체에게 전달을 합니다.
그리고 그 전달하는 과정에서 프록시는 다른 여러가지 조작을 할 수 있습니다.
이러한 기능을 사용하는 것이 Spring Proxy입니다.
따라서 <aop:aspectj-autoproxy />는
Spring Framework에게 AOP Proxy를 자동으로 사용하라고 알려주는 지시자입니다.
결론
Spring AOP 는 interface 기반이다.
Spring AOP 는 Proxy 기반이다.
Spring AOP 는 runtime 기반이다.
++++ aop 사용예시
캐싱을 aop로 하는 경우가 있음
AOP 용어 정리해보기
- Aspect (관점):
- Aspect는 AOP에서 핵심 비즈니스 로직에서 분리된 모듈화된 단위
- 보통 횡단 관심사(cross-cutting concern)를 처리하는 코드와 관련이 있습니다. 예를 들면 로깅, 트랜잭션 처리, 보안 등이 있습니다.
- 부가기능을 의미
- Advisor (조언자):
- Advisor는 어떤 관심사를 언제, 어디에 적용할지를 정의하는 역할을 합니다.
- Advisor는 Pointcut과 Advice를 결합하여 어드바이스를 특정 지점에 적용합니다.
- Advice (어드바이스):
- Advice는 실제로 특정 지점에서 실행되는 코드 블록을 나타냅니다.
- Before, After, Around 등의 Advice 종류가 있으며, 특정 지점에서 실행될 코드를 정의합니다.
- 부가기능을 담은 구현체
- Pointcut (포인트컷):
- Pointcut은 어떤 지점(Joinpoint)에서 Advice를 적용할 것인지를 정의하는 표현식이나 규칙입니다.
- 특정 메소드, 패키지, 클래스 등을 지정하여 Advice가 적용되는 위치를 결정합니다.
- Joinpoint (조인포인트):
- Joinpoint는 프로그램 실행 중에 Aspect가 적용되는 특정 지점을 나타냅니다.
- 메소드 호출, 객체 생성, 필드에서 값을 꺼내오는 것 등
참고 자료
https://www.yes24.com/Product/Goods/17350624
스프링 입문을 위한 자바 객체 지향의 원리와 이해 - 예스24
자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량 애플리케이션 프레임워크인 스프링은 자바와 객체 지향이라는 기반 위에 굳건히 세워져 있다. 따라서 스프링을 제대로 이해하고 활용
www.yes24.com