Spring开发2 spring基础及组件使用2(conditional,import,factorybean)

JDO  java data object  99-03年 

注解:

  • 声明配置类 bean 早期从xml解析 配置类
  • @configuration  相当于 配置文件

扫描的注解: @controller  @Service @Respostry @Component

if(useDefaultFilters){

registerDefaultFilters();

}

this.includeFilters.add(new AnnotationTypeFilter(Componet.class))

以@Component--->

com.enjoy.cpa2

@Controller

@Component

@Service

IOC就是对我们Bean进行管理:bean 注册 实例化 管理

@Conditional条件注册bean

根据指定条件选择性地注册bean实例

 1 package com.enjoy.cap5.config;
 2 
 3 
 4 import com.enjoy.cap1.Person;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Configuration;
 7 
 8 
 9 @Configuration
10 public class Cap5MainConfig {
11 
12     @Bean("person")  // Bean的id 不设置id的时候,默认取的是方法名
13     public Person person(){
14         System.out.println("给容器中添加person....");
15         return new Person("person", 20);
16     }
17 
18     @Bean("lison")
19     public Person lison(){
20         System.out.println("给容器中添加lison....");
21         return new Person("Lison", 20);
22     }
23 
24     @Bean("james")  // bean在容器中的ID为james,IOC容器MAP  map.put("id", value);
25     public Person james(){
26         System.out.println("给容器中添加james....");
27         return new Person("james", 20);
28     }
29 
30     // 创建的时候就会把bean map.put到容器当中
31 
32 }
 1 import com.enjoy.cap5.config.Cap5MainConfig;
 2 import org.junit.Test;
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 public class Cap5Test {
 6 
 7     @Test
 8     public void test01(){
 9         // 创建容器将bean加载进来
10         AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap5MainConfig.class);
11 
12         System.out.println("IOC容器创建完成........");
13 
14     }
15 }

需求:测试运行时候,如果操作系统是windows,就让Lison这个对象实例化到容器中,如果是LINUX,就是让james实例化到容器中。

实现条件

beanFactory

FactoryBean  和 BeanFactory 的区别

  • FactoryBean:可以把java实例bean通过FactoryBean注入到容器中
  • BeanFactory:从容器中获取实例化后的bean
 1 package com.enjoy.cap5.config;
 2 
 3 
 4 import com.enjoy.cap1.Person;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.Conditional;
 7 import org.springframework.context.annotation.Configuration;
 8 
 9 
10 @Configuration
11 public class Cap5MainConfig {
12 
13     @Bean("person")  // Bean的id 不设置id的时候,默认取的是方法名
14     public Person person(){
15         System.out.println("给容器中添加person....");
16         return new Person("person", 20);
17     }
18 
19     @Conditional(WinCondition.class)
20     @Bean("lison")
21     public Person lison(){
22         System.out.println("给容器中添加lison....");
23         return new Person("Lison", 20);
24     }
25 
26     @Conditional(LinCondition.class)
27     @Bean("james")  // bean在容器中的ID为james,IOC容器MAP  map.put("id", value);
28     public Person james(){
29         System.out.println("给容器中添加james....");
30         return new Person("james", 20);
31     }
32 
33     // 创建的时候就会把bean map.put到容器当中
34 
35 }
 1 package com.enjoy.cap5.config;
 2 
 3 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 4 import org.springframework.context.annotation.Condition;
 5 import org.springframework.context.annotation.ConditionContext;
 6 import org.springframework.core.env.Environment;
 7 import org.springframework.core.type.AnnotatedTypeMetadata;
 8 
 9 public class LinCondition implements Condition {
10     /**
11      * ConditionContext:判断条件可以使用的上下文(环境)
12      * AnnotatedTypeMetadata:注解的信息
13      * */
14     public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
15         // TODO >> 是否为Windows
16         // 能够获取到IOC容器正在使用的beanFactory
17         ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
18         // 获取当前环境变量(包括当前操作系统是win还是linux)
19         Environment environment = conditionContext.getEnvironment();
20         String os_name = environment.getProperty("os.name");
21         System.out.println(os_name);
22 
23         if(os_name.contains("linux")){
24             return true;
25         }
26         return false;  // 返回false不起任何作用
27     }
28 }
 1 package com.enjoy.cap5.config;
 2 
 3 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 4 import org.springframework.context.annotation.Condition;
 5 import org.springframework.context.annotation.ConditionContext;
 6 import org.springframework.core.env.Environment;
 7 import org.springframework.core.type.AnnotatedTypeMetadata;
 8 
 9 public class WinCondition implements Condition {
10     /**
11      * ConditionContext:判断条件可以使用的上下文(环境)
12      * AnnotatedTypeMetadata:注解的信息
13      * */
14     public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
15         // TODO >> 是否为Windows
16         // 能够获取到IOC容器正在使用的beanFactory
17         ConfigurableListableBeanFactory beanFactory = conditionContext.getBeanFactory();
18         // 获取当前环境变量(包括当前操作系统是win还是linux)
19         Environment environment = conditionContext.getEnvironment();
20         String os_name = environment.getProperty("os.name");
21         System.out.println(os_name);
22 
23         if(os_name.contains("Windows")){
24             return true;
25         }
26         return false;  // 返回false不起任何作用
27     }
28 }

