Spring Beans

공부는 혼자하는 거·2021년 8월 21일
0

Spring Tip

목록 보기
3/52

https://cbw1030.tistory.com/54

스프링부트의 경우 @Component, @Service, @Controller, @Repository, @Bean, @Configuration 등으로 필요한 빈들을 등록하고 필요한 곳에서 @Autowired를 통해 주입받아 사용하는 것이 일반적이다.

다음 그림과 같이 @Service, @Controller, @Repository는 모두 @Component를 상속받고 있으며 해당 어노테이션으로 등록된 클래스들은 스프링 컨테이너에 의해 자동으로 생성되어 스프링 빈으로 등록된다.

출처: dinfree/blog/스프링프레임워크

스프링부트에서 사용자 클래스를 스프링 빈으로 등록하는 가장 쉬운 방법은 클래스 선언부 위에 Component Annotation을 사용하는 것이다. @Component가 붙은 클래스는 스프링 빈 객체로 등록이 되어 객체 생성/삭제를 스프링에서 관리할 수 있다.

[ @Bean & @Configuration ]

스프링 빈을 생성하는 또 다른 방법으로는 자바 설정 클래스를 이용하는 것이다. 초기 스프링 기반 개발에서 빈 생성은 xml로 된 스프링 설정파일을 통해 이루어졌으며 지금 자바 클래스에서 관련 설정을  대신하는 방법을 주로 사용한다. 물론 필요에 따라 xml 설정은 아직도 사용이 가능하다.

설정 클래스는 @Configuration 어노테이션을 클래스 선언부 앞에 추가를 하면 된다. 또한 특정 타입을 리턴하는 메서드를 만들고 @Bean 어노테이션을 붙여주면 자동으로 해당 타입의 빈 객체가 생성된다.

@Bean 어노테이션의 주요 내용은 다음과 같다.

  • @Configuration 설정된 클래스의 메서드에서 사용가능.
  • 메서드의 리턴 객체가 스프링 빈 객체임을 선언함.
  • 빈의 이름은 기본적으로 메서드 이름이 됨.
  • @Bean(name=”name”) 으로 이름 변경 가능.
  • @Scope 을 통해 객체 생성을 조정할 수 있음.
  • @Component 애너테이션을 통해 @Configuration 없이도 빈 객체를 생성할수도 있음.
  • 빈 객체에 init(), destroy() 등 라이프사이클 메서드를 추가한 다음 @Bean 에서 지정할 수 있음.

[ @Primary & @Qualifier ]

  • @Primary: @Bean 혹은 @Component 에 함께 사용하며 객체 생성의 우선권을 부여.
  • @Qualifier: @Autowired에 함께 사용하며 Bean 의 이름이 같은 객체를 찾음.

Bean에 이름을 지정하는 방법은 다음과 같다.

1) 이름을 명시하지 않는경우

  • @Component: 소문자로 시작하는 클래스이름이 자동으로 사용됨.
  • @Bean: 소문자로 시작하는 메서드이름이 자동으로 사용됨.

2) 이름을 명시하는 경우

  • @Component: @Component(“이름”)과 같이 사용.
  • @Bean: @Bean(name=”이름”)과 같이 사용.

오토와이어링시 이름 사용 @Autowired 에서 특정 이름의 Bean 을 가지고 오려면 @Qualifier 어노테이션을 사용해야 한다.

여기서는 @Bean에 이름을 부여하고 찾는 것으로 다음과 같이 소스코드를 수정한다.

// ConfigurationExample.java
@Bean(name="ak47")
...

@Bean(name="ak47_b")
...

// Review7WeekApplication.java
@Autowired
@Qualifier("ak47_b")
Weapon weapon
...

Spring Bean naming 충돌날때

conflicts with existing, non-compatible bean definition of same name and class

Spring Beans 중복

https://madplay.github.io/post/two-spring-service-beans-with-same-class-name

해결방법 1

@Service("abc.HelloService")
public class HelloService {
    // ...생략
}

OR

