2020년 10월 2일 금요일

스프링어노테이션기반DI/IoC 세터주입/생성자주입/필드주입실습(Annotation based Injection, setter/constructor/field)(자바교육/스프링교육/SpringFramework/스프링프레임워크/스프링학원/자바학원)

스프링어노테이션기반DI/IoC 세터주입/생성자주입/필드주입실습(Annotation based Injection, setter/constructor/field)(자바교육/스프링교육/SpringFramework/스프링프레임워크/스프링학원/자바학원)


https://youtu.be/RzETNGj48ts



http://ojc.asia/bbs/board.php?bo_table=LecSpring&wr_id=862


 

1. 어노테이션 기반 DI


Spring5 에서 어노테이션 기반으로 DI를 하는 방법은 3가지이다. (Constructor Injection, Setter Injection, Field Injection)

XML 기반인 경우에는 Constructor Injection, Setter Injection 만 가능하다.(Bean 요소의 constructor-arg, property 태그를 통해)



2. DI 어떤것을 사용할까?


Field Injection은 의존성 주입이 쉽기 때문에 의존관계가 복잡해질 우려가 있으며, 의존성이 숨어있기에, 즉 생성자, 세터주입과 다르게 의존 관계가 보이지 않아 검증이 어렵다. 또한 필요한 의존성을 가진 클래스를 곧바로 인스턴스화 시킬 수 없다. 그러므로 테스트 코드를 작성할 때 불편하다는 단점이 있다. 

Field Injection은 final을 선언할 수 없다. 그래서 객체가 변할 수 있다.

Setter Inject역시 객체를 주입받은 이후 객체가 변경될 우려가 있다.

Constructor Injection과 달리 Setter Injection에서는 객체가 먼저 생성 된 다음 종속성이 주입된다.



@Controller

public class EmpController {

   @Autowired  //필드주입

   private EmpService empService;

   …

}


@Controller

public class EmpController {

   private EmpService empService;


   @Autowired  //세터주입

   public void) {

      this.empService = empService; setEmpService(EmpService empService

   }

   …

}


스프링 3.x 다큐멘테이션에서는 Setter Injection을 추천, 4.x에서는 더이상 Setter Injection이 아닌 Constructor Injection을 권장한다

Construnctor Inject을 통해 스프링 4.3버전부터는 클래스를 완벽하게 DI 프레임워크로부터 분리할 수 있다. 생성자가 하나인 경우 @Autowired를 붙이지 않아도 된다. 또한 final을 선언할 수 있으므로 객체가 변하지 않도록 할 수 있다. 또한 생성되는 시점에 객체를 주입받으므로 객체들의 주입 순서가 정해져 있어서 순환 의존성도 문제도 알 수 있다. 잘못 설계된 패턴인지 확인할 수 있다.

필수적인 프로퍼티의 경우 Constructor Inject을 사용하고 선택적 프로퍼티의 경우 Setter Injection을 사용한다. 대체로 생성자 주입을 사용하라. 그러나 생성자에 파라미터가 많아지고 복잡해지면 결국 리팩토링 대상이므로 세터 주입도 고려할 만 하다.(생성될 때 받아서 생성 할것도 많은데 객체 주입까지 받으면 복잡해 질 수있다)


@Controller

public class EmpController {

   private EmpService empService;

   @Autowired   //생성자주입

   public void EmpController(EmpService empService)    

   {

      this.empService = empService;

   }

   …

}


3. 세터주입 이란?


Spring5 에서 어노테이션 기반으로 DI를 하는 방법은 3가지이다. (Constructor Injection, Setter Injection, Field Injection)

Spring Setter Injection이란? 객체의 Setter 메소드를 사용하여 Bean 종속성을 주입(필요로 하는 객체를 주입)하는 것입니다. 

Spring Constructor Injection과 달리 Setter Injection에서는 객체가 먼저 생성 된 다음 종속성이 주입됩니다.


db3d955e8763692214ca113c1ff03603_1601691


----------------- pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>setterinjection</groupId>

  <artifactId>setterinjection</artifactId>

  <version>0.0.1-SNAPSHOT</version>

  <name>setterinjection</name>

  <description>setterinjection</description>


  <properties>

<java-version>1.8</java-version>

<org.springframework-version>5.2.9.RELEASE</org.springframework-version>

</properties>

  

  <dependencies>

<dependency>

<groupId>org.springframework</groupId>

<artifactId>spring-context</artifactId>

<version>${org.springframework-version}</version>

</dependency>

</dependencies>

<build>

<sourceDirectory>src</sourceDirectory>

<plugins>

<plugin>

<artifactId>maven-compiler-plugin</artifactId>

<version>3.8.1</version>

<configuration>

<source>1.8</source>

<target>1.8</target>

</configuration>

</plugin>

</plugins>

</build>

</project>

  



----------------- MODEL

package setterinjection;


/*

 * Model

 */

public class Emp {

private String empno;

private String ename;

public Emp(String empno, String ename) {

super();

this.empno = empno;

this.ename = ename;

}

@Override

public String toString() {

return "Emp [empno=" + empno + ", ename=" + ename + "]";

}



public String getEmpno() {

return empno;

}

public void setEmpno(String empno) {

this.empno = empno;

}

public String getEname() {

return ename;

}

public void setEname(String ename) {

this.ename = ename;

}

}





----------------- DAO


package setterinjection;


import java.util.ArrayList;

import java.util.List;


import org.springframework.stereotype.Repository;


@Repository

public class EmpDao {

public List<Emp> getAllEmps() {

List<Emp> emps = new ArrayList<Emp>();

emps.add(new Emp("1", "이종철"));

emps.add(new Emp("2", "오라클자바커뮤니티"));

return emps;

}

}


---------------------- SERVICE


package setterinjection;


import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Service;


@Service

public class EmpService {

private EmpDao empDao;

@Autowired

public void setEmpDao(EmpDao empDao) {

this.empDao = empDao;

}

public List<Emp> getAllEmps() {

return empDao.getAllEmps();

}

}




------------------------ Controller


package setterinjection;


import java.util.List;


import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.stereotype.Controller;


@Controller

public class EmpController {

private EmpService empService;

@Autowired

public void setEmpService(EmpService empService) {

this.empService = empService;

}

public void getAllEmps() {

List<Emp> emps = empService.getAllEmps();

emps.forEach( emp -> System.out.println(emp) );  //jdk 1.8이상

}

}



------------------ TEST MAIN


package setterinjection;


import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;


public class EmpTest {

public static void main(String[] args) {

ApplicationContext factory = new ClassPathXmlApplicationContext("classpath:emp.xml");

EmpController empController = factory.getBean(EmpController.class); 

empController.getAllEmps();

}

}



 


 


 

 

#스프링세터주입, #스프링생성자주입, #세터주입, #생성자주입, #생성자주입어노테이션, #스프링DI, #SetterInjection, #세터주입어노테이션,  #스프링IoC, #SpringDI, #SpringIoC, #자바스프링, #Spring동영상, #Spring강의, #스프링프레임워크, #스프링교육, #스프링학원, #스프링강좌, #스프링강의, #자바학원, #자바, #스프링동영상, #자바동영상, #스프링프레임워크교육, #스프링프레임워크강의, #스프링프레임워크학원 

#스프링DI, #스프링IoC, #SpringDI, #SpringIoC, #자바스프링, #Spring동영상, #Spring강의, #스프링프레임워크, #스프링교육, #스프링학원, #스프링강좌, #스프링강의, #자바학원, #자바, #스프링동영상, #자바동영상, #스프링프레임워크교육, #스프링프레임워크강의, #스프링프레임워크학원

 


스프링 프레임워크 IoC컨테이너/DI개요, DI HelloWorld, 세터주입, 생성자주입 실습(자바교육/스프링교육/SpringFramework/스프링학원)

 

 

1. Spring IoC

 

마틴 파울러는 2004년의글에서 제어의 어떤 측면이 역행되는 것인지에 대한 의문을 제기하고 의존하는 객체를 역행적으로 취득하는 것이라는 결론을 내렸다.  그는 그와 같은 정의에 기초하여 제어 역행이라는 용어에 좀더 참신한 ‘의존성 주입(DI,dependency injection)’이라는 이름을 지어줬다.

IoC(Inversion of Control)는 디자인 패턴, 팩토리 패턴 및 DI (Dependency Injection)와 같은 메커니즘을 통해 달성 할 수 있다.

 

모든 어플리케이션은 비지니스 로직을 수행하기 위해 서로 협업하는 여러 객체들로 이뤄진다. 전통적으로 각 객체는 협업할 객체의 참조를 취득(Emp e = new Emp())해야 하는 책임이 있는데 이것이 의존성이다. 이는 결합도가 높으며 테스트하기 어려운 코드를 만들어 낸다.  

IoC를 적용함으로써 객체들은 시스템 내의 각 객체를 조정하는 어떤 외부의  존재(스프링의 경우 IoC 턴테이너)에 의해 객체참조를 제공받는데 이를 주입(inject)이라고 한다.

따라서 IoC는 한 객체가 협업해야 하는 다른 객체의 참조를 취득하는 방법에 대한 제어의 역행이라는 의미를 갖는다.(new 해서 참조를 취득하지 않고 스프링 IoC 컨테이너로 부터 객체를 주입 받음)

 

 

2. Spring Ioc Container

 

4a6b5e7d8d2b4ae4daec64bc0070c3e2_1601665
 

 

Spring IoC 컨테이너는 객체를 만들고, 연결하고, 구성하고, 생성부터 파괴까지 전체 수명주기를 관리한다.

Spring 컨테이너는 DI(Dependency Injection, 의존성주입)를 사용하여 애플리케이션을 구성하는 구성 요소를 관리한다. 이러한 객체를 Spring Beans 라고 한다.

Spring IoC 컨테이너는 제공된 설정정보(자바빈에 대한 정보)를 읽어 객체를 new하여 생성하고 이름을 부여하고 객체(빈)을 주입해 달라고 하는 곳에 주입을 시키고 객체를 전체적으로 관리한다.

설정정보는 XML 또는 XML을 대신한 어노테이션, 자바 설정파일(자바라이브러리의 클래스를 빈으로 등록하는 경우 주로 사용) 로 정의한다.

 

3. Spring DI

 

IoC를 구현하는 하나의 방법이다.(또한 DL이라고 빈을 룩업하는 것도 이해를 돕기 위해 보면 좋지만 큰 의미 없다.)

class A {

   public static void main(String[] args) {

      B b = new B();    String s = b.sayHello();

   }

}

위 코드에서 “A는 B에 종속된다.” “A는 B를 의존한다.”, “B는 A의 의존객체"라고 한다. A와 B는 종속관계에 있으며 A에서 B의 인스턴스(객체)가 필요하다. Spring IoC 컨테이너는 이러한 종속성을 DI(Dependency Injection)로 해결한다. 

Setter Dependency Injection (SDI) – XML 또는 어노테이션 방식

Constructor Dependency Injection (CDI) - XML 또는 어노테이션 방식

 

 

 

[실습]

0. 전통적인 코딩 방식

 

package spring;

 

class Hello {

void sayHello(String name) {

System.out.println("Hello~ " + name);

}

}

 

public class HelloSpring {

public static void main(String[] args) {

Hello h = new Hello();

h.sayHello("이종철");

}

}

 

 

1. 세터 XML ---------------------------------------------------

 

package spring;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

class Hello1 {

void sayHello(String name) {

System.out.println("Hello~ " + name);

}

}

 

public class HelloSpringSDI1 {

static Hello1 hello;

public void setHello(Hello1 hello) {

this.hello = hello;

}

public static void main(String[] args) {

ApplicationContext factory = new ClassPathXmlApplicationContext("classpath:SDI1.xml");

hello.sayHello("이종철");

}

}

 

 

<?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="h" class="spring.Hello1"/>

<bean id="sdi1" class="spring.HelloSpringSDI1">

<property name="hello">

<ref bean="h"/>

</property>

</bean>

 

</beans>

 

 

 

2. 세터 어노테이션 ---------------------------------------

 

package spring;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.stereotype.Component;

 

@Component

class Hello2 {

void sayHello(String name) {

System.out.println("Hello~ " + name);

}

}

 

@Component

public class HelloSpringSDI2 {

 

static Hello2 hello;

@Autowired

public void setHello2(Hello2 hello) {

this.hello = hello;

}

public static void main(String[] args) {

ApplicationContext factory = new ClassPathXmlApplicationContext("classpath:SDI2.xml");

hello.sayHello("이종철");

}

}

 

 

<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.xsd">

 

<context:component-scan base-package="spring" />

 

</beans>

 

 

 

3. 생성자 XML -----------------------------------

 

package spring;

 

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

 

class Hello3 {

void sayHello(String name) {

System.out.println("Hello~ " + name);

}

}

 

public class HelloSpringSDI3 {

static Hello3 hello;

public HelloSpringSDI3(Hello3 hello) {

this.hello = hello;

}

public static void main(String[] args) {

ApplicationContext factory = new ClassPathXmlApplicationContext("classpath:SDI3.xml");

hello.sayHello("이종철");

}

}

 

 

<?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="h" class="spring.Hello3"/>

<bean id="sdi3" class="spring.HelloSpringSDI3">

<constructor-arg ref="h"/> 

</bean>

 

</beans>

 

 

 

 

4. 생성자 어노테이션 -------------------------------------

 

package spring;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.context.ApplicationContext;

import org.springframework.context.support.ClassPathXmlApplicationContext;

import org.springframework.stereotype.Component;

@Component

class Hello4 {

void sayHello(String name) {

System.out.println("Hello~ " + name);

}

}

 

@Component

public class HelloSpringSDI4 {

static Hello4 hello;

@Autowired

public HelloSpringSDI4(Hello4 hello) {

this.hello = hello;

}

public static void main(String[] args) {

ApplicationContext factory = new ClassPathXmlApplicationContext("classpath:SDI4.xml");

hello.sayHello("이종철");

}

}

 

 

 

<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.xsd">

 

<context:component-scan base-package="spring" />

 

</beans>

 

 

#스프링DI, #스프링IoC, #SpringDI, #SpringIoC, #자바스프링, #Spring동영상, #Spring강의, #스프링프레임워크, #스프링교육, #스프링학원, #스프링강좌, #스프링강의, #자바학원, #자바, #스프링동영상, #자바동영상, #스프링프레임워크교육, #스프링프레임워크강의, #스프링프레임워크학원

 

(C#교육동영상)C# ADO.NET 실습 ODP.NET/ODAC 설치 오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원

  (C#교육동영상)C# ADO.NET 실습  ODP.NET/ODAC 설치  오라클 함수 호출 실습, C#학원, WPF학원, 닷넷학원, 자바학원 https://www.youtube.com/watch?v=qIPU85yAlzc&list=PLxU-i...