[Spring] 스프링에서 DI 의존성 주입 방법

heegon·2025년 11월 3일

목록 보기
11/17

다른 클래스의 메소드나 필드를 사용할 때, 그 클래스의 객체를 생성하여 내부 필드와 메소드에 접근할 수 있다.

문제는 여러 곳(여러 외부)에서 해당 클래스의 필드와 메소드가 필요하다면 매번 객체를 생성해주어야 한다는 것이다.
스프링 웹 프레임워크에서는 이를 해결해주기 위해 객체를 생성할 수 있게 미리 세팅을 해놓고 필요할 때만 불러와서 쓸 수 있게 해놓았다. 이를 의존성 주입 (DI) 라고 한다. 그 방법에는 크게 2가지가 있다.

  • 즉, 자바 빈즈 (데이터 클래스)를 만들고 이를 외부에서 사용하는 방법은 크게 3가지이다.
    1. 객체 생성하여 사용하기 (기존 방식)
    2. XML 파일 이용하기
    3. 어노테이션 사용하여 자바 파일 이용하기

✅ 방법 1번. 객체 만들어 사용하기

ex)

자바빈즈 클래스 (데이터 클래스)

public class Human {

	//필드 2개 (name, age)
	private String name;
    private int age;
    
    //필드 2개에 따른 setter, getter 메소드
    public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

메인 클래스 (외부 클래스)

public class MainClass {
	public static void main(String[] args) {
    	Human human = new Human();
        human.setName("사람1");
        human.setAge(20);
        System.out.println(human.getName() + " 의 나이는 " + human.getAge() + " 입니다.");
    }
}

실행 결과

사람1 의 나이는 20 입니다.


✅ 방법 2번. XML 파일을 이용하는 방법.

xml 파일 생성 방법 : file -> new -> Spring Bean Configuration File
(src/main/resources 폴더에 넣어주면 된다.)

⭐⭐⭐ 핵심 ⭐⭐⭐
AbstractApplicationContext ctx = new GenericXmlApplicationContext("classpath:applicationCTX.xml");

✅✅ XML방식1 (setter 방식)

xml에서 태그를 이용해서 필드에 값 넣어준다.

자바빈즈 클래스 (데이터 클래스)

public class Human {

	//필드 2개 (name, age)
	private String name;
    private int age;
    
    //필드 2개에 따른 setter, getter 메소드
    public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
}

메인 클래스 (외부 클래스)
setter로 사용할 사용 방법
AbstractApplicationContext 객체명 = new GenericXmlApplicationContext("classpath:xml파일명.xml")

public class MainClass {
	public static void main(String[] args) {
  		//⭐핵심
    	AbstractApplicationContext ctx
        	= new GenericXmlApplicationContext("classpath:applicationCTX.xml");
  
        //객체 사용이라면 Human human = new Human();
  		//=new Human() 대신, =ctx.getBean("구분용 아이디", 빈즈클래스명.class) 사용
        Human human = ctx.getBean("humanDataClass", Human.class);
  
        //setter 역할을 xml 파일이 대신해준다. 
        //바로 getter 메소드로 값만 받아와서 외부에서 값 사용하면 된다. 
		System.out.println("이름은 " + human.getName() + " 이고, 나이는 " + human.getAge() + " 입니다.");
        
  		//객체 사용 종료
        ctx.close();
    }
}

applicationCTX.xml

setter 역할을 해주는 xml 파일

java 파일 위치 -> src/main/java
xml 파일 위치 -> src/main/resources
xml파일 위치에서 file -> new -> Spring Bean Configuration File 로 xml 파일 생성하면 된다.

<bean id="humanDataClass" class="heegon.study.spring.Human">
	<property name="name">
    	<value>희곤</value>
    </property>
	<property name="age">
    	<value>20</value>
    </property>
</bean>

실행 결과

이름은 희곤 이고, 나이는 20 입니다.

✅✅ XML방식2 (생성자 방식)

xml에서 태그를 이용해서 필드에 값 넣어준다.

데이터 클래스

public class Human {
	
		//필드 2개 (name, age)
		private String name;
	    private int age;
	    
	    public Human(String name, int age) {
	    	this.name = name;
	    	this.age = age;
	    }
	    
	    public String getName() {
			return name;
		}


		public int getAge() {
			return age;
		}


