4차산업혁명의 일꾼/Java&Spring웹개발과 서버 컴퓨터

Spring DI와 AOP

르무엘 2023. 3. 19. 05:39

스프링의 정석 : 남궁성과 끝까지 간다

Spring DI와 AOP

스프링 DI는 파사드 패턴(API 인터페이스),

AOP는 프록시패턴(복제)

 

1. Spring DI

 

하기 코드를 보면 수동으로 car , engine 객체를 호출할수 있으나

하기와 같이 config.txt 파일을 만들어 바로 주입시킬 수 있다.

car=com.fastcampus.ch3.diCopy2.Truck
engine=com.fastcampus.ch3.diCopy2.Engine

 

config.txt를 통해 DI를 쉽게 하는 모습과 car, engine 객체 수동으로 만들어 호출하는 모습이

코드 내에 다 보인다.

package com.fastcampus.ch3.diCopy1;

import java.io.FileReader;
import java.util.Properties;

class Car {}
class SportsCar extends Car{}
class Truck extends Car {}
class Engine {}

public class Main1 {
    public static void main(String[] args) throws Exception {
        Car car = (Car)getObject("car");
        Engine engine = (Engine) getObject("engine");
        System.out.println("car = " + car);
        System.out.println("engine = " + engine);
    }
    static Object getObject(String key) throws Exception {
        Properties p = new Properties();
        p.load(new FileReader("config.txt"));

        Class clazz = Class.forName(p.getProperty(key));

        return clazz.newInstance();
    }

    static Car getCar() throws Exception {
        Properties p = new Properties();
        p.load(new FileReader("config.txt"));

        Class clazz = Class.forName(p.getProperty("car"));

        return (Car)clazz.newInstance();
    }
}

 

하기 그림의 Spring Container는 ApplicationContext라고 보면 되며 Bean 생성 등 BeanFactory를 확장해서 여러기능을 추가 정의

하기 AapplicationContext는 xml과 java 코드로  비교에서 DI를 하는데

자바코드를  더 많이쓴다.

 

Junit Test 에서 DI를 3가지 한 모습

2. AOP

 

하기 코드는 AOP의 기본 

before

코드

after

package com.fastcampus.ch3.aop;

import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class AopMain {
    public static void main(String[] args) throws Exception {
        MyAdvice myAdvice = new MyAdvice();

        Class myClass = Class.forName("com.fastcampus.ch3.aop.MyClass");
        Object obj = myClass.newInstance();

        for(Method m : myClass.getDeclaredMethods()) {
            myAdvice.invoke(m, obj, null);
        }
    }
}

class MyAdvice {
    Pattern p = Pattern.compile("a.*");

    boolean matches(Method m){
        Matcher matcher = p.matcher(m.getName());
        return matcher.matches();
    }

    void invoke(Method m, Object obj, Object... args) throws Exception {
        if(m.getAnnotation(Transactional.class)!=null)
            System.out.println("[before]{");

        m.invoke(obj, args); // aaa(), aaa2(), bbb() 호출가능

        if(m.getAnnotation(Transactional.class)!=null)
            System.out.println("}[after]");
    }
}

class MyClass {
    @Transactional
    void aaa() {
        System.out.println("aaa() is called.");
    }
    void aaa2() {
        System.out.println("aaa2() is called.");
    }
    void bbb() {
        System.out.println("bbb() is called.");
    }
}

 

aop는 변경에 유리하게( 관심사 분리)

코드를 before 부가 기능, around (핵심기능), after 부가기능

 

SQL의 join처럼 중복제거 하기위해

횡단 관심사라 할 수 있는 부가기능을 동적으로 추가

 

AOP 관련 용어는 하기와 같고

해당 target 에 부가기능 advice 가 추가되어

proxy target에 advice가 동적으로 추가되어 생성된 객체이다.

핵심기능(join point)들이 시행된다.

 

aop-context 설정 : aop:aspectj-autoproxy 설정 

3. @Transactional

root-context.xml 에서 transactionManager 빈과 tx:annotation:driven

@Transcational 의 속성

LIST