JAVA

[JAVA]자바와 객체지향(5) - 스프링 삼각형과 설정정보

채야미 2024. 3. 12. 19:01

이 도서를 기반으로 글을 작성하였습니다.

 

 

 

 

스프링 삼각형과 설정정보

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 빈 지정 우선순위
    1. 주입받고자하는 타입으로 매칭을 시도한다. 
    2. 타입이 여러 개면 필드 또는 파라미터 이름으로 매칭을 시도한다.

 

 

 

  • @ Resource 빈 지정 우선순위
    1. 필드 또는 파라미터 이름으로 매칭을 시도한다. 
    2. 타입이 여러 개면 주입받고자하는 타입으로 매칭을 시도한다. 
    정확히 위 그림과 반대입니다.

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