Mac OS X
Mac OS X
给容器中添加person....
IOC容器创建完成........

@Import注册bean

1,手动添加组件到IOC容器;

2,使用ImportSelector自定义返回组件

3, 使用ImportBeanDefinitionRegistrar返回自定义组件

 1 package com.enjoy.cap6.config;
 2 
 3 
 4 import com.enjoy.cap1.Person;
 5 import com.enjoy.cap6.bean.Cat;
 6 import com.enjoy.cap6.bean.Dog;
 7 import org.springframework.context.annotation.Bean;
 8 import org.springframework.context.annotation.Configuration;
 9 import org.springframework.context.annotation.Import;
10 
11 
12 @Configuration
13 @Import(value={Dog.class, Cat.class, JamesImportSelector.class})  // 相当与new一个对象放到容器中
14 
15 public class Cap6MainConfig {
16 
17    /**
18     * 给我们容器中注册组件:
19     * 1.@Bean:[导入第三方的类或包的组件],比如person为第三方的类,需要再IOC容器中使用
20     * 2.包扫描+组件的标注注解(@ComponentScan:@controller @Service @Component),一般是针对自己写的类。使用这个
21     * 3.@import:[快速给容器导入一个组件]  注意:@Bean有点简单
22     *      a. @Import(要导入到容器中的组件):容器会自动注册这个组件,bean的id为全类名(路径+id)
23     *      b. ImportSelector:是一个接口,返回需要导入到容器的组件的全类名数组
24     */
25     // 容器启动时初始化person的bean实例
26     @Bean("person")
27     public Person person(){
28         System.out.println("给容器中添加person....");
29         return new Person("person", 20);
30     }
31 
32 }
 1 package com.enjoy.cap6.config;
 2 
 3 import org.springframework.context.annotation.ImportSelector;
 4 import org.springframework.core.type.AnnotationMetadata;
 5 
 6 public class JamesImportSelector implements ImportSelector {
 7 
 8     @Override
 9     public String[] selectImports(AnnotationMetadata annotationMetadata) {
10         // 返回全类名的bean
11         return new String[]{"com.enjoy.cap6.bean.Fish", "com.enjoy.cap6.bean.Tiger"};
12     }
13 }
 1 import com.enjoy.cap6.config.Cap6MainConfig;
 2 import org.junit.Test;
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 public class Cap6Test {
 6 
 7     @Test
 8     public void test01(){
 9         // 创建容器将bean加载进来
10         AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap6MainConfig.class);
11 
12         System.out.println("IOC容器创建完成........");
13         String[] beanDefinitionNames = app.getBeanDefinitionNames();
14 
15         for(String name: beanDefinitionNames){
16             System.out.println(name);
17         }
18 
19     }
20 }
给容器中添加person....
IOC容器创建完成........
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
cap6MainConfig
com.enjoy.cap6.bean.Dog
com.enjoy.cap6.bean.Cat
com.enjoy.cap6.bean.Fish
com.enjoy.cap6.bean.Tiger
person

/**
* 给我们容器中注册组件:
* 1.@Bean:[导入第三方的类或包的组件],比如person为第三方的类,需要再IOC容器中使用
* 2.包扫描+组件的标注注解(@ComponentScan:@controller @Service @Component),一般是针对自己写的类。使用这个
* 3.@import:[快速给容器导入一个组件] 注意:@Bean有点简单
* a. @Import(要导入到容器中的组件):容器会自动注册这个组件,bean的id为全类名(路径+id)
* b. ImportSelector:是一个接口,返回需要导入到容器的组件的全类名数组
* c. ImportBeanDefinitionRegistrar:可以手动天剑组件到IOC容器,所有Bean的注册可以使用BeanDefinitionRegistry
* 4.使用Spring提供的FactoryBean(工厂bean)进行注册:把bean注入到容器中
*/
 1 package com.enjoy.cap6.config;
 2 
 3 
 4 import com.enjoy.cap1.Person;
 5 import com.enjoy.cap6.bean.Cat;
 6 import com.enjoy.cap6.bean.Dog;
 7 import org.springframework.context.annotation.Bean;
 8 import org.springframework.context.annotation.Configuration;
 9 import org.springframework.context.annotation.Import;
10 
11 
12 @Configuration
13 @Import(value={Dog.class, Cat.class, JamesImportSelector.class})  // 相当与new一个对象放到容器中
14 
15 public class Cap6MainConfig {
16 
17    /**
18     * 给我们容器中注册组件:
19     * 1.@Bean:[导入第三方的类或包的组件],比如person为第三方的类,需要再IOC容器中使用
20     * 2.包扫描+组件的标注注解(@ComponentScan:@controller @Service @Component),一般是针对自己写的类。使用这个
21     * 3.@import:[快速给容器导入一个组件]  注意:@Bean有点简单
22     *      a. @Import(要导入到容器中的组件):容器会自动注册这个组件,bean的id为全类名(路径+id)
23     *      b. ImportSelector:是一个接口,返回需要导入到容器的组件的全类名数组
24     *      c. ImportBeanDefinitionRegistrar:可以手动天剑组件到IOC容器,所有Bean的注册可以使用BeanDefinitionRegistry
25     */
26     // 容器启动时初始化person的bean实例
27     @Bean("person")
28     public Person person(){
29         System.out.println("给容器中添加person....");
30         return new Person("person", 20);
31     }
32 
33 }
 1 package com.enjoy.cap6.config;
 2 
 3 import com.enjoy.cap6.bean.Pig;
 4 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 5 import org.springframework.beans.factory.support.RootBeanDefinition;
 6 import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
 7 import org.springframework.core.type.AnnotationMetadata;
 8 
 9 public class JamesImportBeanfinitionRegistrar implements ImportBeanDefinitionRegistrar {
10 
11     /**
12      * AnnotationMetadata:当前类的注解信息
13      * BeanDefinitionRegistry:BeanDefinition注册类
14      *    把所有需要添加到容器中的bean加入;
15      *
16      **/
17     @Override
18     public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
19 
20         // 面试官:当容器中存在cat dog 才往容器中添加pig
21 
22         // 判断bean是否存在
23         boolean beanDog = beanDefinitionRegistry.containsBeanDefinition("com.enjoy.cap6.bean.Dog");
24         boolean beanCat = beanDefinitionRegistry.containsBeanDefinition("com.enjoy.cap6.bean.Cat");
25 
26         //对于我们要注册的bean,给bean进行封装     RootBeanDefinition
27 
28         // 如果dog和cat同时存在ioc容器中,那么创建pig类加入到容器当中。
29         if(beanCat && beanDog){
30             RootBeanDefinition beanDefinition = new RootBeanDefinition(Pig.class);  // 特有的容器封装
31             beanDefinitionRegistry.registerBeanDefinition("Pig", beanDefinition);
32         }
33     }
34 }

Error:(30, 49) java: 无法访问java.util.function.Supplier
找不到java.util.function.Supplier的类文件

java编译环境出错 打开File--->Projrct Struct 设置JDK版本解决

Factorybean接口实现

1,getObject()返回对象方法;

2,getObjectType返回对象类型

3, isSingleton()是否单例控制

 1 package com.enjoy.cap6.config;
 2 
 3 import com.enjoy.cap6.bean.Monkey;
 4 import org.springframework.beans.factory.FactoryBean;
 5 
 6 public class JamesFactoryBean implements FactoryBean<Monkey> {
 7     @Override
 8     public Monkey getObject() throws Exception {
 9         return new Monkey();
10     }
11 
12     @Override
13     public Class<?> getObjectType() {
14         return Monkey.class;
15     }
16 
17     // 是否单例模式  true 单实例    false 多实例
18     @Override
19     public boolean isSingleton() {
20         return false;
21     }
22 }
 1 package com.enjoy.cap6.config;
 2 
 3 import com.enjoy.cap1.Person;
 4 import com.enjoy.cap6.bean.Cat;
 5 import com.enjoy.cap6.bean.Dog;
 6 import org.springframework.context.annotation.Bean;
 7 import org.springframework.context.annotation.Configuration;
 8 import org.springframework.context.annotation.Import;
 9 
10 @Configuration
11 @Import(value={Dog.class, Cat.class, JamesImportSelector.class, JamesImportBeanDefinitionRegistrar.class})  // 相当与new一个对象放到容器中
12 
13 public class Cap6MainConfig {
14 
15    /**
16     * 给我们容器中注册组件:
17     * 1.@Bean:[导入第三方的类或包的组件],比如person为第三方的类,需要再IOC容器中使用
18     * 2.包扫描+组件的标注注解(@ComponentScan:@controller @Service @Component),一般是针对自己写的类。使用这个
19     * 3.@import:[快速给容器导入一个组件]  注意:@Bean有点简单
20     *      a. @Import(要导入到容器中的组件):容器会自动注册这个组件,bean的id为全类名(路径+id)
21     *      b. ImportSelector:是一个接口,返回需要导入到容器的组件的全类名数组
22     *      c. ImportBeanDefinitionRegistrar:可以手动天剑组件到IOC容器,所有Bean的注册可以使用BeanDefinitionRegistry
23     * 4.使用Spring提供的FactoryBean(工厂bean)进行注册:把bean注入到容器中
24     */
25     // 容器启动时初始化person的bean实例
26     @Bean("person")
27     public Person person(){
28         System.out.println("给容器中添加person....");
29         return new Person("person", 20);
30     }
31 
32     @Bean
33     public JamesFactoryBean jamesFactoryBean(){
34         return new JamesFactoryBean();
35     }
36 
37 }
 1 import com.enjoy.cap6.config.Cap6MainConfig;
 2 import org.junit.Test;
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 public class Cap6Test {
 6 
 7     @Test
 8     public void test01(){
 9         // 创建容器将bean加载进来
10         AnnotationConfigApplicationContext app = new AnnotationConfigApplicationContext(Cap6MainConfig.class);
11 
12         System.out.println("IOC容器创建完成........");
13         String[] beanDefinitionNames = app.getBeanDefinitionNames();
14 
15         for(String name: beanDefinitionNames){
16             System.out.println(name);
17         }
18 
19         Object bean1 = app.getBean("jamesFactoryBean");
20         System.out.println("bean的类型="+bean1.getClass());
21     }
22 }

生命周期-初始化与销毁

如何定义和销毁3种方式;

  • 1, 指定初始化和销毁方法
  • 2,让Bean实现 InitializingBean(定义初始化逻辑)
  • 3, 使用JSR250规则定义的两个注解来实现

猜你喜欢

转载自www.cnblogs.com/JCcodeblgos/p/11516591.html