		public void printHuman() {
	    	System.out.println("이름은 " + getName() + " 이고, 나이는 " + getAge() + " 입니다.");
	    }

}

메인 클래스(외부 클래스)

public class MainClass {
	public static void main(String[] args) {
  		//⭐핵심
    	AbstractApplicationContext ctx
        	= new GenericXmlApplicationContext("classpath:applicationCTX.xml");
  
        //객체 사용이라면 Human human = new Human();
        Human human = ctx.getBean("humanDataClass", Human.class);
  
        //setter 역할을 xml 파일이 대신해준다. 
        //getter 메소드가 없기 때문에, 출력코드를 만들어준 Human 클래스의 printHuman() 메소드를 불러와 사용한다. 
		human.printHuman();
  
  		//객체 사용 종료
        ctx.close();
    }
}  

applicationCTX.xml
setter메소드를 이용할 때는 <property> 태그를 이용하고,
생성자 함수로 필드에 값을 넣을 때는 <constructor-arg> 태그를 이용한다.

	<bean id="humanDataClass" class="heegon.study.spring.Human">
		<constructor-arg>
			<value>희곤</value>
		</constructor-arg>
		
		<constructor-arg>
			<value>20</value>
		</constructor-arg>
	</bean>

실행 결과

이름은 희곤 이고, 나이는 20 입니다.

✅✅ XML방식3 (ArrayList와 같이 여러 값 넣기)

MainClass.java

public class MainClass {

	public static void main(String[] args) {
		
		AbstractApplicationContext ctx 
  			= new GenericXmlApplicationContext("classpath:applicationCTX.xml");
		
		Human human = ctx.getBean("humanDataClass", Human.class);
		
		System.out.println("===========");
		System.out.print("이름 : ");
		System.out.println(human.getName());
		System.out.print("취미는 : ");
		System.out.println(human.getHobbys());
		System.out.print("나이는 : ");
		System.out.println(human.getAge());
		System.out.println("===========");
		
		ctx.close();
	}

}
 

Human.java

ArrayList 타입의 hobbys 변수가 존재한다. 즉, 여러개의 값을 넣어야 하는 경우가 생겼다.

public class Human {
	
	private String name;
	private int age;
	private ArrayList<String> hobbys;
	
	Human(String name, ArrayList<String> hobbys){
		this.name = name;
		this.hobbys = hobbys;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public ArrayList<String> getHobbys() {
		return hobbys;
	}

	public void setHobbys(ArrayList<String> hobbys) {
		this.hobbys = hobbys;
	}
	
}
 

applicationCTX.xml

아래와 같이 태그 내부에 값 을 넣어주기만 하면 된다.

<bean id="humanDataClass" class="kr.study.spring.Human">
		<constructor-arg>
			<value>희곤</value>
		</constructor-arg>
		
		<constructor-arg>
			<list>
				<value>넷플릭스</value>
				<value>운동</value>
				<value>배틀그라운드</value>
			</list>
		</constructor-arg>
		
		<property name="age" value="20"></property>
	</bean> 

✅ 방법 3번. 어노테이션을 사용하는 방법.

(xml 파일 없이 자바 클래스 파일만으로 가능)

⭐⭐⭐ 핵심 ⭐⭐⭐
AnnotationConfigApplicationContext 객체명 = new AnnotationConfigApplicationContext(파일명.class)

✅✅ 어노테이션 방식1 (setter, getter 메소드만으로 구성된 데이터 클래스)

Human.java

setter와 getter로만 이루어진 (생성자함수 사용 X) 데이터 클래스

public class Human {
	
	private String name;
    private int age;
  
  	public String getName() {
			return name;
	}
  
	public void setName(String name) {
			this.name = name;
	}
  
	public int getAge() {
			return age;
	}
  
	public void setAge(int age) {
		this.age = age;
	}
}

MainClass.java

xml방식과 마찬가지로, ctx 객체를 만들어서 .getBean() 메소드를 통해서 데이터값들을 가져올 수 있다.
xml방식과 달리 AnnotationConfigApplicaionContext 클래스를 이용해 ctx 객체를 생성한다.
= new AnnotationConfigApplicationContext(xml역할을 대신해주는 java코드파일명.class); 이다.

public class MainClass {
	public static void main(String[] args) {
		
		AnnotationConfigApplicationContext ctx
		= new AnnotationConfigApplicationContext(ApplicationConfig.class);
		
    	Human human1 = ctx.getBean("human1", Human.class);
    	System.out.println("이름 : " + human1.getName());
    	System.out.println("나이 : " + human1.getAge());
    	
    	ctx.close();
    }
}

ApplicationConfig.java

xml의 역할을 해주는 자바 클래스를 만들고 @Configuration 어노테이션을 사용해서 알려준다. xml 방식과 다른 점은, 데이터 클래스인 Human 의 객체를 만들어준다음에, 내부 메소드(지금은 setter)를 사용해 값을 넣어주고, 마지막에 return 클래스 객체; 를 통해서 다시 객체를 반환해주어야 한다는 것이다.

@Configuration
public class ApplicationConfig {