@Primary//동일한 유형의 Bean이 여러 개 있을 때 해당 Bean에 더 높은 우선권을 부여
     @Bean(name = "MysqlDataSource")
     @ConfigurationProperties(prefix = "spring.datasource.mysql") //application.yaml에서 어떤 properties를 읽을 지 지정
     public DataSource mysqlDataSource() {
    	 
    	 log.info("yml 설정으로 Mysql Datasource set" );    	 
         return DataSourceBuilder
        		 .create()  
        		 .build(); //type(HikariDataSource.class).
     }

     @Primary
     @Bean(name = "MySqlSessionFactory")
     public SqlSessionFactory mySqlSessionFactory(@Qualifier("MysqlDataSource") DataSource mysqlDataSource, ApplicationContext applicationContex) throws Exception {
            SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
            sqlSessionFactoryBean.setDataSource(mysqlDataSource);
            sqlSessionFactoryBean.setConfigLocation(new PathMatchingResourcePatternResolver().getResource("mybatis-config/mysql-config.xml")); //mybatis 설정 xml 파일매핑 
            sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("mapper/mysql/*.xml"));
            //sqlSessionFactoryBean.setMapperLocations(applicationContex.getResources("classpath:mapper/mysql/*.xml"));
            sqlSessionFactoryBean.setTypeAliasesPackage("net.lunalabs.central.domain.mysql"); //benas pakage에 dao나 vo 모아둘 때 구분하기 위해 쓰는 것도 좋음
            //log.info("여기" + new PathMatchingResourcePatternResolver().getResources("mapper/mysql/*.xml").toString());
            
            //sqlSessionFactoryBean.setTypeAliasesPackage(null); //Mapper 에서 사용하고자하는 VO 및 Entity 에 대해서
            return sqlSessionFactoryBean.getObject();
     }

해결방법 2

public class FullBeanNameGenerator implements org.springframework.beans.factory.support.BeanNameGenerator {

	@Override
	public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
		return definition.getBeanClassName();
	}
}
package net.lunalabs.central.config;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.context.annotation.AnnotationBeanNameGenerator;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Service;

import lombok.extern.slf4j.Slf4j;

/*Bean(name="") 과 이 custom 설정을 같이 적용하는 방법을 못찾겠음*/

//@Configuration
@Slf4j
public class CustomBeanNaming implements BeanNameGenerator {

	
    private final AnnotationBeanNameGenerator defaultGenerator = new AnnotationBeanNameGenerator();

    private List<String> basePackages = new ArrayList<>();

    
	   
	@Override
	public String generateBeanName(BeanDefinition definition, BeanDefinitionRegistry registry) {
		
		String beanName;
		
		
		//Service anootain일 경우 full package 명으로 Bean 이름이 결정
//		if(isService(definition)) {
//			
//
//            beanName = generateFullBeanName((AnnotatedBeanDefinition) definition);
//			
//		}
		
		
	      if(isTargetPackageBean(definition)) {
	    	  beanName = generateFullBeanName((AnnotatedBeanDefinition) definition);
	        }
		
		else {
			
			//beanName = defaultGenerator.generateBeanName(definition, registry);
			//beanName = definition.getBeanClassName();
			beanName =  this.defaultGenerator.generateBeanName(definition, registry);
		}
		
		
		log.trace("Registered Bean Name : " + beanName);
		
		return beanName; 
	}
	
	

    private String generateFullBeanName(final AnnotatedBeanDefinition definition) {
        // 패키지를 포함한 전체 이름을 반환
        return definition.getMetadata().getClassName();
    }
	
	
	
	
    private boolean isService(final BeanDefinition definition) {
    	
        if (definition instanceof AnnotatedBeanDefinition) {
            final Set<String> annotationTypes = ((AnnotatedBeanDefinition) definition).getMetadata()
                    .getAnnotationTypes();

            return annotationTypes.stream()
                    .filter(type -> type.equals(Service.class.getName()))
                    .findAny()
                    .isPresent();
        }
        return false;
    }
    
    
    public boolean addBasePackages(String path) {
        return this.basePackages.add(path);
    }
	
    private boolean isTargetPackageBean(BeanDefinition definition) {
        String beanClassName = definition.getBeanClassName();
        return basePackages.stream().anyMatch(beanClassName::startsWith);
    }
    
    
    
}
@SpringBootApplication
public class CentralApplication extends SpringBootServletInitializer{

	public static void main(String[] args) {
		

		//SpringApplication.run(CentralApplication.class, args);
		
		
//		CustomBeanNaming customBeanNaming = new CustomBeanNaming();
//		customBeanNaming.addBasePackages("net.lunalabs.central.service");
//		
//		  new SpringApplicationBuilder(CentralApplication.class)
//          .beanNameGenerator(customBeanNaming)
//          .run(args);
				

---------------위 아님 아래---------------------------

//		final SpringApplicationBuilder builder = new SpringApplicationBuilder(CentralApplication.class);
//
//		// beanNameGenerator 를 등록한다.
//		builder.beanNameGenerator(new CustomBeanNaming());
//		builder.run(args);		
	  
	}

}

https://blog.woniper.net/318

보통 Spring을 사용해 WebApplication 개발하는 경우 Controller, Service, Repository와 같이 계층별로 나눠놓은 클래스를 Bean으로 등록해 @Autowired 애노테이션을 통해 주입받아 사용한다. 그런데 위와 같이 CustomBeanNameGenerator로 Service나 Repository 클래스 또한 패키지명을 포함한 Bean 이름으로 설정한다면 주입받을때 Bean을 식별하기 @Qualifier 애노테이션을 사용해야한다. @Qualifier("net.woniper.service.v1.SampleService")와 같이 말이다. 물론 이렇게 사용하면 된다. 하지만 패키지명까지 입력하는게 번거롭기도하고, CustomBeanNameGenerator로 이름이 생성되 등록되기 때문에 개발자는 Bean 이름을 추적하기 어렵다.

Controller는 보통 @Autowired 애노테이션을 사용해 주입해 사용하는 경우는 거의 없다. (test 할때는 필요하기도 하다.) 왜나하면 Controller가 최상위 계층이고 하위 계층인 Service나 Repository를 주입받아 사용한다. 즉 Service나 Repository 처럼 @Autowired, @Qualifier 애노테이션을 사용해 주입받는 경우가 거의 없다는 뜻이다. 그래서 패키지명을 포함한 Bean 이름으로 컨테이너에 등록해도 문제가 없다고 판단된다. 그래서 내가 추천하는 방법은 Controller는 모두 CustomBeanNameGenerator를 통해 등록을하고, 그 하위 계층인(주입 받아야하는 계층) Service나 Repository는 Bean 이름을 직접 설정해서 사용하는 것을 추천한다.

전체 소스는 https://github.com/woniper/spring-example/tree/master/spring-boot-custom-bean-name-generator 여기를 참고

Bean 등록은 어떻게 될까?

일단 스프링에서 BeanFactory와 ApplicationContext의 다이어그램을 보자. 사실 스프링 구조를 잘 이해하지 못하고 다이어그램만 보고는 각각의 interface와 class가 어떤 역할을 하는지 도통 알 수 없다.

핵심은 BeanFactory와 ApplicationContext다.

https://t1.daumcdn.net/cfile/tistory/2423B3395895FDCD0D

https://blog.woniper.net/336?category=699184

기타참고

https://atoz-develop.tistory.com/entry/Spring-Autowired의-다양한-사용-방법-required-Primary-Qualifier

@Autowired의 다양한 사용 방법 - required, Primary, Qualifier

@Autowired(required = false)은 의존성을 'Optional'로 설정하는 것이다.

@Autowired(required = false) //주입받을 의존객체가 필수적이지 않을 경우 @Autowired(required = false)로 설정해서 의존객체를 주입받지 못하더라도 빈을 생성하도록 할 수 있다.

https://atoz-develop.tistory.com/entry/Spring-애노테이션을-이용한-빈-설정-방법-정리

@Required, @Autowired, @Qualifier, @Value과 JSR-250 애노테이션 @PostConstruct, @PreDestroy, @Resource에 대해 알아보자

