環境:SpringBoot2.6.12
被導入的類加入到Spring IOC容器中。
public class A { @Bean public B b() { return new B() ; }
在配置類中導入上面的類
@Import({A.class})@Configurationpublic class ImportConfig {}
這樣A,B都被Spring IOC容器管理了。這里可以導入多個類。
注意:在Spring4.2之前的版本中被導入的類必須是配置類也就是類上有@Configuration注解,4.2后的版本隨意一個普通類也可以。
測試
@Resourceprivate A a ;@Resourceprivate B b ; @Testpublic void testImport() { System.out.println("a = " + a) ; System.out.println("b = " + b) ;}
圖片
沒問題,能正常的輸出。
注意,請看下面的示例:
public class ImportMain { static class Person{ } static class A{ @Bean public Person p() { Person person = new Person(); System.out.println("p(), " + person) ; return person ; } @Bean public Date d() { Person p = p() ; System.out.println("d(), " + p) ; return new Date() ; } } @Import({A.class}) @Configuration static class AppConfig { }}
在上面的示例中在d()方法中調用p()方法,那這里得到的Person對象和p()方法中定義的是同一個嗎?
在上面的代碼中一定不是同一個,輸出如下:
p(), com.pack.main.importaware.ImportMain$Person@18dfcc1p(), com.pack.main.importaware.ImportMain$Person@19f7dcfd(), com.pack.main.importaware.ImportMain$Person@19f7dcf
分別是兩個不同的對象,如何解決呢?我們只需要在A類上添加@Configuration即可,添加了該類后Spring容器首先會對當前的A這個類創建代理,當我們在A這個類中調用其它方法的時候會通過攔截器BeanMethodInterceptor進行攔截;在該攔截器中會根據你調用的方法來確定對應的beanName,然后在容器中查找是否有對應的Bean,如果有則直接返回,所以就確保了在當前類中你不管調用多少次其它@Bean方法都能保證是同一個對象。
通過實現ImportSelector接口
public class E { @Bean public G g() { return new G() ; }}public class F {}public class G {}
配置類
@Import({C.class, A.class})@Configurationpublic class ImportConfig {}
實現ImportSelector接口
public class C implements ImportSelector { @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { return new String[] {"com.pack.import_annotation.E", "com.pack.import_annotation.F"}; }}
這里的返回值中必須是完整的包名+類名
注意:這里可以返回空的String數組(length = 0),但是不能返回null。實現ImportSelector該接口的這個本身是不會被注冊為Bean的。
測試
@Resourceprivate E e ;@Resourceprivate F f ;@Resourceprivate G g ; @Testpublic void testImport() { System.out.println("e = " + e) ; System.out.println("f = " + f) ; System.out.println("g = " + g) ;}
圖片
public class H implements ImportBeanDefinitionRegistrar { @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { GenericBeanDefinition beanDefinition = new GenericBeanDefinition() ; beanDefinition.setBeanClass(X.class) ; // 給X這個類配置屬性name值 beanDefinition.getPropertyValues().addPropertyValue("name", "張三") ; // x 為當前X類在Spring容器中的beanName registry.registerBeanDefinition("x", beanDefinition) ; }}
配置類
public class X { private String name ; public String getName() { return name; } public void setName(String name) { this.name = name; } }@Import({C.class, A.class, H.class})@Configurationpublic class ImportConfig {}
測試:
圖片
注意:實現ImportBeanDefinitionRegistrar該接口本身這個類是不會被注冊為Bean的。
完畢!!!
本文鏈接:http://www.tebozhan.com/showinfo-26-11212-0.htmlSpring常用注解@Import的三種使用方式,你都了解了嗎?
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com