๐ŸŒฟ Spring

Spring DI(์˜์กด์ฃผ์ž…), @Autowired (์˜์กด ์ž๋™์ฃผ์ž…)

์—ฐ_์šฐ๋ฆฌ 2022. 4. 2. 15:59
๋ฐ˜์‘ํ˜•

๋ชฉ์ฐจ

     

     

    ์˜์กด์ฃผ์ž… ๋ฐฉ๋ฒ•

    ์„ค์ • ํด๋ž˜์Šค์—์„œ ์ง์ ‘ ์˜์กด ์ฃผ์ž…

    ์„ค์ •ํด๋ž˜์Šค์—์„œ ์˜์กด๊ฐ์ฒด๋ฅผ ์ง์ ‘ ์ฃผ์ž…ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. 

    @Configuration
    public class AppCtx {
        @Bean
        public MemberDao memberDao(){
            return new MemberDao();
        }
    
        @Bean
        public MemberRegisterService memberRegisterService(){
            return new MemberRegisterService(memberDao());
        }
    
        @Bean
        public ChangePasswordService changePasswordService(){
            ChangePasswordService changePasswordService = new ChangePasswordService();
            changePasswordService.setMemberDao(memberDao());
            return changePasswordService;
        }
    }

     

     

    ์ž๋™ ์˜์กด ์ฃผ์ž…

    ์„ค์ •ํด๋ž˜์Šค์—์„œ ์ง์ ‘ ์ฃผ์ž…ํ•˜์ง€ ์•Š๊ณ , ์Šคํ”„๋ง์ด ์ž๋™์œผ๋กœ ์˜์กด ๊ฐ์ฒด๋ฅผ ์ฃผ์ž…ํ•ด์ฃผ๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

     

    ์„ค์ •ํด๋ž˜์Šค์—์„œ ์ƒ์„ฑ์ž, setter๋กœ memberDao๋ฅผ ์ฃผ์ž…ํ•ด์ฃผ๋Š” ์ฝ”๋“œ๋ฅผ ๋ชจ๋‘ ์ฃผ์„์ฒ˜๋ฆฌํ•œ๋‹ค.

    @Configuration
    public class AppCtx {
        @Bean
        public MemberDao memberDao(){
            return new MemberDao();
        }
    
        @Bean
        public MemberRegisterService memberRegisterService(){
    //        return new MemberRegisterService(memberDao());
            return new MemberRegisterService();
        }
    
        @Bean
        public ChangePasswordService changePasswordService(){
            ChangePasswordService changePasswordService = new ChangePasswordService();
    //        changePasswordService.setMemberDao(memberDao());
            return changePasswordService;
        }
    
    }

     

    ์˜์กด์„ ์ฃผ์ž…๋ฐ›๋Š” ํด๋ž˜์Šค์—์„œ ํ•„๋“œ ๋˜๋Š” Setter๋ฉ”์„œ๋“œ์— @Autowired๋ฅผ ๋ถ™์ธ๋‹ค.

    (์—ฌ๊ธฐ์„œ ์ƒ์„ฑ์ž์— @Autowired๋ฅผ ๋ถ™์ด๋ฉด AppCtx์—์„œ @Bean์„ ์ƒ์„ฑํ•  ๋•Œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•œ๋‹ค. )

    public class MemberRegisterService {
        @Autowired	//โญ
        private MemberDao memberDao;
    
    //    constructor DI
    //    public MemberRegisterService(MemberDao memberDao) {
    //        this.memberDao = memberDao;
    //    }
    
        public Long regist(RegisterDTO req){
            //ํšŒ์›๊ฐ€์ž… ๋กœ์ง
            ...
        }
    }
    public class ChangePasswordService {
        @Autowired	//โญ
        private MemberDao memberDao;
    
    //    @Autowired //โญ ์—ฌ๊ธฐ์— ๋ถ™์—ฌ๋„๋œ๋‹ค.
    //    public void setMemberDao(MemberDao memberDao) {
    //        this.memberDao = memberDao;
    //    }
    
        public void changePassword(String email, String oldpwd, String newpwd){
            //๋น„๋ฐ€๋ฒˆํ˜ธ ๋ณ€๊ฒฝ๋กœ์ง
            ...
        }
    }

     

    @Autowired ์–ด๋…ธํ…Œ์ด์…˜์„ ํ•„๋“œ๋‚˜ setter๋ฉ”์„œ๋“œ์— ๋ถ™์ด๋ฉด 

    ์Šคํ”„๋ง ์ปจํ…Œ์ด๋„ˆ๋Š” ํƒ€์ž…์ด ์ผ์น˜ํ•˜๋Š” Bean๊ฐ์ฒด๋ฅผ ์ฐพ์•„ ์ฃผ์ž…ํ•ด์ค€๋‹ค.

     

     

    @Autowired ์˜์กด ์ฃผ์ž… ์‹œ ํƒ€์ž… ์ผ์น˜ํ•˜๋Š” Bean์ด ์—†๋Š” ๊ฒฝ์šฐ

    UnsatisfiedDependencyException ๋ฐœ์ƒ

     

     

    @Autowired ์˜์กด ์ฃผ์ž… ์‹œ ํƒ€์ž… ์ผ์น˜ํ•˜๋Š” Bean์ด 2๊ฐœ ์ด์ƒ์ธ ๊ฒฝ์šฐ -> @Qualifier ์–ด๋…ธํ…Œ์ด์…˜ ์‚ฌ์šฉ

    @Configuration
    public class AppCtx {
        @Bean
        public MemberDao memberDao1(){	//โญ
            return new MemberDao();
        }
    
        @Bean
        public MemberDao memberDao2(){	//โญ
            return new MemberDao();
        }
    
        @Bean
        public MemberRegisterService memberRegisterService(){
            return new MemberRegisterService();
        }
    
        @Bean
        public ChangePasswordService changePasswordService(){
            return new ChangePasswordService();
        }
    }
    public class MemberRegisterService {
        @Autowired
        private MemberDao memberDao;
        ...
    }
    
    public class ChangePasswordService {
        @Autowired
        private MemberDao memberDao;
        ...
    }

     

    ๊ทธ๋ƒฅ ์‹คํ–‰ํ•˜๋ฉด NoUniqueBeanDefinitionException ๋ฐœ์ƒ

     

     

    @Qualifier๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

    @Configuration
    public class AppCtx {
        @Bean
        @Qualifier("memberDaoForRegister") //โญ
        public MemberDao memberDao1(){
            return new MemberDao();
        }
    
        @Bean
        public MemberDao memberDao2(){
            return new MemberDao();
        }
    
        @Bean
        public MemberRegisterService memberRegisterService(){
            return new MemberRegisterService();
        }
    
        @Bean
        public ChangePasswordService changePasswordService(){
            return new ChangePasswordService();
        }
    }
    public class MemberRegisterService {
        @Autowired
        @Qualifier("memberDaoForRegister") //โญ
        private MemberDao memberDao;
    
        public Long regist(RegisterDTO req){
            //ํšŒ์›๊ฐ€์ž… ๋กœ์ง
        }
    }

     

    AppCtx์˜ @Bean ๋“ฑ๋ก ์‹œ @Qualifier๋กœ ์ด๋ฆ„ ์ง€์ •, @Autowired๋กœ ๋นˆ ์ฃผ์ž… ์‹œ @Qualifier๋กœ ์ด๋ฆ„ ์ง€์ •

    ์–‘์ชฝ์— ์ ์–ด์ฃผ์–ด์„œ ๋นˆ์˜ ์ด๋ฆ„์œผ๋กœ ๊ตฌ๋ถ„ํ•œ๋‹ค.

    (๋™์ผ ํƒ€์ž… ๋นˆ์ด 2๊ฐœ์ผ๋•Œ, ํ•˜๋‚˜์—๋งŒ Qualifier๋ฅผ ๋ถ™์—ฌ๋„ ๋‘ ๋นˆ์„ ๊ตฌ๋ถ„ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋ฅ˜์—†์ด ์‹คํ–‰ ๊ฐ€๋Šฅํ•˜๋‹ค)

     

     

     

    ์ƒ์œ„/ํ•˜์œ„ ํƒ€์ž… ๊ด€๊ณ„์™€ ์ž๋™์ฃผ์ž…

    public class MemberParentPrinter {
    }
    
    
    public class MemberChildPrinter extends MemberParentPrinter{
    }

    ์ƒ์†๊ด€๊ณ„์—์„œ @Qualifier ์• ๋…ธํ…Œ์ด์…˜์„ ์•ˆ๋ถ™์ธ๋‹ค๋ฉด ์ด๊ฒƒ๋„ NoUniqueBeanDefinitionException์ด ๋ฐœ์ƒํ•œ๋‹ค.

     

     

     

    @Autowired ํ•„์ˆ˜ ์—ฌ๋ถ€

    @Autowired๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ํƒ€์ž…์— ํ•ด๋‹นํ•˜๋Š” ๋นˆ์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด Exception์ด ๋ฐœ์ƒํ•œ๋‹ค.

     

    @Autowired(required = false)
    public void setDateFormatter(DateTimeFormatter dateTimeFormatter){
    	this.dateTimeFormatter = dateTimeFormatter;
    }
    
    @Autowired
    public void setDateFormatter(Optional<DateTimeFormatter> dateTimeFormatter){
    	this.dateTimeFormatter = dateTimeFormatter;
    }
    
    @Autowired
    public void setDateFormatter(@Nullable DateTimeFormatter dateTimeFormatter){
    	this.dateTimeFormatter = dateTimeFormatter;
    }

    ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ํ•„์ˆ˜๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ์—๋Š”

    @Autowired ์• ๋…ธํ…Œ์ด์…˜์˜ required ์†์„ฑ์„ false๋กœ ์ง€์ •ํ•˜๊ฑฐ๋‚˜,

    Optional์„ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜, @Nullable์„ ์‚ฌ์šฉํ•˜์—ฌ ์ž๋™์ฃผ์ž…์„ ์ˆ˜ํ–‰ํ•˜์ง€ ์•Š์œผ๋ฉด๋œ๋‹ค.

     

    ์œ„์˜ ๋ฐฉ์‹์€ ํ•„๋“œ์—๋„ ๊ทธ๋Œ€๋กœ ์ ์šฉ๋œ๋‹ค.

    @Autowired(required = false)
    private DateTimeFormatter dateTimeFormatter;
    
    @Autowired
    private Optional<DateTimeFormatter> dateTimeFormatter;
    
    @Autowired
    @Nullable
    private DateTimeFormatter dateTimeFormatter;

     

     

     

    ์ƒ์„ฑ์ž ์ดˆ๊ธฐํ™”์™€ ํ•„์ˆ˜ ์—ฌ๋ถ€ ์ง€์ •

    public class MemberPrinter{
    	private DateTimeFormatter dateTimeFormatter;
        
        public MemberPrinter(){
        	dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy๋…„ MM์›” dd์ผ");
        }
        
        @Autowired(required = false)
        public void setDateTimeFormatter(DateTimeFormatter dateTimeFormatter){
        	this.dateTimeFormatter = dateTimeFormatter;
        }
    }

    ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด DateTimeFormatter๋Š” ๊ธฐ๋ณธ์ƒ์„ฑ์ž์—์„œ ์ดˆ๊ธฐํ™” ๋œ ๊ฐ’("yyyy๋…„ MM์›” dd์ผ")์„ ์‚ฌ์šฉํ•œ๋‹ค.

     => required = false๋Š” ๋งค์นญ๋˜๋Š” ๋นˆ์ด ์—†๋‹ค๋ฉด ์•„๋ฌด๊ฒƒ๋„ ํ•˜์ง€ ์•Š๋Š”๋‹ค.

     => ๊ธฐ๋ณธ์ƒ์„ฑ์ž์˜ ์ดˆ๊ธฐํ™” ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š”๋‹ค. 

     

     

    public class MemberPrinter{
    	private DateTimeFormatter dateTimeFormatter;
        
        public MemberPrinter(){
        	dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy๋…„ MM์›” dd์ผ");
        }
        
        @Autowired
        public void setDateTimeFormatter(@Nullable DateTimeFormatter dateTimeFormatter){
        	this.dateTimeFormatter = dateTimeFormatter;
        }
    }

    ์œ„์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด DateTimeFormatter๋Š” ๊ธฐ๋ณธ์ƒ์„ฑ์ž๊ฐ€ ์•„๋‹Œ Setter์—์„œ ์„ค์ •๋œ ๊ฐ’์„ ์‚ฌ์šฉํ•œ๋‹ค.

     => @Nullable์€ ๋งค์นญ๋˜๋Š” ๋นˆ์ด ์—†๋‹ค๋ฉด ๊ฐ’์„ null๋กœ ์„ค์ •ํ•œ๋‹ค.

     => ๊ธฐ๋ณธ์ƒ์„ฑ์ž์˜ ์ดˆ๊ธฐํ™” ๊ฐ’์„ ์„ค์ •ํ•œ ํ›„, Setter๋ฅผ ์‹คํ–‰ํ•จ์œผ๋กœ์จ null์ด ์„ค์ •๋œ๋‹ค.

     

    Optional๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Optional์„ ํ• ๋‹นํ•œ๋‹ค.

     

     

    ์ž๋™ ์ฃผ์ž…๊ณผ ๋ช…์‹œ์  ์˜์กด ์ฃผ์ž…

    @Configuration
    public class AppCtx{
    
        @Bean @Qualifier("printer")
        public MemberPrinter memberPrinter(){
        	return new MemberPrinter();
        }
        
        @Bean @Qualifier("summaryPrinter")
        public MemberSummaryPrinter memberPrinter2(){
        	return new MemberSummaryPrinter();
        }
        
        @Bean
        public MemberInfoPrinter infoPrinter(){
        	MemberInfoPrinter infoPrinter = new MemberInfoPrinter();
            //MemberInfoPrinter์˜ setPrinter๋ฉ”์„œ๋“œ์—๋Š” @Autowired๊ฐ€ ๋ถ™์–ด์žˆ์–ด์„œ
            //memberPrinter(=MemberPrinter)๋ฅผ ์„ค์ •ํ•ด์ค€๋‹ค.
            
            infoPrinter.setPrinter(memberPrinter2());
            //๊ทธ ๋‹ค์Œ setter๋กœ ๋‹ค์‹œ memberPrinter2(=MemberSummaryPrinter)๋ฅผ ์„ค์ •ํ•ด์ค€๋‹ค.
        }
    }
    public class MemberInfoPrinter{
        @Autowired @Qualifier("printer")
        public void setPrinter(MemberPrinter memberPrinter){
        	this.printer = memberPrinter;
        }
    }

     

     

    ๊ฒฐ๊ณผ๋Š” MemberPrinter์˜ ๋‚ด์šฉ์œผ๋กœ ์‹คํ–‰๋œ๋‹ค.

    ์ฆ‰, setter DI๋กœ ์™ธ๋ถ€์—์„œ ๊ฐ’์„ ๋„ฃ์–ด์ฃผ์–ด๋„

    ํ•ด๋‹น setter์— @Autowired๊ฐ€ ๋ถ™์–ด์žˆ์œผ๋ฉด @Autowired๊ฐ€ ์šฐ์„ ๊ถŒ์„ ๊ฐ–๋Š”๋‹ค.

     

    ์šฐ์„ ์ˆœ์œ„ : @Autowired > Setter DI ์ฃผ์ž…

     

     

     

    ์ •๋ฆฌ

    • ์˜์กด ์ฃผ์ž… ๋ฐฉ๋ฒ•
     - ์ง์ ‘์˜์กด์ฃผ์ž… : Bean์„ ์ƒ์„ฑํ•  ๋•Œ setter๋กœ ์˜์กด์„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•
     - ์ž๋™์˜์กด์ฃผ์ž… : Bean์„ ์ƒ์„ฑํ•  ๋•Œ setter๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ ,

                           ๊ฐ ํด๋ž˜์Šค๋“ค์˜ ํ•„๋“œ/setter์— @Autowired๋ฅผ ๋ถ™์—ฌ์„œ ์˜์กด์„ ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•


    • @Autowired๋Š” ํƒ€์ž…์ด ์ผ์น˜ํ•˜๋Š” Bean๊ฐ์ฒด๋ฅผ ์ฐพ์•„ ์ฃผ์ž…ํ•ด์ค€๋‹ค.
    ํƒ€์ž… ์ผ์น˜ Bean์ด ์—†์œผ๋ฉด -> UnsatisfiedDependencyException ๋ฐœ์ƒ
    ํƒ€์ž… ์ผ์น˜ Bean์ด 2๊ฐœ ์ด์ƒ์ด๋ฉด -> NoUniqueBeanDefinitionException ๋ฐœ์ƒ. 

                                                 @Qualifier๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ๊ฐ ๋นˆ์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•˜์—ฌ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ

     


    • @Qualifier๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์„ค์ •ํด๋ž˜์Šค์™€ ์ฃผ์ž…๋˜๋Š” ํด๋ž˜์Šค์— ๋ชจ๋‘ ์ ์–ด์ฃผ์–ด์•ผํ•œ๋‹ค.

     


    • ์ƒ์œ„/ํ•˜์œ„ ํƒ€์ž… ๊ด€๊ณ„์—์„œ @Qualifier๋Š” ์•ˆ๋ถ™์ด๋ฉด -> NoUniqueBeanDefinitionException ๋ฐœ์ƒ. @Qualifier๋กœ ํ•ด๊ฒฐ ๊ฐ€๋Šฅ


    • ์ž๋™ ์ฃผ์ž…ํ•  ๋Œ€์ƒ์ด ํ•„์ˆ˜๊ฐ€ ์•„๋‹ˆ๋ฉด 3๊ฐ€์ง€ ๋ฐฉ๋ฒ• ์‚ฌ์šฉ
     - @Autowired(required = false) : ๋งค์นญ๋˜๋Š” ๋นˆ์ด ์—†๋‹ค๋ฉด ๊ฐ’์„ ํ• ๋‹นํ•˜์ง€ ์•Š๋Š”๋‹ค
     - Optional : ๋งค์นญ๋˜๋Š” ๋นˆ์ด ์—†์œผ๋ฉด Optional ํ• ๋‹น
     - @Nullable : ๋งค์นญ๋˜๋Š” ๋นˆ์ด ์—†์œผ๋ฉด Null์„ ํ• ๋‹นํ•œ๋‹ค.


    • ์˜์กด ์ฃผ์ž…๋ฐ›๋Š” ํด๋ž˜์Šค์˜ setter์— @Autowired๊ฐ€ ์žˆ์–ด์„œ A๋ฅผ ์ฃผ์ž…๋ฐ›์„ ์ˆ˜ ์žˆ๋Š”๋ฐ
    ์„ค์ •ํด๋ž˜์Šค์—์„œ setter๋ฅผ ํ˜ธ์ถœํ•ด B๋ฅผ ์ฃผ์ž…ํ•ด์ฃผ๋ฉด?
    @Autowired๊ฐ€ setter DI๋ณด๋‹ค ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’๊ธฐ๋•Œ๋ฌธ์— A๋กœ ๋™์ž‘ํ•˜๊ฒŒ๋œ๋‹ค.

     

     

     

     

     

     

     

    ๋ฐ˜์‘ํ˜•
    • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
    • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
    • ํŠธ์œ„ํ„ฐ ๊ณต์œ ํ•˜๊ธฐ
    • ๊ตฌ๊ธ€ ํ”Œ๋Ÿฌ์Šค ๊ณต์œ ํ•˜๊ธฐ
    • ์นด์นด์˜คํ†ก ๊ณต์œ ํ•˜๊ธฐ