XML 설정에 애노테이션 빈 설정을 사용하기 위한 코드 추가

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:context="http://www.springframework.org/schema/context"
       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
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">

    <context:annotation-config/>
</beans>

context 네임 스페이스와 <context:annotation-config/> 코드를 추가한다.

이렇게 설정하면 빈 설정을 XML 파일이 아닌 빈 클래스의 애노테이션을 검색해 반영한다.

@Required

  • setter에 붙여 반드시 주입해야하는 프로퍼티로 설정하는 애노테이션- Spring 5.1 버전 부터 Deprecated 되었다. ➡️ 반드시 주입해야 할 프로퍼티는 생성자 주입을 이용한다.- 스프링 5.1이상을 사용하거나 자바 파일로 bean을 등록했을 경우 무시된다.

예제 코드

public class TestBean1 {

	private int data1;

	public int getData1() {
		return data1;
	}

	// 필수 주입 프로퍼티
        // 스프링 5.1이상을 사용하거나 자바 파일로 bean을 등록했을 경우 무시된다
	@Required
	public void setData1(int data1) {
		this.data1 = data1;
	}
}

@Configuration
public class BeanConfigClass {

	@Bean
	public TestBean1 testBean1() {
		return new TestBean1();
	}
}

@Autowired

  • 객체 타입을 통해 빈 객체를 자동으로 주입한다.- 필드, 생성자, setter에 붙일 수 있다.- 필드, setter에 붙여서 사용할 경우 반드시 기본 생성자가 정의되어 있어야 한다.- 필드에 붙이면 setter를 통해 주입되며 setter가 없을 경우 컴파일 과정에서 자동으로 추가된다.

예제 자바 코드

public class TestBean1 {

	// 필드 자동 주입
	// 자동으로 setter 메서드가 추가되어 setter 메서드를 통해 주입된다.
	@Autowired
	private DataBean1 data3;
}

public class DataBean1 { }

설정 - 자바

@Configuration
public class BeanConfigClass {

	@Bean
	public TestBean1 testBean1() {
		return new TestBean1();
	}

	@Bean
	public DataBean1 dataBean1() {
		return new DataBean1();
	}
}

설정 - XML

<?xml version="1.0" encoding="UTF-8"?>
<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:annotation-config/>

	<bean id='testBean1' class='com.atoz_develop.beans.TestBean1'/>
	<bean class='com.atoz_develop.beans.DataBean1'/>

</beans>

@Qualifier

  • @Autowired와 함께 사용한다.- @Autowired를 통한 자동 주입 시 같은 타입의 빈이 여러 개 정의되어 있으면 @Qualifier에 설정되어 있는 빈을 찾아 주입한다.

예제 자바 코드

public class TestBean1 {

	@Autowired
	@Qualifier("obj4")
	private DataBean2 data4;

	@Autowired
	@Qualifier("obj5")
	private DataBean2 data5;
}

public class DataBean2 { }

설정 - 자바

@Configuration
public class BeanConfigClass {

	@Bean
	public TestBean1 testBean1() {
		return new TestBean1();
	}

	@Bean
	public DataBean2 obj4() {
		return new DataBean2();
	}

	@Bean
	public DataBean2 obj5() {
		return new DataBean2();
	}
}

설정 - XML

<?xml version="1.0" encoding="UTF-8"?>
<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:annotation-config/>

	<bean id='testBean1' class='com.atoz_develop.beans.TestBean1'/>
	<bean id='obj4' class='com.atoz_develop.beans.DataBean2'/>
	<bean id='obj5' class='com.atoz_develop.beans.DataBean2'/>

</beans>

@Value

  • 생성자 주입 시 자동으로 주입되지 않는 기본 자료형과 문자열의 값을 설정한다.

예제 자바 코드

public class TestBean2 {

	private int data1;
	private String data2;
	private DataBean3 data3;
	private DataBean4 data4;

	public TestBean2(@Value("100") int data1, @Value("문자열") String data2, DataBean3 data3, DataBean4 data4) {
		this.data1 = data1;
		this.data2 = data2;
		this.data3 = data3;
		this.data4 = data4;
	}
}

public class DataBean3 { }

public class DataBean4 { }

설정 - XML

<?xml version="1.0" encoding="UTF-8"?>
<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:annotation-config/>

	<bean id='testBean2' class='com.atoz_develop.beans.TestBean2'/>

	<bean class='com.atoz_develop.beans.DataBean3'/>
	<bean class='com.atoz_develop.beans.DataBean4'/>

</beans>

XML 설정에서 <context:annotation-config/>를 추가하면 빈 클래스에 주입 설정을 따로 하지 않아도 생성자 주입이 자동으로 이루어진다.

이때 기본 타입과 문자열 타입의 필드는 자동으로 주입되지 않으며 @Value를 사용해서 값을 설정할 수 있다.

자바 애노테이션 설정(@Configuration)을 사용할때는 이 방법이 적용되지 않는다.

JSR-250 애노테이션 의존성 추가

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

@PostConstruct

  • @Bean(initMethod="...") 대신 사용- 생성자 호출 후 자동으로 호출될 메소드에 붙여서 사용

@Configuration 클래스에서 @Bean의 initMethod 속성에 빈이 생성될때 호출될 메소드를 지정하는 대신 빈의 클래스의 메소드에 @PostConstruct를 붙여 직접 설정할 수 있다.

예제 코드

public class TestBean2 {

	// 생성자 호출 이후 자동으로 호출
	@PostConstruct
	public void init2() {
		System.out.println("TestBean2의 init 메서드");
	}
}

설정

@Configuration
public class BeanConfigClass {

	@Bean
	public TestBean2 obj2() {
		return new TestBean2();
	}
}

@PreDestroy

  • @Bean(destroyMethod="...") 대신 사용- 객체 소멸 전 자동으로 호출될 메소드에 붙여서 사용

@Configuration 클래스에서 @Bean의 destroyMethod 속성에 빈이 생성될때 호출될 메소드를 지정하는 대신 빈의 클래스의 메소드에 @PostConstruct를 붙여 직접 설정할 수 있다.

예제 코드

public class TestBean2 {

	// 객체가 소멸되기 전에 자동으로 호출
	@PreDestroy
	public void destroy2() {
		System.out.println("TestBean2의 destroy 메서드");
	}
}

설정

@Configuration
public class BeanConfigClass {

	@Bean
	public TestBean2 obj2() {
		return new TestBean2();
	}
}

@Resource

  • 빈 이름(id)을 통해 자동 주입- @Autowired + @Qualifier와 유사- 필드명과 동일한 이름의 빈을 주입- 필드명과 빈 이름이 다르면 @Resource(name=“…”)

👉 필드명과 빈 이름(id)가 동일한 경우

예제 코드

public class TestBean5 {

	// 변수의 이름과 동일한 이름의 Bean이 주입된다.
	@Resource
	private DataBean1 data1;

	@Resource
	private DataBean2 data2;
}

설정

@Configuration
public class BeanConfigClass {

	@Bean
	public DataBean1 data1() {
		return new DataBean1();
	}

	@Bean
	public DataBean2 data2() {
		return new DataBean2();
	}

	@Bean
	public TestBean5 obj5() {
		return new TestBean5();
	}
}

👉 필드명과 빈 이름(id)가 다른 경우 - name 속성 사용

예제 코드

public class TestBean6 {

	@Resource(name = "data1")
	private DataBean1 data100;

	@Resource(name = "data2")
	private DataBean2 data200;
}

설정

@Configuration
public class BeanConfigClass {

	@Bean
	public DataBean1 data1() {
		return new DataBean1();
	}

	@Bean
	public DataBean2 data2() {
		return new DataBean2();
	}

	@Bean
	public TestBean6 obj6() {
		return new TestBean6();
	}
}

TestBean6의 DataBean1타입 필드명이 각각 data100, data200이고 빈 등록은 data1, data2로 되어있으므로 그냥 @Resource를 붙이면 자동 주입이 이루어지지 않는다.

이런 경우 @Resource의 name 속성을 사용해서 빈 이름을 직접 지정한다.

Java의 annotation-api는 스프링을 위한 라이브러리가 아니라 여러가지 자바 어플리케이션 개발에 사용할 수 있는 라이브러리이다.

스프링에서도 @PostConstruct, @PreDestroy, @Resource와 같은 애노테이션을 지원하므로 편리하게 사용할 수 있다.

2) @Configuration 설정을 사용할 경우

@Configuration
// 지정된 패키지의 Bean 클래스들의 어노테이션을 분석하여 Bean을 등록하라고 지정한다.
@ComponentScan(basePackages = {"com.atoz_develop.beans", "com.atoz_develop.bean1"})
@ComponentScan(basePackages = "com.atoz_develop.beans2")
@ComponentScan(basePackages = "com.atoz_develop.beans3")

public class BeanConfigClass { }

1) @Component로 등록한 빈 가져오기

ApplicationContext ctx = new AnnotationConfigApplicationContext(BeanConfigClass.class);

TestBean1 t1 = ctx.getBean(TestBean1.class);
TestBean1 t1 = (TestBean1) ctx.getBean("testBean1");
TestBean1 t1 = ctx.getBean("testBean1", TestBean1.class);

@Component를 붙여 빈을 등록하면 클래스 이름의 첫 문자를 소문자로 바꾼 것이 빈의 이름(id)이 된다.

빈 객체가 생성되는 시점은 ApplicationContext 객체가 생성되는 시점이며 기본적으로 singleton scope이다.

2) @Component("이름")

@Component("tb")
public class TestBean { }

@Component("이름")과 같이 빈 이름(id)를 지정할 수 있다.

@Lazy

@Component
@Lazy
public class TestBean { }

@Component를 붙여서 등록한 빈은 기본적으로 ApplicationContext 객체가 생성될때 빈 객체가 생성되는데 @Lazy를 같이 붙이면 getBean()과 같이 해당 빈이 사용될때 빈 객체가 생성된다.

와 동일한 표현이다.

@Scope

@Component
@Scope("prototype")
public class TestBean { }

@Component를 붙여서 등록한 빈은 기본적으로 singleton scope이 되는데 @Scope를 붙여서 빈의 scope를 설정할 수 있다.

의 scope 속성과 동일한 설정을 할 수 있다.

@PostConstruct, @PreDestroy

@Component
public class TestBean {

    @PostConstruct
    public void init() {
        System.out.println("init 메서드 호출");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("destroy 메서드 호출");
    }
}

@PostConstruct로 빈 생성자 호출 이후 자동으로 호출될 메서드와 @PreDestroy로 빈 객체가 소멸될 때 자동으로 호출되는 메서드를 등록한다.

자바에서 제공하는 JSR-250 애노테이션이며 사용하려면 다음 라이브러리를 추가해야한다.

<!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
<dependency>
    <groupId>javax.annotation</groupId>
    <artifactId>javax.annotation-api</artifactId>
    <version>1.3.2</version>
</dependency>

3) @Resource

@Component
public class TestBean1 {

	@Resource(name = "obj3")
	private DataBean3 data3;

	@Resource(name = "obj4")
	private DataBean3 data4;

	@Resource(name = "obj5")
	private DataBean3 data5;
}

@Component("obj2")
public class DataBean2 { }

@Configuration
@ComponentScan(basePackages = "com.atoz_develop.beans")
public class BeanConfigClass {

	@Bean
	public DataBean3 obj4() {
		return new DataBean3();
	}

	@Bean
	public DataBean3 obj5() {
		return new DataBean3();
	}
}

JSR-250 애노테이션 @Resource는 필드명과 이름이 같은 빈을 찾아 자동 주입한다.

@Resource(name = 이름)과 같이 특정 이름을 지정하면 필드명이 아닌 지정한 이름의 빈을 찾아 자동 주입한다.

사용하려면 JSR-250 애노테이션 라이브러리를 추가해야 한다.

profile
시간대비효율

0개의 댓글