@Configuration註解告訴Spring這是一個配置類linux
@Bean註解是給容器中註冊一個Bean,類型是返回值的類型,id默認是方法名做爲idspring
@Bean("person") public Person person2(){ System.out.println("create a new bean of person"); return new Person(); }
@ComponentScan(value = "com.eric",excludeFilters = {
@ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class})windows
@ComponentScan 的屬性數組
/** * Description: spring-parent * 配置類==配置文件 * * @author caoqianqian * @date 2021/2/14 */ @Configuration //告訴Spring這是一個配置類 @ComponentScan(value = "com.eric",excludeFilters = { @ComponentScan.Filter(type = FilterType.ANNOTATION,classes = {Controller.class, Service.class}) }) public class MainConfig { //給容器中註冊一個Bean,類型是返回值的類型,id默認是方法名做爲id @Bean public Person person(){ return new Person("testName",20); } }
經過@Scope註解來制定該bean的做用範圍,也能夠說是調整做用域,ioc容器中加載的組件默認是單實例的。session
做用域範圍即value的可取值範圍ide
//經過@Scope註解來制定該bean的做用範圍,也能夠說是調整做用域 @Scope("singleton") @Bean("person") public Person person() { System.out.println("I'm creating an instance Person"); return new Person("Person", 28); }
單實例bean:默認在容器啓動的時候建立對象。
懶加載:容器啓動不建立對象,第一次使用(獲取)bean時建立對象,並初始化。測試
單實例bean加上懶加載的註解以後容器啓動時不建立對象,第一次使用時纔會去建立對象並初始化。prototype
@Bean("person") @Lazy public Person person2(){ System.out.println("create a new bean of person"); return new Person(); }
@Conditional按照必定的條件進行判斷,知足條件給容器中註冊beancode
標在方法上,表示這個方法知足必定條件纔會生效。component
標在類上,類中組件統一設置,表示知足當前條件,這個類中配置的全部bean註冊纔會生效
判斷是不是Linux系統
public class LinuxCondition implements Condition { /** *判斷是不是Linux系統 * @param conditionContext 判斷條件能使用的上下文(環境) * @param annotatedTypeMetadata 當前標註註解的註釋信息 * @return */ @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { //能獲取到ioc使用的beanFactory ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory(); //獲取類加載器 ClassLoader classLoader = conditionContext.getClassLoader(); //獲取當前環境信息 Environment environment = conditionContext.getEnvironment(); //獲取bean定義的註冊類 BeanDefinitionRegistry registry = conditionContext.getRegistry(); //判斷容器中bean的註冊狀況 boolean definition = registry.containsBeanDefinition("person"); RootBeanDefinition beanDefinition = new RootBeanDefinition(Person.class); //給容器中註冊bean registry.registerBeanDefinition("person2",beanDefinition); String property = environment.getProperty("os.name"); if(property.contains("linux")){ return true; } return false; } }
判斷是不是Windows系統
public class WindowsCondition implements Condition { @Override public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { Environment environment = conditionContext.getEnvironment(); String osName = environment.getProperty("os.name"); if (osName.contains("Windows")){ return true; } return false; } }
配置類
@Configuration public class MainConfig2 { /** *Conditional({Condition}):按照必定的條件進行判斷,知足條件給容器中註冊bean * 若是系統是windows,給容器中註冊("bill") * 若是系統是linux,給容器中註冊("linus") * @return */ @Conditional({WindowsCondition.class}) @Bean("bill") public Person person(){ return new Person("Bill Gates",62); } @Conditional({LinuxCondition.class}) @Bean("linus") public Person person2(){ return new Person("linus",42); } @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); } }
測試方法
@Test public void testCondition() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); ConfigurableEnvironment environment = ac.getEnvironment(); String[] beanNamesForType = ac.getBeanNamesForType(Person.class); //動態獲取環境變量的值:windows 7 String property = environment.getProperty("os.name"); System.out.println(property); for (String p:beanNamesForType) { System.out.println(p); } }
運行結果以下,Windows 7的系統因此bill註冊了進來
Windows 7 bill person2
快速導入組件,id默認是組件的全類名
配置類上加了@Import註解
@Configuration @Import({Color.class, Dog.class}) public class MainConfig2 { /** *Conditional({Condition}):按照必定的條件進行判斷,知足條件給容器中註冊bean * 若是系統是windows,給容器中註冊("bill") * 若是系統是linux,給容器中註冊("linus") * @return */ @Conditional({WindowsCondition.class}) @Bean("bill") public Person person(){ return new Person("Bill Gates",62); } @Conditional({LinuxCondition.class}) @Bean("linus") public Person person2(){ return new Person("linus",22); } }
測試方法
@Test public void testImport() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); String[] beanNamesForType = ac.getBeanDefinitionNames(); for (String p:beanNamesForType) { System.out.println(p); } }
運行結果:除了內部的bean,Color和Dog也被註冊進來了
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 mainConfig2 com.eric.bean.Color com.eric.bean.Dog bill person2
//自定義邏輯返回須要導入的組件 public class MyImportSelector implements ImportSelector { //返回值就是導入到容器中的組件的全類名 //AnnotationMetadata 當前標註@Import註解類的全部註解信息 @Override public String[] selectImports(AnnotationMetadata annotationMetadata) { Set<String> annotationTypes = annotationMetadata.getAnnotationTypes(); for(String str : annotationTypes){ System.out.println("===="+str); } return new String[]{"com.eric.bean.Blue","com.eric.bean.Red"}; } }
@Import註解加上自定義的組件MyImportSelector
@Configuration @Import({Color.class, Dog.class,MyImportSelector.class}) public class MainConfig2 { /** *Conditional({Condition}):按照必定的條件進行判斷,知足條件給容器中註冊bean * 若是系統是windows,給容器中註冊("bill") * 若是系統是linux,給容器中註冊("linus") * @return */ @Conditional({WindowsCondition.class}) @Bean("bill") public Person person(){ return new Person("Bill Gates",62); } @Conditional({LinuxCondition.class}) @Bean("linus") public Person person2(){ return new Person("linus",22); } }
測試方法
@Test public void testImport() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); String[] beanNamesForType = ac.getBeanDefinitionNames(); for (String p:beanNamesForType) { System.out.println(p); } }
運行結果:Blue Red 都被註冊進來了
====org.springframework.context.annotation.Configuration ====org.springframework.context.annotation.Import 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 mainConfig2 com.eric.bean.Color com.eric.bean.Dog com.eric.bean.Blue com.eric.bean.Red bill person2
手動註冊bean到容器中
//要被註冊的bean public class Rainbow { }
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar { /** * * @param importingClassMetadata 當前類的註解信息 * @param registry BeanDefinition註冊類 * 把全部須要添加到容器中的bean,調用 * BeanDefinitionRegistry.registerBeanDefinition手工註冊進來 */ @Override public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) { boolean blueDefinition = registry.containsBeanDefinition("com.eric.bean.Blue"); if (blueDefinition){ //指定bean的定義信息 RootBeanDefinition beanDefinition = new RootBeanDefinition(Rainbow.class); //註冊一個bean,指定bean名 registry.registerBeanDefinition("rainbow", beanDefinition); } } }
配置類:@Import加入了中MyImportBeanDefinitionRegistrar
@Configuration @Import({Color.class, Blue.class,MyImportBeanDefinitionRegistrar.class}) public class MainConfig2 { }
測試方法:
@Test public void testImport() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); String[] beanNamesForType = ac.getBeanDefinitionNames(); for (String p:beanNamesForType) { System.out.println(p); } }
運行結果:邏輯判斷Blue存在因此rainbow被註冊了進來
mainConfig2 com.eric.bean.Blue bill person2 rainbow
使用spring提供的FactoryBean(工廠Bean)
建立一個ColorFactoryBean實現FactoryBean接口:
//建立一個Spring定義的FactoryBean public class ColorFactoryBean implements FactoryBean<Color> { /** * 返回一個Color對象,這個對象會添加到容器中 * @return * @throws Exception */ @Override public Color getObject() throws Exception { System.out.println("ColorFactoryBean=========getObject====="); return new Color(); } /** * 返回的bean類型 * @return */ @Override public Class<Color> getObjectType() { return Color.class; } /** * 是否單例 * 返回true表明是單實例,在容器中保存一份 * false是多實例,每次獲取都會建立一個新的bean * @return */ @Override public boolean isSingleton() { return true; } }
配置類裏註冊該工廠bean
@Configuration public class MainConfig2 { @Bean public ColorFactoryBean colorFactoryBean(){ return new ColorFactoryBean(); } }
測試方法:
@Test public void testFactoryBean() { AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(MainConfig2.class); //工廠bean獲取的是調用getObject()方法建立的對象 Object bean1 = ac.getBean("colorFactoryBean"); Object bean2 = ac.getBean("colorFactoryBean"); System.out.println("bean的類型:"+bean1.getClass()); //單實例返回true 多實例返回false System.out.println(bean1 == bean2); //默認獲取到的是工廠bean調用getObejct建立的對象 //要獲取工廠bean自己,咱們須要給id前面加一個&標識 Object bean3 = ac.getBean("&colorFactoryBean"); System.out.println("bean3的類型:"+bean3.getClass()); }
運行結果: 單實例獲取到的是相同的bean,加&以後獲取到的bean爲ColorFactoryBean
ColorFactoryBean=========getObject===== bean的類型:class com.eric.bean.Color true bean3的類型:class com.eric.condition.ColorFactoryBean
給容器中註冊組件:
ok,組件註冊完結,撒花。