	@Bean
	public Human human1() {
		Human human = new Human();
		human.setName("희곤");
		human.setAge(20);
		
		return human;
	}
}

pom.xml

추가적으로 자바 클래스를 이용한 어노테이션 방식에서는 반드시 pom 파일 안에 아래와 같이 내용을 추가로 넣어주어야 동작된다.

<dependency>
	<groupId>cglib</groupId>
	<artifactId>cglib</artifactId>
	<version>2.2.2</version>
</dependency>

✅✅ 어노테이션 방식2 (생성자 함수를 이용한 데이터 클래스)

Human.java

public class Human {
	
		//필드 2개 (name, age)
		private String name;
	    private int age;
	    
		//생성자 함수로 이름과 나이를 넣어줌.
	    public Human(String name, int age) {
	    	this.name = name;
	    	this.age = age;
	    }
	    
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}

}

MainClass.java

public class MainClass {
	public static void main(String[] args) {
		
		AnnotationConfigApplicationContext ctx
		= new AnnotationConfigApplicationContext(ApplicationConfig.class);
		
  	Human human1 = ctx.getBean("human1", Human.class);
  	System.out.println("이름 : " + human1.getName());
  	System.out.println("나이 : " + human1.getAge());
  	
  	ctx.close();
  }
}

ApplicationConfig.java

@Configuration
public class ApplicationConfig {

	@Bean
	public Human human1() {
		//생성자 함수이기 때문에 다음과 같이 값을 넣어준다.
		Human human = new Human("희곤", 20);
		//return 객체명은 똑같이 필요하다. 
		return human;
	}
}

✅✅ 어노테이션 방식3 (ArrayList 같은 여러 값을 넣어주어야 하는 경우)

Human.java

public class Human {
	
		//필드 3개 (name, age, hobbys)
		private String name;
	    private int age;
	    private ArrayList<String> hobbys;
	    
	    //생성자함수
	    public Human(String name, int age) {
	    	this.name = name;
	    	this.age = age;
	    }
	    
	    //setter, getter
		public String getName() {
			return name;
		}
		public void setName(String name) {
			this.name = name;
		}
		public int getAge() {
			return age;
		}
		public void setAge(int age) {
			this.age = age;
		}

		public ArrayList<String> getHobbys() {
			return hobbys;
		}

		public void setHobbys(ArrayList<String> hobbys) {
			this.hobbys = hobbys;
		}
		
}

MainClass.java

public class MainClass {
	public static void main(String[] args) {
		
		AnnotationConfigApplicationContext ctx
		= new AnnotationConfigApplicationContext(ApplicationConfig.class);
		
  	Human human1 = ctx.getBean("human1", Human.class);
  	System.out.println("이름 : " + human1.getName());
  	System.out.println("나이 : " + human1.getAge());
  	System.out.println("취미 : " + human1.getHobbys());
  	
  	ctx.close();
  }
}

ApplicationConfig.java

여러 값을 넣어주어야 하는 경우에는 데이터타입의 객체를 새롭게 만들고, .add() 함수 안에 값을 넣어주어 추가해준다. 그리고 setter 메소드에 객체를 넣어서 값을 넣어주어야 한다. (생성자 함수라면 생성자 함수 소괄호 안에 넣어주면 된다.)

@Configuration
public class ApplicationConfig {

	@Bean
	public Human human1() {
		//생성자 함수이기 때문에 다음과 같이 값을 넣어준다.
		Human human = new Human("희곤", 20);
		//ArrayList 와 같이 여러 값을 넣어주어야 하는 경우
		ArrayList<String> hobbys = new ArrayList<String>();
		hobbys.add("축구");
		hobbys.add("배틀그라운드");
		human.setHobbys(hobbys);
		//return 객체명은 똑같이 필요하다. 
		return human;
	}
}

...끝!

profile
❤️

0개의 댓글