Spring java yapılandırmasında @Bean açıklamalı bir yöntemi çağırma


104

Yay enjeksiyonunun @Beanaçıklama ile yöntemleri çağırmayı nasıl ele aldığını merak ediyorum . @BeanBir yönteme ek açıklama koyup bir örnek döndürürsem, bunun spring'e yöntemi çağırıp döndürülen örneği alarak bir fasulye oluşturmasını söylediğini anlıyorum. Bununla birlikte, bazen bu fasulyenin diğer fasulyeleri bağlamak veya başka bir kod ayarlamak için kullanılması gerekir. Bunun olağan yolu, @Beanbir örnek almak için açıklamalı yöntemi çağırmaktır . Sorum şu, bu neden birden fazla fasulyenin etrafta dolaşmasına neden olmuyor?

Örneğin, aşağıdaki koda bakın (başka bir sorudan alınmıştır). entryPoint()Yöntem ile açıklamalı @BeanBahar yeni bir örneğini oluşturur hayal diye, BasicAuthenticationEntryPointbir fasulye olarak. Ardından, entryPoint()configure bloğunda tekrar çağırıyoruz , ancak entryPoint()bean örneğini döndürüyor gibi görünüyor ve birden çok kez çağrılmıyor (günlüğe kaydetmeyi denedim ve yalnızca bir günlük girişi aldım). Potansiyel entryPoint()olarak, konfigürasyonun diğer bölümlerinde birden çok kez arayabiliriz ve her zaman aynı örneği alırız. Bunu anladığım doğru mu? Bahar, ek açıklamalarda bulunan yöntemlerin büyülü bir şekilde yeniden yazılmasını sağlıyor @Beanmu?

@Bean
public BasicAuthenticationEntryPoint entryPoint() {
    BasicAuthenticationEntryPoint basicAuthEntryPoint = new BasicAuthenticationEntryPoint();
    basicAuthEntryPoint.setRealmName("My Realm");
    return basicAuthEntryPoint;
}

@Override
protected void configure(HttpSecurity http) throws Exception {

    http
        .exceptionHandling()
            .authenticationEntryPoint(entryPoint())
            .and()
        .authorizeUrls()
            .anyRequest().authenticated()
            .and()
        .httpBasic();       
}

Yanıtlar:


136

Evet, Bahar biraz sihir yapar . Kontrol edin Bahar Dokümanlar :

İşte sihrin @Configurationdevreye girdiği yer burasıdır: Tüm sınıflar başlangıç ​​sırasında alt sınıflara alınır. girdiği yer burasıdır: CGLIB alınır . Alt sınıfta, alt yöntem, üst yöntemi çağırmadan ve yeni bir örnek oluşturmadan önce, önce önbelleğe alınmış (kapsamı alınmış) fasulye için kapsayıcıyı kontrol eder.

Bu, çağrıların @Bean yöntemlere CGLIB aracılığıyla vekalet ve bu nedenle önbelleğe alınmış sürümünün döndürüldüğü (yeni bir tane oluşturulmadığı) anlamına gelir.

Varsayılan kapsamı @Beans olduğuSINGLETON aşağıdaki gibi farklı bir kapsam belirtirseniz, PROTOTYPEçağrı orijinal yönteme geçirilir.

Lütfen bunun statik yöntemler için geçerli olmadığını unutmayın . İlkbahar belgelerine göre:

Statik @Beanyöntemlere yapılan çağrılar @Configuration, teknik sınırlamalar nedeniyle sınıflar içinde bile (bu bölümde daha önce açıklandığı gibi) bile konteyner tarafından asla yakalanmaz : CGLIB alt sınıflandırma yalnızca statik olmayan yöntemleri geçersiz kılabilir. Sonuç olarak, başka bir @Beanyönteme doğrudan yapılan bir çağrının standart Java semantiği vardır, bu da bağımsız bir örneğin doğrudan fabrika yönteminden döndürülmesine neden olur.


Bu şekilde oluşturulan fasulyeleri geçersiz kılmak mümkün mü? Örneğin, doğrudan bir fasulye oluşturma yöntemini çağıran Yay tanımlı bir sınıfım var. İstediğim o yöntemle oluşturulan fasulye kullanılır değil yani, ama bir ben (ile açıklayarak kendimi tanımlamak @Beanve @Primary).
Fons

4
Ama aynı zamanda proxy'nin (jdk veya CGLIB, hangisi olursa olsun) kendi kendine çağırmada çalışamayacağını hatırlıyorum, peki @Configuration fasulye arası bağımlılığı nasıl tanımlar? Tam olarak kendi kendine çağırma kullanıyor
Nowhy

3
@Nowhy CGLib allows us to create proxy classes at runtime by creating sub class of specified class using Byte code generation. CGLib proxies are used in the case where Proxy is to be created for those class which does not have any interfaces or have methods which are not declared in the implementing interface. Bu durumda, CGLIB @Configuration sınıfının alt sınıfını oluşturur ve yöntemlerini geçersiz kılar (@Bean yöntemi dahil). Bu nedenle, başka bir yöntemden @Bean yöntemini çağırdığımızda, aslında onun overriden versiyonunu çağırıyoruz (java dinamik bağlama sayesinde).
Flame239

Peki @Component, java Poxy yerine proxy oluşturmak için CHLIB kullanırsam selfInvocation AOP çalışacak mı?
Antoniossss
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.