수색…


특정 유형의 모든 bean 자동 배선

동일한 인터페이스를 여러 개 구현 한 경우 Spring은이 객체들을 모두 콜렉션 객체로 자동 변환 할 수 있습니다. Validator 패턴 1 을 사용하는 예제를 사용할 것입니다.

푸 클래스 :

public class Foo {
     private String name;
     private String emailAddress;
     private String errorMessage;
     /** Getters & Setters omitted **/
}

인터페이스 :

public interface FooValidator {
    public Foo validate(Foo foo);
}

이름 검사기 클래스 :

@Component(value="FooNameValidator")
public class FooNameValidator implements FooValidator {
    @Override
    public Foo validate(Foo foo) {
        //Validation logic goes here.
    }
}

이메일 검사기 클래스 :

@Component(value="FooEmailValidator")
public class FooEmailValidator implements FooValidator {
    @Override
    public Foo validate(Foo foo) {
        //Different validation logic goes here.
    }
}

이제 이러한 유효성 검사기를 개별적으로 또는 클래스에 자동으로 autowire 할 수 있습니다.

인터페이스 :

public interface FooService {
    public void handleFoo(Foo foo);
}

수업:

@Service
public class FooServiceImpl implements FooService {
    /** Autowire all classes implementing FooValidator interface**/
    @Autowired
    private List<FooValidator> allValidators;

    @Override
    public void handleFoo(Foo foo) {
       /**You can use all instances from the list**/
       for(FooValidator validator : allValidators) {
           foo = validator.validate(foo);               
       }
    }   
}

Spring IoC 컨테이너에 둘 이상의 인터페이스 구현이 있고 @Qualifier 주석과 함께 사용하려는 인터페이스를 지정하지 않은 경우 Spring은 시작하려고 할 때 예외를 throw합니다. 왜냐하면 ' 어떤 인스턴스를 사용할 지 알지 못합니다.

1 : 이러한 간단한 검증을 수행하는 올바른 방법은 아닙니다. 이것은 autowiring에 대한 간단한 예입니다. Spring이 어노테이션을 사용하여 유효성 검사를하는 방법을보다 쉽게 ​​검증 할 수있는 방법을 찾고 싶다면

콩 선언하기

빈을 선언하려면 메소드를 @Bean 주석으로 주석을 달거나 @Component 주석 (주석 @Service , @Repository , @Controller 도 함께 사용할 수 있음)으로 주석을 달기 만하면된다.

JavaConfig가 그러한 메소드를 발견하면, 그 메소드를 실행하고 리턴 값을 BeanFactory 내에 bean으로 등록합니다. 기본적으로 bean 이름은 메소드 이름의 bean 이름이됩니다.

다음 세 가지 방법 중 하나를 사용하여 bean을 만들 수 있습니다.

  1. Java 기반 설정 사용하기 : 설정 파일에서 @bean annotation을 사용하여 bean을 선언해야합니다.

    @Configuration
    public class AppConfig {
        @Bean
        public TransferService transferService() {
            return new TransferServiceImpl();
        }
    }
    
  2. XML 기반 설정 사용하기 : XML 기반 설정을 위해서 우리는 애플리케이션 설정 XML에서 declare bean을 생성 할 필요가있다.

     <beans>
         <bean name="transferService" class="com.acme.TransferServiceImpl"/>
     </beans>
    
  3. 주석 기반 구성 요소 : 주석 기반 구성 요소의 경우 Bean으로 선언하려는 클래스에 @Component 주석을 추가해야합니다.

     @Component("transferService")
     public class TransferServiceImpl implements TransferService {
         ...
     }
    

이제는 transferService 라는 이름을 가진 세 개의 Bean을 모두 BeanFactory 또는 ApplicationContext 에서 사용할 수 있습니다.

자동 주석 달기 기본 주석

인터페이스 :

public interface FooService {
    public int doSomething();
}

수업:

@Service
public class FooServiceImpl implements FooService {
    @Override
    public int doSomething() {
        //Do some stuff here
        return 0;
    }
}

이 클래스를 autowire 할 수 있으려면 클래스가 Spring 용 인터페이스를 구현해야한다. Spring이로드 시간 짜기를 사용하여 독립 실행 형 클래스를 autowire하는 방법은 있지만이 예제에서는 범위를 벗어납니다.

@Autowired 어노테이션을 사용하여 Spring IoC 컨테이너로 인스턴스화 한 클래스에서이 빈에 액세스 할 수있다.

용법:

@Autowired([required=true])

@Autowired 어노테이션은 먼저 유형별로 자동 와이어 링을 시도한 다음 모호한 경우 빈 이름으로 돌아갑니다.

이 주석은 여러 가지 다른 방식으로 적용될 수 있습니다.

생성자 삽입 :

public class BarClass() {
    private FooService fooService         

    @Autowired
    public BarClass(FooService fooService) {
        this.fooService = fooService;
    }
}

필드 주입 :

