@ComponentScan+ @Controller + @Service + @Repositoryjava
導入第三方包裏的組件spring
幾個實體類的聲明:shell
package com.niewj.bean; public class PojoBean { public PojoBean() { System.out.println("PojoBean[無註解java類] 初始化~~~"); } }
package com.niewj.bean; public class PojoBean2 { public PojoBean2(){ System.out.println("PojoBean2[無註解java類] 初始化~~~"); } }
package com.niewj.bean; public class PojoBean3 { public PojoBean3(){ System.out.println("PojoBean3[無註解java類] 初始化~~~"); } }
package com.niewj.bean; public class Pojo4 { public Pojo4(){ System.out.println("Pojo4[無註解java類] 初始化~~~"); } }
package com.niewj.bean; public class Pojo5 { public Pojo5(){ System.out.println("Pojo5[無註解java類] 初始化~~~"); } }
package com.niewj.config; import com.niewj.bean.PojoBean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration @Import(PojoBean.class) // 這裏 public class ImportTestConfig { }
private AnnotationConfigApplicationContext printAnnoBeans(Class clazz) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(clazz); Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println); return ctx; } @Test public void testImport(){ // PojoBean*.java並沒有註解類, 可是會初始化納入spring容器管理! -> @Import的做用! ApplicationContext ctx = printAnnoBeans(ImportTestConfig.class); }
output:數組
PojoBean[無註解java類] 初始化~~~ org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importTestConfig com.niewj.bean.PojoBean
能夠看到 PojoBean 的初始化和bean id的展現!springboot
普通Javabean並無任何註解的:ide
package com.niewj.config; import com.niewj.bean.PojoBean; import com.niewj.bean.PojoBean2; import com.niewj.bean.PojoBean3; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration //@Import(PojoBean.class) @Import({PojoBean.class, PojoBean2.class, PojoBean3.class}) // 這裏 public class ImportTestConfig { }
測試:測試
private AnnotationConfigApplicationContext printAnnoBeans(Class clazz) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(clazz); Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println); return ctx; } @Test public void testImport(){ // PojoBean*.java並沒有註解類, 可是會初始化納入spring容器管理! -> @Import的做用! ApplicationContext ctx = printAnnoBeans(ImportTestConfig.class); }
output: 能夠看到這三個無註解的普通bean也被容器管理和初始化了!code
PojoBean[無註解java類] 初始化~~~ PojoBean2[無註解java類] 初始化~~~ PojoBean3[無註解java類] 初始化~~~ org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importTestConfig com.niewj.bean.PojoBean com.niewj.bean.PojoBean2 com.niewj.bean.PojoBean3
@ImportSelector接口的實現類, 能夠放入@Import中使用:對象
@Import是列出全部; @ImportSelector是返回一個 class name的字符串的數組, 能夠理解爲@Import的簡化版(方便使用)接口
package com.niewj.config; import com.niewj.bean.PojoBean; import com.niewj.bean.PojoBean2; import com.niewj.bean.PojoBean3; import com.niewj.condition.MyImportSelector; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration //@Import(PojoBean.class) //@Import({PojoBean.class, PojoBean2.class, PojoBean3.class}) @Import({PojoBean.class, PojoBean2.class, PojoBean3.class, MyImportSelector.class}) // 這裏 public class ImportTestConfig { }
MyImportSelector:
package com.niewj.condition; import com.niewj.bean.Pojo4; import com.niewj.bean.Pojo5; import org.springframework.context.annotation.ImportSelector; import org.springframework.core.type.AnnotationMetadata; import java.util.ArrayList; import java.util.List; public class MyImportSelector implements ImportSelector { /** * 返回的數組中的類名, 也會做爲加入容器管理的bean * @param importingClassMetadata 能夠獲取到當前類的全部註解信息! * @return */ @Override public String[] selectImports(AnnotationMetadata importingClassMetadata) { List<String> classNameList = new ArrayList<>(); // 能夠假設Pojo4/Pojo5的類名都讀取字配置文件, 好比 spring.factories-->相似springboot源碼 classNameList.add(Pojo4.class.getName()); classNameList.add(Pojo5.class.getName()); return classNameList.toArray(new String[0]); } }
testcase:
private AnnotationConfigApplicationContext printAnnoBeans(Class clazz) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(clazz); Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println); return ctx; } @Test public void testImport(){ // PojoBean*.java並沒有註解類, 可是會初始化納入spring容器管理! -> @Import的做用! ApplicationContext ctx = printAnnoBeans(ImportTestConfig.class); }
output: 可見: PojoBean/PojoBean2/PojoBean3都初始化了; 並且 ImportSelector中加入數組的 Pojo4/Pojo5也初始化了!
PojoBean[無註解java類] 初始化~~~ PojoBean2[無註解java類] 初始化~~~ PojoBean3[無註解java類] 初始化~~~ Pojo4[無註解java類] 初始化~~~ Pojo5[無註解java類] 初始化~~~ org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importTestConfig com.niewj.bean.PojoBean com.niewj.bean.PojoBean2 com.niewj.bean.PojoBean3 com.niewj.bean.Pojo4 com.niewj.bean.Pojo5
能夠結合已有beanDefinition信息!
package com.niewj.config; import com.niewj.bean.PojoBean; import com.niewj.bean.PojoBean2; import com.niewj.bean.PojoBean3; import com.niewj.condition.MyImportBeanDefRegistrar; import com.niewj.condition.MyImportSelector; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; @Configuration //@Import(PojoBean.class) //@Import({PojoBean.class, PojoBean2.class, PojoBean3.class}) @Import({PojoBean.class, PojoBean2.class, PojoBean3.class, MyImportSelector.class, MyImportBeanDefRegistrar.class}) public class ImportTestConfig { }
MyImportBeanDefRegistrar:
package com.niewj.condition; import com.niewj.bean.Pojo4; import com.niewj.bean.Pojo5; import com.niewj.bean.PojoWhenHasPojo4AndPojo5; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.context.annotation.ImportBeanDefinitionRegistrar; import org.springframework.core.type.AnnotationMetadata; public class MyImportBeanDefRegistrar implements ImportBeanDefinitionRegistrar { /** 能夠獲取容器中已有 BeanDefinition 信息來作一些判斷; * 好比, 若是有這兩個類, 也加入類 PojoWhenHasPojo4AndPojo5 * @param importingClassMetadata 能夠獲取到當前類(掃描到的類)的全部註解信息 * @param registry beanDefinition的註冊接口 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean hasPojo5 = registry.containsBeanDefinition(Pojo5.class.getName()); boolean hasPojo4 = registry.containsBeanDefinition(Pojo4.class.getName()); if(hasPojo4 && hasPojo5){ RootBeanDefinition beanDefinition = new RootBeanDefinition(PojoWhenHasPojo4AndPojo5.class); registry.registerBeanDefinition("pojoWhenHasPojo4AndPojo5", beanDefinition); } } }
測試:
private AnnotationConfigApplicationContext printAnnoBeans(Class clazz) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(clazz); Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println); return ctx; } @Test public void testImport(){ // PojoBean*.java並沒有註解類, 可是會初始化納入spring容器管理! -> @Import的做用! ApplicationContext ctx = printAnnoBeans(ImportTestConfig.class); }
output: 能夠看到 PojoWhenHasPojo4AndPojo5 的初始化!
PojoBean[無註解java類] 初始化~~~ PojoBean2[無註解java類] 初始化~~~ PojoBean3[無註解java類] 初始化~~~ Pojo4[無註解java類] 初始化~~~ Pojo5[無註解java類] 初始化~~~ PojoWhenHasPojo4AndPojo5[無註解java類] 初始化~~~ org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importTestConfig com.niewj.bean.PojoBean com.niewj.bean.PojoBean2 com.niewj.bean.PojoBean3 com.niewj.bean.Pojo4 com.niewj.bean.Pojo5 pojoWhenHasPojo4AndPojo5
注意: 經過 ctx.getBean("beanId") 調用, 獲得的是 getObject()方法返回的對象的實際內容;
經過ctx.getBean("&beanId")調用, 獲得的纔是實際的FactoryBean對象
package com.niewj.bean; public class Pojo7 { public Pojo7(){ System.out.println("Pojo7[無註解java類] 初始化~~~"); } }
package com.niewj.bean; import org.springframework.beans.factory.FactoryBean; public class Pojo7FactoryBean implements FactoryBean<Pojo7> { @Override public Pojo7 getObject() throws Exception { System.out.println("Pojo7FactoryBean---FactoryBean---初始化"); return new Pojo7(); } @Override public Class<?> getObjectType() { return Pojo7.class; } @Override public boolean isSingleton() { return false; } }
private AnnotationConfigApplicationContext printAnnoBeans(Class clazz) { AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(clazz); Arrays.stream(ctx.getBeanDefinitionNames()).forEach(System.out::println); return ctx; } @Test public void testImport(){ // PojoBean*.java並沒有註解類, 可是會初始化納入spring容器管理! -> @Import的做用! ApplicationContext ctx = printAnnoBeans(ImportTestConfig.class); Pojo7 bean1 = ctx.getBean("pojo7", Pojo7.class); System.out.println(bean1); Pojo7FactoryBean bean2 = ctx.getBean("&pojo7", Pojo7FactoryBean.class); System.out.println(bean2); }
output: 看最後兩行: 說明了 FactoryBean的特徵: &beanId獲得是 FactoryBean; beanId獲得是 getObject()返回的實際Bean!
PojoBean[無註解java類] 初始化~~~ PojoBean2[無註解java類] 初始化~~~ PojoBean3[無註解java類] 初始化~~~ Pojo4[無註解java類] 初始化~~~ Pojo5[無註解java類] 初始化~~~ PojoWhenHasPojo4AndPojo5[無註解java類] 初始化~~~ org.springframework.context.annotation.internalConfigurationAnnotationProcessor org.springframework.context.annotation.internalAutowiredAnnotationProcessor org.springframework.context.annotation.internalCommonAnnotationProcessor org.springframework.context.event.internalEventListenerProcessor org.springframework.context.event.internalEventListenerFactory importTestConfig com.niewj.bean.PojoBean com.niewj.bean.PojoBean2 com.niewj.bean.PojoBean3 com.niewj.bean.Pojo4 com.niewj.bean.Pojo5 pojo7 pojoWhenHasPojo4AndPojo5 Pojo7FactoryBean---FactoryBean---初始化 Pojo7[無註解java類] 初始化~~~ com.niewj.bean.Pojo7@2bbf180e com.niewj.bean.Pojo7FactoryBean@163e4e87
向spring容器中註冊組件有四種方式:
@Import導入普通bean也有四種方式: