22 Aralık 2019 Pazar

SpringContext @Qualifier Anotasyonu - Bean'e İsmi İle Erişiriz

Giriş
Aynı arayüzden kalıtan iki tane bean varsa @Qualifier ile belirtilen isme sahip bean'e erişebilmeyi sağlar. @Autowired ile birlikte kullanılır.

Not : Eğer aynı arayüzden kalıtan iki bean varsa ve değişkenimizin ismi bir tane bean ismi ile aynıysa @Qualifier anotasyonunu kullanmaya gerek kalmayabiliyor. Açılaması şöyle. Ancak eğer obfuscation kullanıyorsak değişken ismi de farklılaştığı için bu fallback işe yaramıyor.
As a fallback Spring uses the bean name as a default qualifier value.
@Qualifier Nasıl Çalışıyor
Bence şuna benzer bir şey yapıyor. Elimizde aynı arayüzden kalıtan iki bean olsun
public interface PaymentGateway {
  void processPayment(PaymentRequest paymentRequest);
}

@Service("paypalGateway")
public class PaypalGateway implements PaymentGateway {
  public void processPayment(PaymentRequest paymentRequest) {
    // process payment using PayPal API
  }
}

@Service("stripeGateway")
public class StripeGateway implements PaymentGateway {
  public void processPayment(PaymentRequest paymentRequest) {
    // process payment using Stripe API
  }
}
İstenilen bean'e ismen erişmek için şöyle yaparız. Yani context.getBean(beanName) ile eriştik. @Qualifier bunu bizim için yapıyor.
@Configuration
public class PaymentGatewayConfig {
  @Value("${payment.gateway}")
  private String gatewayName;

  @Autowired
  private ApplicationContext context;

  @Bean
  public PaymentGateway paymentGateway() {
    PaymentGateway gateway = (PaymentGateway) context.getBean(gatewayName);
    return gateway;
  }
}
Örnek
Elimizde bir Configuration sınıfı olsun.
@Configuration
public class ConfigClass {
  @Bean(name="normalBean")
  @Primary
  public MyBeanInterface getNormalBeanInterface() {
    return new MyBeanInterfaceImpl();
  }

  @Bean(name="specialBean")
  public MyBeanInterface getSpecialBeanInterface() {
    return new MyBeanInterfaceForMyAnnotation();
  }
}
Bu bean'lere isim ile erişmek için şöyle yaparız.
public class MyController {
  @Autowired
  @Qualifier("normalBean")
  private MyBeanInterface base;

  @Autowired
  @Qualifier("specialBean")
  private MyBeanInterface special;
}
Örnek
Elimizde iki tane DataSource arayüzünü gerçekleştiren bean olsun. Bir tanesine isim verelim. Şöyle yaparız.
@Qualifier(value = "main")
public DataSource mysql() {
  return new MySQL();
}
Bean'e isim ile erişmek için şöyle yaparız
@Qualifier("main") // or @Qualifier("mysql"), to use the bean name
private DataSource dataSource;
Örnek
Elimizde ismi olan bir bean olsun
@Configuration
@ComponentScan("com.project")
public class ResponseConfig {

  ...
  @Bean
  @Qualifier("fileUInit")
  public String fileUInit() {
    return "whatever";
  }
}
Bean'e erişmek için şöyle yaparız.
@Component
public class Foo {

  ...

  @Autowired
  @Qualifier("fileUInit")
  private String s;
  
}
Örnek
Aynı bean'e iki defa erişmek için şöyle yaparız.
@Autowired 
@Qualifier("firstBean")
private MyBean bean1;

@Autowired 
@Qualifier("firstBean")
private MyBean bean2;
Örnek
Açıklaması şöyle.
That said, as of 4.3, collection/map and array types can be matched through Spring’s @Autowired type matching algorithm as well, as long as the element type information is preserved in @Bean return type signatures or collection inheritance hierarchies.
Tüm bean'lere erişmek için şöyle yaparız.
@Autowired 
private List<MyBean> beans;  // all you beans will be here
Örnek - Custom Annotation
@Qualifier Anotasyonu - Custom Annotation yazısına taşıdım

Hiç yorum yok:

Yorum Gönder