public class BarClass() {
    @Autowired
    private FooService fooService;
}

세터 주입 :

public class BarClass() {
    private FooService fooService;

    @Autowired
    public void setFooService(FooService fooService) {
        this.fooService = fooService;
    }
}

동적 빈 인스턴스 생성을 위해 FactoryBean 사용하기

주입 할 빈을 동적으로 결정하기 위해 FactoryBean 을 사용할 수 있습니다. 이것들은 팩토리 메소드 패턴을 구현하는 클래스이며 컨테이너에 대한 빈 인스턴스를 제공합니다. 그들은 봄에 의해 인식되고 콩이 공장에서 온다는 것을 알 필요없이 투명하게 사용될 수 있습니다. 예 :

public class ExampleFactoryBean extends AbstractFactoryBean<String> {
    // This method determines the type of the bean for autowiring purposes
    @Override
    public Class<?> getObjectType() {
        return String.class;
    }

    // this factory method produces the actual bean
    @Override
    protected String createInstance() throws Exception {
        // The thing you return can be defined dynamically,
        // that is read from a file, database, network or just
        // simply randomly generated if you wish.
        return "Something from factory";
    }
}

구성 :

@Configuration
public class ExampleConfig {
    @Bean
    public FactoryBean<String> fromFactory() {
        return new ExampleFactoryBean();
    }
}

Bean 가져 오기 :

AbstractApplicationContext context = new AnnotationConfigApplicationContext(ExampleConfig.class);
String exampleString = (String) context.getBean("fromFactory");

실제 FactoryBean을 얻으려면 bean 이름 앞에 앰퍼샌드 접두어를 사용하십시오 :

FactoryBean<String> bean = (FactoryBean<String>) context.getBean("&fromFactory");

prototype 또는 singleton 범위 만 사용할 수 있습니다 - 범위를 prototype 재정의 isSingleton 메서드로 변경하려면 다음을 유의하십시오.

public class ExampleFactoryBean extends AbstractFactoryBean<String> {
    @Override
    public boolean isSingleton() {
        return false;
    }

    // other methods omitted for readability reasons
}

범위 지정은 팩토리 빈 자체가 아니라 실제 생성되는 인스턴스를 참조합니다.

프로토 타입 범위의 bean을 싱글 톤으로 삽입

컨테이너는 싱글 톤 빈을 생성하고 공동 작업자를 한 번만 주입합니다. 싱글 톤 빈에 프로토 타입 범위 협업 자 (prototype-scoped collaborator)가있는 경우 원하는 접근법이 아니다. 프로토 타입 범위의 빈은 접근자를 통해 액세스 될 때마다 주입되어야하기 때문이다.

