본문 바로가기

Spring

@Autowired

@Autowired란

각 상황에 맞는 Bean을 IOC 컨테이너에서 자동으로 주입하게 만드는 것

 

@Autowired를 사용하는 이유 : 편리함

 

@Autowired 사용 전

public class AutowiredService {

    private Autowiredrepository autowiredrepository;

    public AutowiredService(Autowiredrepository autowiredrepository){
        this.autowiredrepository = autowiredrepository;
    }
}

AutowiredRepository를 전달반고 변수로 할당함

그럼 repository를 service 에 주입하기 위해서

public class AutowiredService {

    private Autowiredrepository autowiredrepository;

    public AutowiredService(Autowiredrepository autowiredrepository){
        this.autowiredrepository = autowiredrepository;
    }
}

이렇게 xml로 bean 설정을 해주어야 함

아니면 java class에 Bean 설정을 해주어야 함

@Configuration
public class ApplicationConfig {
    @Bean //메소드
    public Autowiredrepository autowiredrepository(){
        return new AutowiredRepository();
    }
    @Bean
    public AutowiredService autowiredService(){
        return new AutowiredService(AutowiredRepository());
    }
}

@Autowired를 사용하면 객체 의존성을 가지는 부분에 annotation을 사용하면 된다

@Service
public class AutowiredService {

    private Autowiredrepository autowiredrepository;

    
    @Autowired
    public AutowiredService(Autowiredrepository autowiredrepository){
        this.autowiredrepository = autowiredrepository;
    }
}

repository에 annotation을 달아서 Bean으로 등록해주고 의존성 주입이 되게 만들면 된다

@Repository
public interface Autowiredrepository  {
}

직접적으로 사용하는 것보다는 스프링 ioc에서 디펜던시를 주입하는 방법이 더 많이 쓰임

 

TMI : Spring 4.3부터 클래스에 생성자가 하나이고, 생성자로 주입받는 레퍼런스 변수들이 빈으로 등록되어있다면 자동으로 주입해주도록 기능이 추가 됨

@Autowired를 생략하여 사용 가능함

 

사용할 수 있는곳

Field Setter 생성자

 

@Autowired-1

필드에 바로 주입을 받는 방법

(final을 붙이면 안된다 / 인스턴스를 무조건 붙여야 하는 것이라서 붙이면 안된다 )

@Autowired

Private MainRepository main;

@Autowired-2

Setter에 @Autowired를 붙이는 방법

final을 붙이면 안된다

@Autowired

Public void SetMain(MainRepository main){

this.main = main;

 

인스턴스를 만든 후 setter 를 통해 ioc 컨테이너의 빈 중 MainRepository 타입을 찾아서 넣어준다

 

  • final이란 : 정의하고 변경하지 못하도록 할때 사용

상수, 클래스, 메서드 3가지 경우에 사용 가능

1. 상수 : final 타입 상수명

final int cnt; 
final int cnt=1;

cnt =10

//이렇게 사용을 하면 에러가 난다

2. 메서드 : final 반환형 메서드명 (매개변수){}

ovrriding을 못하게 만든다

class study{

	public final void study1(){
		//내용정의
	}
}
public class Main extends study{
	//public test2(){} compile error: final method는 오버라이딩 못함
}

3.클래스 상속 : final class 클래스{}

final class Test{

int test;

}

class에 Final 키워드는 상속을 못하게 할때 사용

final을 사용한 test는 객체를 생성할 수 없다

final의 장점은 객체를 바꿔치기 할 수 없다

 

@Autowired-3

레퍼런스에서 권장하는 방법  -> 생성자

필수적으로 사용해야 하는 레퍼런스 없이는 인스턴스를 만들지 못하도록 강제 할 수 있음

Private final MainRepository main;

Public void SetMain(MainRepository main){
this.main = main;
}

[생성자를 통한 의존성 주입의 장점]

-의존성 주입이 필요한 필드를 final 로 선언하여 Immutable 하게 사용가능

-의존관계가 설정되지 않으면 객체 생성이 불가능하기 때문에 null을 주입하지 않는 이상 NullPointError 를 방지할 수 있다

-테스트코드 작성 용이(필드 인젝션이면 단위테스트시 의존관계를 가지는 객체를 생성해서 주입할 수가 없음 / 생성자를 사용해 작성되었다면 객체를 생성할때 원하는 구현체를 넘겨주면 되고 구현체를 넘겨주지 않으면 객체 생성 자체가 불가능하기 때문에 테스트에 용이)

 

 

단, 순환참조가 발생할 수 있음

(순환 참조가 발생했을 때 가장 좋은 해결책은 다시 설계 하는 것ㅎㅎ)

A와 b가 서로를 참조한다 (생성자 인젝션 사용)

둘다 생성이 되지 않는다. -> 의존성 주입이 안되면 어플리케이션이 뜨지 않는다

컨테이너가 빈을 생성하는 시점에서 객체생성에 사이클 관계가 생기기 때문

(필드 주입이나, 수정자 주입은 객체 생성 시점에 순환참조가 일어나는지 아닌지 알 방법이 없다.)

이런 경우 생성자 인젝션 대신에 Setter 인젝션이나 field 인젝션을 사용하면  상호 참조하는 의존성 문제 해결 가능

 

 

https://galid1.tistory.com/512

https://www.youtube.com/watch?v=IVzYerodIyg

'Spring' 카테고리의 다른 글

페이징처리  (0) 2021.05.10
hibernate란?  (0) 2021.05.09
Spring VS Node.js  (0) 2021.04.25