이 문제에 대한 해결책은 여러 가지가 있습니다.

  1. 조회 메소드 삽입 사용
  2. javax.inject.Provider 를 통해 프로토 타입 범위의 빈 검색
  3. org.springframework.beans.factory.ObjectFactory 를 통해 프로토 타입 범위의 빈을 검색 org.springframework.beans.factory.ObjectFactory (# 2와 동일하지만 Spring에 고유 한 클래스 사용)
  4. ApplicationContextAware 인터페이스를 구현하여 싱글 톤 bean 컨테이너를 인식하게한다.

접근법 # 3과 # 4는 일반적으로 응용 프로그램을 Spring 프레임 워크에 강하게 묶어 놓기 때문에 일반적으로 권장하지 않습니다. 따라서이 예제에서는 다루지 않습니다.

XML 구성 및 추상 메소드를 통한 조회 메소드 삽입

Java 클래스

public class Window {
}

public abstract class WindowGenerator {

    public Window generateWindow() {
        Window window = createNewWindow(); // new instance for each call
        ... 
    }

    protected abstract Window createNewWindow(); // lookup method
}

XML

<bean id="window" class="somepackage.Window" scope="prototype" lazy-init="true"/>

<bean id="windowGenerator" class="somepackage.WindowGenerator">
    <lookup-method name="createNewWindow" bean="window"/>
</bean>

Java 구성 및 @Component를 통한 조회 메소드 삽입

Java 클래스

public class Window {
}

@Component
public class WindowGenerator {

    public Window generateWindow() {
        Window window = createNewWindow(); // new instance for each call
        ...
    }

    @Lookup
    protected Window createNewWindow() {
        throw new UnsupportedOperationException();
    }
}

Java 구성

@Configuration
@ComponentScan("somepackage") // package where WindowGenerator is located
public class MyConfiguration {

    @Bean
    @Lazy
    @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Window window() {
        return new Window();
    }
}

Java 구성을 통한 수동 조회 방법 삽입

Java 클래스

public class Window {
}

public abstract class WindowGenerator {

    public Window generateWindow() {
        Window window = createNewWindow(); // new instance for each call
        ...
    }

    protected abstract Window createNewWindow(); // lookup method
}

Java 구성

@Configuration
public class MyConfiguration {

    @Bean
    @Lazy
    @Scope(scopeName = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
    public Window window() {
        return new Window();
    }

    @Bean
    public WindowGenerator windowGenerator(){
        return new WindowGenerator() {
            @Override
            protected Window createNewWindow(){
                return window();
            }
        };
    }
}

javax.inject.Provider 를 통해 프로토 타입 범위의 빈을 싱글 톤으로 javax.inject.Provider

Java 클래스

public class Window {
}

public class WindowGenerator {

    private final Provider<Window> windowProvider;

    public WindowGenerator(final Provider<Window> windowProvider) {
        this.windowProvider = windowProvider;
    }

    public Window generateWindow() {
        Window window = windowProvider.get(); // new instance for each call   
        ...
    }
}

XML

<bean id="window" class="somepackage.Window" scope="prototype" lazy-init="true"/>

<bean id="windowGenerator" class="somepackage.WindowGenerator">
    <constructor-arg>
        <bean class="org.springframework.beans.factory.config.ProviderCreatingFactoryBean">
            <property name="targetBeanName" value="window"/>
        </bean>
    </constructor-arg>
</bean>

같은 접근법이 다른 스코프에도 사용될 수 있습니다 (예 : request-scoped bean을 싱글 톤에 주입).

@Qualifier를 사용하여 특정 빈 인스턴스를 Autowiring하기

같은 인터페이스를 여러 개 구현 한 경우 Spring은 클래스에 자동으로 연결해야하는 인터페이스를 알아야합니다. 이 예제에서는 Validator 패턴을 사용하려고합니다. 1

푸 클래스 :

public class Foo {
     private String name;
     private String emailAddress;
     private String errorMessage;
     /** Getters & Setters omitted **/
}

인터페이스 :

public interface FooValidator {
    public Foo validate(Foo foo);
}

이름 검사기 클래스 :

@Component(value="FooNameValidator")
public class FooNameValidator implements FooValidator {
    @Override
    public Foo validate(Foo foo) {
        //Validation logic goes here.
    }
}

이메일 검사기 클래스 :

@Component(value="FooEmailValidator")
public class FooEmailValidator implements FooValidator {
    @Override
    public Foo validate(Foo foo) {
        //Different validation logic goes here.
    }
}

이제 이러한 유효성 검사기를 개별적으로 클래스에 자동 배선 할 수 있습니다.

인터페이스 :

public interface FooService {
    public void handleFoo(Foo foo);
}

수업:

@Service
public class FooServiceImpl implements FooService {
    /** Autowire validators individually **/
    @Autowired
    /* 
     * Notice how the String value here matches the value 
     * on the @Component annotation? That's how Spring knows which 
     * instance to autowire.
     */
    @Qualifier("FooNameValidator")
    private FooValidator nameValidator;

    @Autowired
    @Qualifier("FooEmailValidator")
    private FooValidator emailValidator;

    @Override
    public void handleFoo(Foo foo) {
        /**You can use just one instance if you need**/
        foo = nameValidator.validate(foo);
    }   
}

Spring IoC 컨테이너에 둘 이상의 인터페이스 구현이 있고 @Qualifier 주석과 함께 사용하려는 인터페이스를 지정하지 않은 경우 Spring은 시작하려고 할 때 예외를 throw합니다. 왜냐하면 ' 어떤 인스턴스를 사용할 지 알지 못합니다.

1 : 이러한 간단한 검증을 수행하는 올바른 방법은 아닙니다. 이것은 autowiring에 대한 간단한 예입니다. Spring이 어노테이션을 사용하여 유효성 검사를하는 방법을보다 쉽게 ​​검증 할 수있는 방법을 찾고 싶다면

제네릭 형식 매개 변수를 사용하여 클래스의 특정 인스턴스 자동 배선

제네릭 타입 매개 변수를 가진 인터페이스를 가지고 있다면, Spring은 이것을 사용하여 여러분이 지정한 타입 매개 변수를 구현하는 구현만을 autowire 할 수 있습니다.

인터페이스 :

public interface GenericValidator<T> {
    public T validate(T object);
}

Foo Validator 클래스 :

@Component
public class FooValidator implements GenericValidator<Foo> {
    @Override
    public Foo validate(Foo foo) {
        //Logic here to validate foo objects.
    }
}

바 유효성 검사기 클래스 :

@Component
public class BarValidator implements GenericValidator<Bar> {
    @Override
    public Bar validate(Bar bar) {
        //Bar validation logic here
    }
}

이제 형식 매개 변수를 사용하여이 유효성 검사기를 autowire하여 autowire 할 인스턴스를 결정할 수 있습니다.

인터페이스 :

public interface FooService {
    public void handleFoo(Foo foo);
}

수업:

@Service
public class FooServiceImpl implements FooService {
    /** Autowire Foo Validator **/
    @Autowired
    private GenericValidator<Foo> fooValidator;

    @Override
    public void handleFoo(Foo foo) {
        foo = fooValidator.validate(foo);
    }   
}


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow