Spring常用注解式开发

时间:2019-12-12
本文章向大家介绍Spring常用注解式开发,主要包括Spring常用注解式开发使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1、组件注册@Configuration、@Bean给容器中注册组件。

  注解,@Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
  注解,@Bean给Spring容器注入一个bean对象,bean.xml配置文件里面的class属性,在注解式开发中class类型是返回值的类型,bean.xml配置文件里面的id属性,在注解式开发中id默认是方法名称。

2、组件注册@ComponentScan自动扫描组件、指定扫描规则。

  注解,@ComponentScan包扫描注解,只要标注了@Controller、@Service、@Repository、@Component注解组件都会被扫描,然后将对应的bean实例添加到spring容器中。

3、使用maven构建项目,学习Spring的注解开发,如下所示。

 1 <project xmlns="http://maven.apache.org/POM/4.0.0"
 2     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 3     xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
 4     http://maven.apache.org/xsd/maven-4.0.0.xsd">
 5     <modelVersion>4.0.0</modelVersion>
 6     <groupId>com.bie</groupId>
 7     <artifactId>spring-annotation</artifactId>
 8     <version>0.0.1-SNAPSHOT</version>
 9 
10     <dependencies>
11         <!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
12         <dependency>
13             <groupId>org.springframework</groupId>
14             <artifactId>spring-context</artifactId>
15             <version>4.3.12.RELEASE</version>
16         </dependency>
17         <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok -->
18         <dependency>
19             <groupId>org.projectlombok</groupId>
20             <artifactId>lombok</artifactId>
21             <version>1.18.8</version>
22             <scope>provided</scope>
23         </dependency>
24 
25     </dependencies>
26 
27 </project>

先搞一个实体类,用于数据的传输。

 1 package com.bie.po;
 2 
 3 import lombok.AllArgsConstructor;
 4 import lombok.Data;
 5 import lombok.NoArgsConstructor;
 6 
 7 /**
 8  * 
 9  *
10  * @Title: Person.java
11  * @Package com.bie.po
12  * @Description: TODO
13  * @author biehl
14  * @date 2019年12月9日
15  * @version V1.0
16  *
17  */
18 @AllArgsConstructor
19 @NoArgsConstructor
20 @Data
21 public class Person {
22 
23     private Integer id;
24     private String name;
25 
26 }

组件注册@Configuration、@Bean给容器中注册组件。组件注册@ComponentScan自动扫描组件、指定扫描规则。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.ComponentScan;
 5 import org.springframework.context.annotation.ComponentScan.Filter;
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.context.annotation.FilterType;
 8 import org.springframework.stereotype.Repository;
 9 
10 import com.bie.filter.PersonCustomFilter;
11 import com.bie.po.Person;
12 
13 /**
14  * 
15  *
16  * @Title: SpringApplicationConfig.java
17  * @Package com.bie.config
18  * @Description: TODO
19  * @author biehl
20  * @date 2019年12月9日
21  * @version V1.0
22  * 
23  * 
24  *          1、组件注册@Configuration、@Bean给容器中注册组件。
25  * 
26  *          2、组件注册@ComponentScan自动扫描组件、指定扫描规则
27  * 
28  */
29 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
30 @Configuration
31 
32 // @ComponentScan,只要标注了@Controller、@Service、@Repository、@Component注解组件都会被扫描,然后将对应的bean实例添加到spring容器中。
33 // jdk1.8版本的时候,@ComponentScan新增了@Repeatable,可以写多次@ComponentScan注解。
34 // value属性值指定了要扫描的包。
35 // excludeFilters属性值是Filter[]数组。Filter数组是一个@Filter注解。指定扫描的时候按照什么规则排除那些组件。
36 // includeFilter属性值是只包含。Filter[]。Filter数组是一个@Filter注解。指定扫描的时候只需要包含那些组件。
37 @ComponentScan(value = "com.bie",
38 
39         // excludeFilters排除的规则。
40         excludeFilters = {
41 
42                 // @Filter注解进行排除要扫描的包
43                 // type属性排除的规则,ANNOTATION按照注解排除、ASSIGNABLE_TYPE按照给定的类型排除、ASPECTJ表达式排除、REGEX正则表达式排除、CUSTOM自定义排除。
44                 // classes属性是按照类进行排除。
45                 @Filter(type = FilterType.ANNOTATION, classes = { Repository.class }) },
46 
47         // includeFilter只包含规则。includeFilters需要useDefaultFilters配合使用。
48         includeFilters = {
49 
50                 // @Filter(type = FilterType.ANNOTATION, classes = { Service.class }),
51                 // ASSIGNABLE_TYPE按照给的的类型进行包含,比如只要是PersonDao类型的组件都会加载到容器中,不管是子类还是实现类等等。
52                 // @Filter(type = FilterType.ASSIGNABLE_TYPE, classes = { PersonDao.class }),
53                 // 自定义过滤规则,自定义包含规则。
54                 @Filter(type = FilterType.CUSTOM, classes = { PersonCustomFilter.class })
55 
56         },
57 
58         // 禁用掉默认的过滤规则。默认的规则是扫描所有的。useDefaultFilters = false才使includeFilters只包含生效。
59         useDefaultFilters = false
60 
61 )
62 public class SpringApplicationConfig {
63 
64     @Bean(value = "person")
65     // @Bean给Spring容器注入一个bean对象
66     // bean.xml配置文件里面的class属性,在注解式开发中class类型是返回值的类型
67     // bean.xml配置文件里面的id属性,在注解式开发中id默认是方法名称
68     public Person person() {
69         return new Person(1008611, "张三");
70     }
71 
72 }

自定义过滤规则,自定义包含规则。

 1 package com.bie.filter;
 2 
 3 import java.io.IOException;
 4 
 5 import org.springframework.core.io.Resource;
 6 import org.springframework.core.type.AnnotationMetadata;
 7 import org.springframework.core.type.ClassMetadata;
 8 import org.springframework.core.type.classreading.MetadataReader;
 9 import org.springframework.core.type.classreading.MetadataReaderFactory;
10 import org.springframework.core.type.filter.TypeFilter;
11 
12 /**
13  * 
14  *
15  * @Title: PersonCustomFilter.java
16  * @Package com.bie.filter
17  * @Description: TODO
18  * @author biehl
19  * @date 2019年12月9日
20  * @version V1.0
21  *
22  */
23 public class PersonCustomFilter implements TypeFilter {
24 
25     /**
26      * metadataReader读取到的当前正在扫描的类的信息。
27      * 
28      * 
29      * metadataReaderFactory是一个工厂,可以获取到其他任何类的信息。
30      */
31     @Override
32     public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
33             throws IOException {
34         // 获取当前类注解的信息
35         AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
36         // 获取当前正在扫描的类的类信息
37         ClassMetadata classMetadata = metadataReader.getClassMetadata();
38         // 获取当前类资源信息,比如类的路径等等
39         Resource resource = metadataReader.getResource();
40 
41         // 获取到类的名称
42         String className = classMetadata.getClassName();
43         System.out.println("-------------------------------------------" + className);
44         // 如果包含er就会被扫描
45         if (className.contains("er")) {
46             return true;
47         }
48         return false;
49     }
50 
51 }

搞一个测试类,来进行注解版开发的使用。

 1 package com.bie.main;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 5 
 6 import com.bie.config.SpringApplicationConfig;
 7 import com.bie.po.Person;
 8 
 9 /**
10  * 
11  *
12  * @Title: SpringApplication.java
13  * @Package com.bie.main
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  *
19  */
20 public class SpringApplication {
21 
22     public static void main(String[] args) {
23         // 获取到注解配置类
24         ApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig.class);
25         // 根据类型获取到spring容器中的bean对象实例
26         Person person = ac.getBean(Person.class);
27         System.out.println(person.toString());
28         System.out.println("===========================================");
29 
30         // 根据实例类型获取到spring容器中bean实例的名称
31         String[] beanNamesForType = ac.getBeanNamesForType(Person.class);
32         for (String s : beanNamesForType) {
33             System.out.println(s);
34         }
35         System.out.println("===========================================");
36 
37         // 获取到spring容器中定义的bean实例名称。
38         String[] beanDefinitionNames = ac.getBeanDefinitionNames();
39         for (String s : beanDefinitionNames) {
40             System.out.println(s);
41         }
42         System.out.println("===========================================");
43 
44     }
45 
46 }

4、组件注册@Scope设置组件作用域。@Scope指定作用范围,默认是单实例的singleton单实例,还有prototype多实例、request同一次请求创建一个实例、session同一个session创建一个实例。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.ComponentScan;
 5 import org.springframework.context.annotation.ComponentScan.Filter;
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.context.annotation.FilterType;
 8 import org.springframework.context.annotation.Scope;
 9 import org.springframework.stereotype.Repository;
10 
11 import com.bie.filter.PersonCustomFilter;
12 import com.bie.po.Person;
13 
14 /**
15  * 
16  *
17  * @Title: SpringApplicationConfig.java
18  * @Package com.bie.config
19  * @Description: TODO
20  * @author biehl
21  * @date 2019年12月9日
22  * @version V1.0
23  * 
24  * 
25  *          1、组件注册@Configuration、@Bean给容器中注册组件。
26  * 
27  *          2、组件注册@ComponentScan自动扫描组件、指定扫描规则
28  * 
29  */
30 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
31 @Configuration
32 public class SpringApplicationConfig2 {
33 
34     @Bean(value = "person")
35     // @Bean给Spring容器注入一个bean对象
36     // bean.xml配置文件里面的class属性,在注解式开发中class类型是返回值的类型
37     // bean.xml配置文件里面的id属性,在注解式开发中id默认是方法名称
38     @Scope("prototype") // @Scope指定作用范围,默认是单实例的singleton单实例,还有prototype多实例、request同一次请求创建一个实例、session同一个session创建一个实例
39     // singleton单实例,ioc容器启动就会调用方法创建对象放入到ioc容器中。以后每次获取直接从容器中来拿。
40     // prototype多实例,ioc容器启动不会调用方法创建对象放在容器中,而是每次获取的时候才会调用方法创建对象。每次获取都会调用一遍。
41     public Person person() {
42         System.out.println("容器中添加person实例.....");
43         return new Person(1008611, "张三三");
44     }
45 
46 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 5 
 6 import com.bie.config.SpringApplicationConfig2;
 7 import com.bie.po.Person;
 8 
 9 /**
10  * 
11  *
12  * @Title: SpringApplication.java
13  * @Package com.bie.main
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  *
19  */
20 public class SpringApplication {
21 
22     public static void main(String[] args) {
23         // 获取到注解配置类
24         ApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig2.class);
25         System.out.println("ioc容器创建完成.....");
26         // 根据名称获取到spring容器中的bean对象实例
27         // 默认添加到spring容器中的bean实例是单实例的。
28         Person person = (Person) ac.getBean("person");
29         Person person2 = (Person) ac.getBean("person");
30         System.out.println("person : " + person.hashCode());
31         System.out.println("person2 : " + person.hashCode());
32         System.out.println(person == person2);
33         System.out.println("===========================================" + person);
34         System.out.println("===========================================" + person2);
35     }
36 
37 }

5、组件注册@Lazy,bean懒加载。单实例bean,默认在容器启动的时候创建对象,创建完对象将bean实例放入到容器中。懒加载就是容器启动的时候先不创建对象。当第一次使用bean实例的时候创建对象,并进行初始化。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.ComponentScan;
 5 import org.springframework.context.annotation.ComponentScan.Filter;
 6 import org.springframework.context.annotation.Configuration;
 7 import org.springframework.context.annotation.FilterType;
 8 import org.springframework.context.annotation.Lazy;
 9 import org.springframework.context.annotation.Scope;
10 import org.springframework.stereotype.Repository;
11 
12 import com.bie.filter.PersonCustomFilter;
13 import com.bie.po.Person;
14 
15 /**
16  * 
17  *
18  * @Title: SpringApplicationConfig.java
19  * @Package com.bie.config
20  * @Description: TODO
21  * @author biehl
22  * @date 2019年12月9日
23  * @version V1.0
24  * 
25  * 
26  *          1、组件注册@Configuration、@Bean给容器中注册组件。
27  * 
28  *          2、组件注册@ComponentScan自动扫描组件、指定扫描规则
29  * 
30  */
31 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
32 @Configuration
33 public class SpringApplicationConfig2 {
34 
35     @Bean(value = "person")
36     // @Bean给Spring容器注入一个bean对象
37     // bean.xml配置文件里面的class属性,在注解式开发中class类型是返回值的类型
38     // bean.xml配置文件里面的id属性,在注解式开发中id默认是方法名称
39     @Scope("singleton") // @Scope指定作用范围,默认是单实例的singleton单实例,还有prototype多实例、request同一次请求创建一个实例、session同一个session创建一个实例
40     // singleton单实例,ioc容器启动就会调用方法创建对象放入到ioc容器中。以后每次获取直接从容器中来拿。
41     // prototype多实例,ioc容器启动不会调用方法创建对象放在容器中,而是每次获取的时候才会调用方法创建对象。每次获取都会调用一遍。
42     @Lazy(value = true) // 懒加载,默认是true
43     // 懒加载就是容器启动的时候先不创建对象。当第一次使用bean实例的时候创建对象,并进行初始化。
44     public Person person() {
45         System.out.println("容器中添加person实例.....");
46         return new Person(1008611, "张三三");
47     }
48 
49 }

6、组件注册@Conditional按照条件向spring容器中注册bean实例。按照一定的条件进行判断,满足条件给容器中注册bean。如果不满足条件,则不进行bean实例的注册。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Conditional;
 5 import org.springframework.context.annotation.Configuration;
 6 
 7 import com.bie.condition.LinuxCondition;
 8 import com.bie.condition.WindowCondition;
 9 import com.bie.po.Person;
10 
11 /**
12  * 
13  *
14  * @Title: SpringApplicationConfig.java
15  * @Package com.bie.config
16  * @Description: TODO
17  * @author biehl
18  * @date 2019年12月9日
19  * @version V1.0
20  * 
21  * 
22  *          1、组件注册@Configuration、@Bean给容器中注册组件。
23  * 
24  *          2、组件注册@ComponentScan自动扫描组件、指定扫描规则
25  * 
26  */
27 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
28 @Configuration
29 public class SpringApplicationConfig3 {
30 
31     @Bean(value = "zhangsan")
32     // @Bean给Spring容器注入一个bean对象
33     // bean.xml配置文件里面的class属性,在注解式开发中class类型是返回值的类型
34     // bean.xml配置文件里面的id属性,在注解式开发中id默认是方法名称
35     @Conditional(value = { WindowCondition.class })
36     // 如果是window操作系统返回zhangsan
37     // @Conditional注解不仅可以标注到方法上,标注到方法上表示用当前的bean按照条件进行判断。
38     // @Conditional注解还可以标注到类上面,标注到类上满足当前条件,这个类中配置的所有bean注册才能生效。类中组件统一设置。
39     public Person person() {
40         System.out.println("容器中添加person实例.....");
41         return new Person(1008611, "张三三");
42     }
43 
44     @Bean(value = "zhaoliu")
45     @Conditional(value = { LinuxCondition.class })
46     // 如果是window操作系统返回zhaoliuliu
47     public Person person02() {
48         System.out.println("容器中添加person实例.....");
49         return new Person(1008611, "赵六六");
50     }
51 
52 }

使用@Conditional注解必须实现Condition接口,然后进行条件判断的实现,如下所示:

 1 package com.bie.condition;
 2 
 3 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 4 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 5 import org.springframework.context.annotation.Condition;
 6 import org.springframework.context.annotation.ConditionContext;
 7 import org.springframework.core.env.Environment;
 8 import org.springframework.core.type.AnnotatedTypeMetadata;
 9 
10 /**
11  * 
12  *
13  * @Title: WindowCondition.java
14  * @Package com.bie.condition
15  * @Description: TODO
16  * @author biehl
17  * @date 2019年12月10日
18  * @version V1.0
19  *
20  *          判断是否是window系统。
21  *          
22  *          
23  */
24 public class WindowCondition implements Condition {
25 
26     /**
27      * context判断条件能使用的上下文环境。
28      * 
29      * metadata标注了Condition注解的注释信息
30      */
31     @Override
32     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
33         // 是否是window操作系统
34         // 1、可以获取到ioc使用的bean工厂
35         ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
36         // 2、 获取到类加载器
37         ClassLoader classLoader = context.getClassLoader();
38         // 3、获取到环境变量信息,封装了运行时信息,环境变量,虚拟机变量等等。
39         Environment environment = context.getEnvironment();
40         // 4、获取到bean定义的注册类
41         BeanDefinitionRegistry registry = context.getRegistry();
42         // 判断容器中是否包含某一个bean实例。如果不存在还可以进行注册bean实例。
43         boolean containsBeanDefinition = registry.containsBeanDefinition("springApplicationConfig3");
44 
45         // 判断操作系统
46         String osName = environment.getProperty("os.name");
47         if (osName.contains("Windows") && containsBeanDefinition) {
48             return true;
49         }
50         return false;
51     }
52 
53 }
 1 package com.bie.condition;
 2 
 3 import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
 4 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 5 import org.springframework.context.annotation.Condition;
 6 import org.springframework.context.annotation.ConditionContext;
 7 import org.springframework.core.env.Environment;
 8 import org.springframework.core.type.AnnotatedTypeMetadata;
 9 
10 /**
11  * 
12  *
13  * @Title: LinuxCondition.java
14  * @Package com.bie.condition
15  * @Description: TODO
16  * @author biehl
17  * @date 2019年12月10日
18  * @version V1.0
19  * 
20  *          判断是否是linux系统
21  */
22 public class LinuxCondition implements Condition {
23 
24     @Override
25     public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
26         // 是否是window操作系统
27         // 1、可以获取到ioc使用的bean工厂
28         ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
29         // 2、 获取到类加载器
30         ClassLoader classLoader = context.getClassLoader();
31         // 3、获取到环境变量信息,封装了运行时信息,环境变量,虚拟机变量等等。
32         Environment environment = context.getEnvironment();
33         // 4、获取到bean定义的注册类
34         BeanDefinitionRegistry registry = context.getRegistry();
35 
36         // 判断操作系统
37         String osName = environment.getProperty("os.name");
38         if (osName.contains("linux")) {
39             return true;
40         }
41         return false;
42     }
43 
44 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import java.util.Map;
 4 import java.util.Map.Entry;
 5 import java.util.Set;
 6 
 7 import org.springframework.context.ApplicationContext;
 8 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 9 import org.springframework.core.env.Environment;
10 
11 import com.bie.config.SpringApplicationConfig3;
12 import com.bie.po.Person;
13 
14 /**
15  * 
16  *
17  * @Title: SpringApplication.java
18  * @Package com.bie.main
19  * @Description: TODO
20  * @author biehl
21  * @date 2019年12月9日
22  * @version V1.0
23  *
24  */
25 public class SpringApplication {
26 
27     public static void main(String[] args) {
28         // 获取到注解配置类
29         ApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig3.class);
30         // 获取操作系统环境变量的值
31         // Environment environment = ac.getEnvironment();
32         // String osName = environment.getProperty("os.name");
33         // System.out.println("==========================================" + osName);
34 
35         System.out.println("ioc容器创建完成.....");
36         // 根据名称获取到spring容器中的bean对象实例
37         // 默认添加到spring容器中的bean实例是单实例的。
38         Person zhangsan = (Person) ac.getBean("zhangsan");
39         // Person zhaoliu = (Person) ac.getBean("zhaoliu");
40         System.out.println("zhangsan : " + zhangsan.hashCode());
41         // System.out.println("zhaoliu : " + zhaoliu.hashCode());
42         System.out.println("===========================================" + zhangsan);
43         // System.out.println("===========================================" + zhaoliu);
44         System.out.println("===========================================");
45 
46         // 获取到spring容器中定义的bean实例名称。
47         String[] beanDefinitionNames = ac.getBeanDefinitionNames();
48         for (String s : beanDefinitionNames) {
49             System.out.println(s);
50         }
51         System.out.println("===========================================");
52 
53         // 根据实例类型获取到spring容器中bean实例的名称
54         String[] beanNamesForType = ac.getBeanNamesForType(Person.class);
55         for (String s : beanNamesForType) {
56             System.out.println(s);
57         }
58         System.out.println("===========================================");
59 
60         // 根据类型获取到ioc容器中的bean实例
61         Map<String, Person> beansOfType = ac.getBeansOfType(Person.class);
62         for (Map.Entry<String, Person> entrySet : beansOfType.entrySet()) {
63             String key = entrySet.getKey();
64             Person value = entrySet.getValue();
65             System.out.println("key : " + key + ", " + "value : " + value);
66         }
67 
68     }
69 
70 }

7、组件注册@Import给容器中快速导入一个组件。

给容器中注册组件。
  1)、第一种方式是包扫描和组件标注注解(注解包含@Controller、@Service、@Repository、@Component等等)。具有局限性,只能将自己的类进行注解,将实例bean注入到spirng容器中。
  2)、第二种方式是,@Bean注解,导入的第三方包里面的组件。
  3)、第三种方式是,@Import注解,快速给容器中导入一个组件。@Import注解可以直接写要导入容器中的组件,容器中就会自动注册这个组件,id默认是全类名称。

  4)、第四种方式是,组件注册使用Spring提供的FactoryBean(工厂Bean)注册组件。FactoryBean是一个接口,T getObject();调用该方法返回的的T对象放入到Bean容器中。Class<?> getObjectType();调用该方法,返回对象的类型。boolean isSingleton();调用该方法是否单例模式。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Conditional;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.context.annotation.Import;
 7 
 8 import com.bie.bean.Dog;
 9 import com.bie.condition.LinuxCondition;
10 import com.bie.condition.WindowCondition;
11 import com.bie.po.Person;
12 
13 /**
14  * 
15  *
16  * @Title: SpringApplicationConfig.java
17  * @Package com.bie.config
18  * @Description: TODO
19  * @author biehl
20  * @date 2019年12月9日
21  * @version V1.0
22  * 
23  * 
24  *          1、组件注册@Configuration、@Bean给容器中注册组件。
25  * 
26  *          2、组件注册@ComponentScan自动扫描组件、指定扫描规则
27  * 
28  */
29 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
30 @Configuration
31 @Import(value = { Dog.class }) // @Import注解,快速给容器中导入一个组件。
32 public class SpringApplicationConfig4 {
33 
34 }
 1 package com.bie.bean;
 2 
 3 /**
 4  * 
 5  *
 6  * @Title: Dog.java
 7  * @Package com.bie.bean
 8  * @Description: TODO
 9  * @author biehl
10  * @date 2019年12月10日
11  * @version V1.0
12  *
13  */
14 public class Dog {
15 
16 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 5 
 6 import com.bie.config.SpringApplicationConfig4;
 7 
 8 /**
 9  * 
10  *
11  * @Title: SpringApplication.java
12  * @Package com.bie.main
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月9日
16  * @version V1.0
17  *
18  */
19 public class SpringApplication {
20 
21     public static void main(String[] args) {
22         // 获取到注解配置类
23         ApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig4.class);
24         // 获取到spring容器中定义的bean实例名称。
25         String[] beanDefinitionNames = ac.getBeanDefinitionNames();
26         for (String s : beanDefinitionNames) {
27             System.out.println(s);
28         }
29         System.out.println("===========================================");
30 
31     }
32 
33 }

7.1、组件注册@Import使用ImportSelector,ImportSelector是Import的选择器。ImportSelector是一个接口,规定方法selectImports,返回值String[]字符串数组,数组里面就是类的全类名,返回需要导入的组件的全类名数组。 

 1 package com.bie.bean;
 2 
 3 import org.springframework.context.annotation.ImportSelector;
 4 import org.springframework.core.type.AnnotationMetadata;
 5 
 6 /**
 7  * 
 8  *
 9  * @Title: DogImportSelector.java
10  * @Package com.bie.bean
11  * @Description: TODO
12  * @author biehl
13  * @date 2019年12月10日
14  * @version V1.0
15  * 
16  *          自定义逻辑返回需要导入的组件
17  * 
18  */
19 public class DogImportSelector implements ImportSelector {
20 
21     /**
22      * 返回值就是要导入到容器中的组件全类名。
23      * 
24      * importingClassMetadata,当前标注@Import注解的类的所有注解信息。
25      */
26     @Override
27     public String[] selectImports(AnnotationMetadata importingClassMetadata) {
28         String className = importingClassMetadata.getClassName();
29         // @Import(value = { DogImportSelector.class })。获取到的类名是标注了该类的名称。
30         System.out.println("className : " + className);
31         
32         // 方法不能返回null,可以返回空数组
33         return new String[] { "com.bie.bean.Dog" };
34     }
35 
36 }

使用@Import注解可以ImportSelector这个接口。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Configuration;
 4 import org.springframework.context.annotation.Import;
 5 
 6 import com.bie.bean.DogImportSelector;
 7 
 8 /**
 9  * 
10  *
11  * @Title: SpringApplicationConfig.java
12  * @Package com.bie.config
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月9日
16  * @version V1.0
17  * 
18  * 
19  *          1、组件注册@Configuration、@Bean给容器中注册组件。
20  * 
21  *          2、组件注册@ComponentScan自动扫描组件、指定扫描规则
22  * 
23  */
24 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
25 @Configuration
26 @Import(value = { DogImportSelector.class }) // @Import注解,快速给容器中导入一个组件。
27 public class SpringApplicationConfig4 {
28 
29 }

7.2、组件注册@Import使用ImportBeanDefinitionRegistrar,ImportBeanDefinitionRegistrar是一个接口,规定方法registerBeanDefinitions,返回值是空void。通过调用该方法自己给容器中添加组件。importingClassMetadata是当前类的注解信息,registry是bean定义的注册类,使用registry给容器注册一个bean实例。

 1 package com.bie.config;
 2 
 3 import org.springframework.cache.Cache;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.context.annotation.Import;
 6 
 7 import com.bie.bean.Cat;
 8 import com.bie.bean.Dog;
 9 import com.bie.bean.DogImportBeanDefinitionRegistrar;
10 
11 /**
12  * 
13  *
14  * @Title: SpringApplicationConfig.java
15  * @Package com.bie.config
16  * @Description: TODO
17  * @author biehl
18  * @date 2019年12月9日
19  * @version V1.0
20  * 
21  * 
22  *          1、组件注册@Configuration、@Bean给容器中注册组件。
23  * 
24  *          2、组件注册@ComponentScan自动扫描组件、指定扫描规则
25  * 
26  */
27 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
28 @Configuration
29 @Import(value = { Dog.class, Cat.class, DogImportBeanDefinitionRegistrar.class }) // @Import注解,快速给容器中导入一个组件。
30 public class SpringApplicationConfig4 {
31 
32 }

ImportBeanDefinitionRegistrar是一个接口,规定方法registerBeanDefinitions,返回值是空void。通过调用该方法自己给容器中添加组件。

 1 package com.bie.bean;
 2 
 3 import org.springframework.beans.factory.support.BeanDefinitionRegistry;
 4 import org.springframework.beans.factory.support.RootBeanDefinition;
 5 import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
 6 import org.springframework.core.type.AnnotationMetadata;
 7 
 8 /**
 9  * 
10  *
11  * @Title: DogImportBeanDefinitionRegistrar.java
12  * @Package com.bie.bean
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月10日
16  * @version V1.0
17  *
18  */
19 public class DogImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
20 
21     /**
22      * AnnotationMetadata当前类的注解信息。
23      * 
24      * BeanDefinitionRegistry是bean定义的注册类信息。把所有需要添加到容器中的bean。
25      * registry.registerBeanDefinition手工注册。
26      */
27     @Override
28     public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
29         // 判断容器中是否有dog这个bean实例对象
30         boolean dogDefinition = registry.containsBeanDefinition("com.bie.bean.Dog");
31         if (dogDefinition) {
32             // 指定要自定义bean名称的bean类型
33             RootBeanDefinition rootBeanDefinition = new RootBeanDefinition(Cat.class);
34             // 指定bean的名称
35             registry.registerBeanDefinition("cat", rootBeanDefinition);
36         }
37     }
38 
39 }

测试,主类,如下所示: 

 1 package com.bie.main;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 5 
 6 import com.bie.config.SpringApplicationConfig4;
 7 
 8 /**
 9  * 
10  *
11  * @Title: SpringApplication.java
12  * @Package com.bie.main
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月9日
16  * @version V1.0
17  *
18  */
19 public class SpringApplication {
20 
21     public static void main(String[] args) {
22         // 获取到注解配置类
23         ApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig4.class);
24         // 获取到spring容器中定义的bean实例名称。
25         String[] beanDefinitionNames = ac.getBeanDefinitionNames();
26         for (String s : beanDefinitionNames) {
27             System.out.println(s);
28         }
29         System.out.println("===========================================");
30 
31     }
32 
33 }

7.4、第四种方式是,组件注册使用Spring提供的FactoryBean(工厂Bean)注册组件。FactoryBean是一个接口,T getObject();调用该方法返回的的T对象放入到Bean容器中。Class<?> getObjectType();调用该方法,返回对象的类型。boolean isSingleton();调用该方法是否单例模式。默认获取到的是工厂bean调用getObject创建的对象。获取到工厂bean本身,需要给id前面加&符号。

 1 package com.bie.bean;
 2 
 3 import org.springframework.beans.factory.FactoryBean;
 4 
 5 /**
 6  * 
 7  *
 8  * @Title: DogFactoryBean.java
 9  * @Package com.bie.bean
10  * @Description: TODO
11  * @author biehl
12  * @date 2019年12月10日
13  * @version V1.0
14  * 
15  *          创建spring定义的工厂bean
16  */
17 public class DogFactoryBean implements FactoryBean<Dog> {
18 
19     /**
20      * 返回Dog对象,这个对象将会添加到容器中
21      */
22     @Override
23     public Dog getObject() throws Exception {
24         System.out.println("getObject DogFactoryBean.......\n");
25         return new Dog();
26     }
27 
28     /**
29      * 返回对象的类型
30      */
31     @Override
32     public Class<?> getObjectType() {
33         System.out.println("Class<?> DogFactoryBean.......\n");
34         return Dog.class;
35     }
36 
37     /**
38      * 控制是否单例模式
39      */
40     @Override
41     public boolean isSingleton() {
42         System.out.println("isSingleton DogFactoryBean.......\n");
43         // 返回true代表是单实例,在容器中保存一个bean实例,返回false代表是多实例,每次获取都会创建一个新的bean实例
44         return true;
45     }
46 
47 }

将DogFactoryBean工厂bean注入到spring容器中。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 
 6 import com.bie.bean.DogFactoryBean;
 7 
 8 /**
 9  * 
10  *
11  * @Title: SpringApplicationConfig.java
12  * @Package com.bie.config
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月9日
16  * @version V1.0
17  * 
18  * 
19  *          1、组件注册@Configuration、@Bean给容器中注册组件。
20  * 
21  *          2、组件注册@ComponentScan自动扫描组件、指定扫描规则
22  * 
23  */
24 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
25 @Configuration
26 // @Import(value = { Dog.class, Cat.class,
27 // DogImportBeanDefinitionRegistrar.class }) // @Import注解,快速给容器中导入一个组件。
28 public class SpringApplicationConfig4 {
29 
30     /**
31      * 将DogFactoryBean工厂bean注入到spring容器中
32      * 
33      * @return
34      */
35     @Bean
36     public DogFactoryBean dogFactoryBean() {
37         return new DogFactoryBean();
38     }
39 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.ApplicationContext;
 4 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 5 
 6 import com.bie.config.SpringApplicationConfig4;
 7 
 8 /**
 9  * 
10  *
11  * @Title: SpringApplication.java
12  * @Package com.bie.main
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月9日
16  * @version V1.0
17  *
18  */
19 public class SpringApplication {
20 
21     public static void main(String[] args) {
22         // 获取到注解配置类
23         ApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig4.class);
24 
25         // 工厂bean获取到的是调用getObject创建的对象。
26         Object bean = ac.getBean("dogFactoryBean");
27         System.out.println("......." + bean.getClass());
28     }
29 
30 }

8、生命周期@Bean指定初始化和销毁方法。

  bean的生命周期,包含创建、初始化、销毁的过程。bean的生命周期是由spring容器进行管理的。

  可以自定义初始化和销毁的方法。容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。

  调用构造方法,创建对象。如果是单实例,在容器启动的时候创建对象。如果是多实例,在每次获取的时候创建对象。

  单实例,调用初始化方法init-method,是在对象创建完成,并将属性值赋值完毕,开始调用初始化方法。多实例,在每次获取的时候创建对象,然后并将属性值赋值完毕,开始调用初始化方法。

  单实例,调用销毁方法destory-method,在容器关闭的时候,调用销毁的方法。多实例,不调用销毁方法。spring容器不负责对多实例bean的销毁。可以手动调用销毁方法。

 1 package com.bie.bean;
 2 
 3 /**
 4  * 
 5  *
 6  * @Title: Dog.java
 7  * @Package com.bie.bean
 8  * @Description: TODO
 9  * @author biehl
10  * @date 2019年12月10日
11  * @version V1.0
12  *
13  */
14 public class Dog {
15 
16     public Dog() {
17         // 无参构造器,创建对象的时候打印
18         System.out.println("dog constructor......");
19     }
20 
21     public void init() {
22         System.out.println("dog init 初始化方法......");
23     }
24 
25     public void destory() {
26         System.out.println("dog destory 销毁的方法......");
27     }
28 
29 }

8.1)、方式一、指定初始化和销毁方法。在bean.xml配置文件中可以指定init-method、destory-method配置。也可以通过@Bean注解。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 
 6 import com.bie.bean.Dog;
 7 
 8 /**
 9  * 
10  *
11  * @Title: SpringApplicationConfig.java
12  * @Package com.bie.config
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月9日
16  * @version V1.0
17  * 
18  * 
19  *          1、bean的生命周期,包含创建、初始化、销毁的过程。bean的生命周期是由spring容器进行管理的。
20  * 
21  *          2、可以自定义初始化和销毁的方法。容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
22  * 
23  *          3、调用构造方法,创建对象。如果是单实例,在容器启动的时候创建对象。如果是多实例,在每次获取的时候创建对象。
24  * 
25  *          4、单实例,调用初始化方法init-method,是在对象创建完成,并将属性值赋值完毕,开始调用初始化方法。
26  *          多实例,在每次获取的时候创建对象,然后并将属性值赋值完毕,开始调用初始化方法。
27  * 
28  *          5、单实例,调用销毁方法destory-method,在容器关闭的时候,调用销毁的方法。
29  *          多实例,不调用销毁方法。spring容器不负责对多实例bean的销毁。可以手动调用销毁方法。
30  * 
31  *          6、指定初始化和销毁方法的四种方式,如下所示:
32  *          方式一、指定初始化和销毁方法。在bean.xml配置文件中可以指定init-method、destory-method配置。也可以通过@Bean注解。
33  *          方式二、生命周期InitializingBean接口和DisposableBean接口。
34  *             
35  * 
36  * 
37  */
38 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
39 @Configuration
40 public class SpringApplicationConfig5 {
41 
42     @Bean(value = "dog", initMethod = "init", destroyMethod = "destory")
43     public Dog dog() {
44         return new Dog();
45     }
46 
47 }

8.2)、方式二、生命周期InitializingBean接口和DisposableBean接口。通过让Bean实现InitializingBean接口定义初始化逻辑。 通过让Bean实现DisposableBean接口来进行bean实例的销毁。

  InitializingBean接口里面的afterPropertiesSet方法是,创建好对象,并将属性值设置完毕以后,开始调用改方法。相当于初始化方法。
  DisposableBean接口里面的destroy方法是,BeanFactory销毁的时候将单实例的bean销毁。

 1 package com.bie.bean;
 2 
 3 import org.springframework.beans.factory.DisposableBean;
 4 import org.springframework.beans.factory.InitializingBean;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * 
 9  *
10  * @Title: Dog.java
11  * @Package com.bie.bean
12  * @Description: TODO
13  * @author biehl
14  * @date 2019年12月10日
15  * @version V1.0
16  *
17  */
18 @Component
19 public class Dog implements InitializingBean, DisposableBean {
20 
21     public Dog() {
22         // 无参构造器,创建对象的时候打印
23         System.out.println("dog constructor......");
24     }
25 
26     /**
27      * 调用初始化的方法,在bean创建完毕,属性设置完毕以后。
28      */
29     @Override
30     public void afterPropertiesSet() throws Exception {
31         System.out.println("dog afterPropertiesSet 初始化方法......");
32     }
33 
34     /**
35      * 调用销毁的方法,在容器关闭的时候进行调用。
36      */
37     @Override
38     public void destroy() throws Exception {
39         System.out.println("dog destroy 销毁的方法......");
40     }
41 
42 }

生命周期InitializingBean接口和DisposableBean接口。通过让Bean实现InitializingBean接口定义初始化逻辑。 通过让Bean实现DisposableBean接口。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.ComponentScan;
 5 import org.springframework.context.annotation.Configuration;
 6 
 7 import com.bie.bean.Dog;
 8 
 9 /**
10  * 
11  *
12  * @Title: SpringApplicationConfig.java
13  * @Package com.bie.config
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  * 
19  * 
20  *          1、bean的生命周期,包含创建、初始化、销毁的过程。bean的生命周期是由spring容器进行管理的。
21  * 
22  *          2、可以自定义初始化和销毁的方法。容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
23  * 
24  *          3、调用构造方法,创建对象。如果是单实例,在容器启动的时候创建对象。如果是多实例,在每次获取的时候创建对象。
25  * 
26  *          4、单实例,调用初始化方法init-method,是在对象创建完成,并将属性值赋值完毕,开始调用初始化方法。
27  *          多实例,在每次获取的时候创建对象,然后并将属性值赋值完毕,开始调用初始化方法。
28  * 
29  *          5、单实例,调用销毁方法destory-method,在容器关闭的时候,调用销毁的方法。
30  *          多实例,不调用销毁方法。spring容器不负责对多实例bean的销毁。可以手动调用销毁方法。
31  * 
32  *          6、指定初始化和销毁方法的四种方式,如下所示:
33  *          方式一、指定初始化和销毁方法。在bean.xml配置文件中可以指定init-method、destory-method配置。也可以通过@Bean注解。
34  *          方式二、生命周期InitializingBean接口和DisposableBean接口。
35  *          通过让Bean实现InitializingBean接口定义初始化逻辑。 通过让Bean实现DisposableBean接口
36  * 
37  * 
38  */
39 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
40 @Configuration
41 @ComponentScan(basePackages = { "com.bie.bean" })
42 public class SpringApplicationConfig6 {
43 
44     @Bean(value = "dog")
45     public Dog dog() {
46         return new Dog();
47     }
48 
49 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 import com.bie.config.SpringApplicationConfig6;
 6 
 7 /**
 8  * 
 9  *
10  * @Title: SpringApplication.java
11  * @Package com.bie.main
12  * @Description: TODO
13  * @author biehl
14  * @date 2019年12月9日
15  * @version V1.0
16  *
17  */
18 public class SpringApplication {
19 
20     public static void main(String[] args) {
21         // 获取到注解配置类
22         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig6.class);
23         // 调用关闭的时候,调用destory销毁方法。
24         ac.close();
25     }
26 
27 }

8.3)、方式三、生命周期@PostConstruct&@PreDestroy。可以使用JSR250定义规范的注解。

 1 package com.bie.bean;
 2 
 3 import javax.annotation.PostConstruct;
 4 import javax.annotation.PreDestroy;
 5 
 6 import org.springframework.stereotype.Component;
 7 
 8 /**
 9  * 
10  *
11  * @Title: Dog.java
12  * @Package com.bie.bean
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月10日
16  * @version V1.0
17  *
18  */
19 @Component
20 public class Dog {
21 
22     public Dog() {
23         // 无参构造器,创建对象的时候打印
24         System.out.println("dog constructor......");
25     }
26 
27     /**
28      * 调用初始化的方法,在bean创建完毕,属性设置完毕以后。对象创建并赋值之后进行调用。
29      */
30     @PostConstruct
31     public void init() throws Exception {
32         System.out.println("dog init 初始化方法......");
33     }
34 
35     /**
36      * 调用销毁的方法,在容器关闭的时候进行调用。容器移除对象之前调用该方法。
37      */
38     @PreDestroy
39     public void destory() throws Exception {
40         System.out.println("dog destory 销毁的方法......");
41     }
42 
43 }

生命周期@PostConstruct&(在bean实例装配完成,属性值设置完毕以后,进行初始化操作,标注在方法上)、 @PreDestroy(在容器销毁bean之前通知我们进行清理工作)。可以使用JSR250定义规范的注解。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.ComponentScan;
 5 import org.springframework.context.annotation.Configuration;
 6 
 7 import com.bie.bean.Dog;
 8 
 9 /**
10  * 
11  *
12  * @Title: SpringApplicationConfig.java
13  * @Package com.bie.config
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  * 
19  * 
20  *          1、bean的生命周期,包含创建、初始化、销毁的过程。bean的生命周期是由spring容器进行管理的。
21  * 
22  *          2、可以自定义初始化和销毁的方法。容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
23  * 
24  *          3、调用构造方法,创建对象。如果是单实例,在容器启动的时候创建对象。如果是多实例,在每次获取的时候创建对象。
25  * 
26  *          4、单实例,调用初始化方法init-method,是在对象创建完成,并将属性值赋值完毕,开始调用初始化方法。
27  *          多实例,在每次获取的时候创建对象,然后并将属性值赋值完毕,开始调用初始化方法。
28  * 
29  *          5、单实例,调用销毁方法destory-method,在容器关闭的时候,调用销毁的方法。
30  *          多实例,不调用销毁方法。spring容器不负责对多实例bean的销毁。可以手动调用销毁方法。
31  * 
32  *          6、指定初始化和销毁方法的四种方式,如下所示:
33  *          方式一、指定初始化和销毁方法。在bean.xml配置文件中可以指定init-method、destory-method配置。也可以通过@Bean注解。
34  *          方式二、生命周期InitializingBean接口和DisposableBean接口。
35  *          通过让Bean实现InitializingBean接口定义初始化逻辑。 通过让Bean实现DisposableBean接口
36  *          方式三、生命周期@PostConstruct&(在bean实例装配完成,属性值设置完毕以后,进行初始化操作,标注在方法上)、 @PreDestroy(在容器销毁bean之前通知我们进行清理工作)。可以使用JSR250定义规范的注解。
37  * 
38  * 
39  */
40 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
41 @Configuration
42 @ComponentScan(basePackages = { "com.bie.bean" })
43 public class SpringApplicationConfig7 {
44 
45     @Bean(value = "dog")
46     public Dog dog() {
47         return new Dog();
48     }
49 
50 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 import com.bie.config.SpringApplicationConfig7;
 6 
 7 /**
 8  * 
 9  *
10  * @Title: SpringApplication.java
11  * @Package com.bie.main
12  * @Description: TODO
13  * @author biehl
14  * @date 2019年12月9日
15  * @version V1.0
16  *
17  */
18 public class SpringApplication {
19 
20     public static void main(String[] args) {
21         // 获取到注解配置类
22         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig7.class);
23         // 调用关闭的时候,调用destory销毁方法。
24         ac.close();
25     }
26 
27 }

8.4)、方式四、生命周期BeanPostProcessor后置处理器。BeanPostProcessor是一个接口,被称为bean的后置处理器。在bean初始化前后进行处理操作。postProcessBeforeInitialization方法是初始化之前进行后置处理工作,什么时候应用后置处理器,在已经创建bean实例,在bean实例任何初始化调用之前(比如InitializingBean、afterPropertiesSet、或者自定义init-method)进行工作。postProcessAfterInitialization方法是初始化之后进行后置处理工作,什么时候应用后置处理器,在bean后置处理器,这些初始化方法调用之后(比如InitializingBean、afterPropertiesSet、或者自定义init-method)进行工作。

 1 package com.bie.bean;
 2 
 3 import org.springframework.beans.BeansException;
 4 import org.springframework.beans.factory.config.BeanPostProcessor;
 5 import org.springframework.stereotype.Component;
 6 
 7 /**
 8  * 
 9  *
10  * @Title: DogBeanPostProcessor.java
11  * @Package com.bie.bean
12  * @Description: TODO
13  * @author biehl
14  * @date 2019年12月11日
15  * @version V1.0
16  * 
17  *          后置处理器,初始化前后进行处理工作。
18  */
19 @Component // 添加到容器中,将后置处理器加入到容器中
20 public class DogBeanPostProcessor implements BeanPostProcessor {
21 
22     /**
23      * 
24      * @param bean
25      *            创建的bean实例,未被初始化。
26      * @param beanName
27      *            该bean实例在容器中的名称
28      * @return
29      * @throws BeansException
30      */
31     @Override
32     public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
33         System.out.println("postProcessBeforeInitialization......" + beanName + " : " + bean);
34         return bean;
35     }
36 
37     /**
38      * 
39      * @param bean
40      *            创建的bean实例,未被初始化。
41      * @param beanName
42      *            该bean实例在容器中的名称
43      * @return
44      * @throws BeansException
45      */
46     @Override
47     public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
48         System.out.println("postProcessAfterInitialization......" + beanName + " : " + bean);
49         return bean;
50     }
51 
52 }

生命周期BeanPostProcessor后置处理器。BeanPostProcessor是一个接口,被称为bean的后置处理器。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.ComponentScan;
 4 import org.springframework.context.annotation.Configuration;
 5 
 6 /**
 7  * 
 8  *
 9  * @Title: SpringApplicationConfig.java
10  * @Package com.bie.config
11  * @Description: TODO
12  * @author biehl
13  * @date 2019年12月9日
14  * @version V1.0
15  * 
16  * 
17  *          1、bean的生命周期,包含创建、初始化、销毁的过程。bean的生命周期是由spring容器进行管理的。
18  * 
19  *          2、可以自定义初始化和销毁的方法。容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法。
20  * 
21  *          3、调用构造方法,创建对象。如果是单实例,在容器启动的时候创建对象。如果是多实例,在每次获取的时候创建对象。
22  * 
23  *          4、单实例,调用初始化方法init-method,是在对象创建完成,并将属性值赋值完毕,开始调用初始化方法。
24  *          多实例,在每次获取的时候创建对象,然后并将属性值赋值完毕,开始调用初始化方法。
25  * 
26  *          5、单实例,调用销毁方法destory-method,在容器关闭的时候,调用销毁的方法。
27  *          多实例,不调用销毁方法。spring容器不负责对多实例bean的销毁。可以手动调用销毁方法。
28  * 
29  *          6、指定初始化和销毁方法的四种方式,如下所示:
30  *          方式一、指定初始化和销毁方法。在bean.xml配置文件中可以指定init-method、destory-method配置。也可以通过@Bean注解。
31  *          方式二、生命周期InitializingBean接口和DisposableBean接口。
32  *          通过让Bean实现InitializingBean接口定义初始化逻辑。 通过让Bean实现DisposableBean接口
33  *          方式三、生命周期@PostConstruct&(在bean实例装配完成,属性值设置完毕以后,进行初始化操作,标注在方法上)、 @PreDestroy(在容器销毁bean之前通知我们进行清理工作)。可以使用JSR250定义规范的注解。
34  *          方式四、生命周期BeanPostProcessor后置处理器。BeanPostProcessor是一个接口,被称为bean的后置处理器。
35  * 
36  */
37 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
38 @Configuration
39 @ComponentScan(basePackages = { "com.bie.bean" })
40 public class SpringApplicationConfig8 {
41 
42 }
 1 package com.bie.bean;
 2 
 3 import javax.annotation.PostConstruct;
 4 import javax.annotation.PreDestroy;
 5 
 6 import org.springframework.stereotype.Component;
 7 
 8 /**
 9  * 
10  *
11  * @Title: Dog.java
12  * @Package com.bie.bean
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月10日
16  * @version V1.0
17  *
18  */
19 @Component
20 public class Dog {
21 
22     public Dog() {
23         // 无参构造器,创建对象的时候打印
24         System.out.println("dog constructor......");
25     }
26 
27     /**
28      * 调用初始化的方法,在bean创建完毕,属性设置完毕以后。对象创建并赋值之后进行调用。
29      */
30     @PostConstruct
31     public void init() throws Exception {
32         System.out.println("dog init 初始化方法......");
33     }
34 
35     /**
36      * 调用销毁的方法,在容器关闭的时候进行调用。容器移除对象之前调用该方法。
37      */
38     @PreDestroy
39     public void destory() throws Exception {
40         System.out.println("dog destory 销毁的方法......");
41     }
42 
43 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 import com.bie.config.SpringApplicationConfig8;
 6 
 7 /**
 8  * 
 9  *
10  * @Title: SpringApplication.java
11  * @Package com.bie.main
12  * @Description: TODO
13  * @author biehl
14  * @date 2019年12月9日
15  * @version V1.0
16  *
17  */
18 public class SpringApplication {
19 
20     public static void main(String[] args) {
21         // 获取到注解配置类
22         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig8.class);
23         // 调用关闭的时候,调用destory销毁方法。
24         ac.close();
25     }
26 
27 }

总结:BeanPostProcessor.postProcessBeforeInitialization方法初始化之前可以调用。
BeanPostProcessor.postProcessAfterInitialization方法初始化之后可以调用。
初始化方法有三种通过@Bean自定义指定init-method、通过Bean实现InitializingBean接口、通过JSR250的注解@PostConstruct。

9、属性赋值@Value赋值。

 1 package com.bie.po;
 2 
 3 import org.springframework.beans.factory.annotation.Value;
 4 
 5 import lombok.AllArgsConstructor;
 6 import lombok.Data;
 7 import lombok.NoArgsConstructor;
 8 
 9 /**
10  * 
11  *
12  * @Title: Person.java
13  * @Package com.bie.po
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  *
19  */
20 @AllArgsConstructor
21 @NoArgsConstructor
22 @Data
23 public class Person {
24 
25     // 1、使用@Value进行赋值。
26     // 方式一、基本数值赋值。
27     // 方式二、SpEL表达式。
28     // 方式三、使用${}获取到配置文件的值(在运行环境变量中的值)
29 
30     @Value("#{27-2}")
31     private Integer id;
32     @Value(value = "李四四")
33     private String name;
34 
35 }

配置文件类,如下所示:

 1 package com.bie.bean;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 
 6 import com.bie.po.Person;
 7 
 8 /**
 9  * 
10  *
11  * @Title: PersonPropertyValues.java
12  * @Package com.bie.bean
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月11日
16  * @version V1.0
17  *
18  */
19 @Configuration
20 public class PersonPropertyValues {
21 
22     @Bean
23     public Person person() {
24         return new Person(1008611, "张三三");
25     }
26 
27 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 import com.bie.bean.PersonPropertyValues;
 6 import com.bie.po.Person;
 7 
 8 /**
 9  * 
10  *
11  * @Title: SpringApplication.java
12  * @Package com.bie.main
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月9日
16  * @version V1.0
17  *
18  */
19 public class SpringApplication {
20 
21     public static void main(String[] args) {
22         // 获取到注解配置类
23         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PersonPropertyValues.class);
24         Person person = ac.getBean(Person.class);
25         System.out.println(person);
26         // 调用关闭的时候,调用destory销毁方法。
27         ac.close();
28     }
29 
30 }

10、属性赋值@PropertySource加载外部配置文件。

 1 package com.bie.bean;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.Configuration;
 5 import org.springframework.context.annotation.PropertySource;
 6 
 7 import com.bie.po.Student;
 8 
 9 /**
10  * 
11  *
12  * @Title: PersonPropertyValues.java
13  * @Package com.bie.bean
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月11日
17  * @version V1.0
18  * 
19  *          1、属性赋值@PropertySource加载外部配置文件。value可以指定文件路径或者类路径地址。
20  *          使用@PropertySource读取外部配置文件中的key/value对来保存运行的环境变量中。
21  *          加载完外部的配置文件以后使用${}取出配置文件里面的值。
22  * 
23  *          2、可以使用@PropertySources。或者多个@PropertySource注解的形式。
24  */
25 @Configuration
26 @PropertySource(value = { "classpath:/spring.properties" })
27 public class PersonPropertyValues {
28 
29     @Bean
30     public Student student() {
31         return new Student();
32     }
33 
34 }

配置文件spring.properties,如下所示:

1 student.address=北京市西城区什刹海街道西什库大街31号院24号楼

使用${}获取到配置文件*.properties的值(在运行环境变量中的值)。

 1 package com.bie.po;
 2 
 3 import org.springframework.beans.factory.annotation.Value;
 4 
 5 import lombok.AllArgsConstructor;
 6 import lombok.Data;
 7 import lombok.NoArgsConstructor;
 8 
 9 /**
10  * 
11  *
12  * @Title: Person.java
13  * @Package com.bie.po
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  *
19  */
20 @AllArgsConstructor
21 @NoArgsConstructor
22 @Data
23 public class Student {
24 
25     // 1、使用@Value进行赋值。
26     // 方式一、基本数值赋值。
27     // 方式二、SpEL表达式。
28     // 方式三、使用${}获取到配置文件*.properties的值(在运行环境变量中的值)
29 
30     @Value("#{27-2}")
31     private Integer id;
32     @Value(value = "李四四")
33     private String name;
34 
35     @Value("${student.address}")
36     private String address;
37 
38 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 import org.springframework.core.env.ConfigurableEnvironment;
 5 
 6 import com.bie.bean.PersonPropertyValues;
 7 import com.bie.po.Student;
 8 
 9 /**
10  * 
11  *
12  * @Title: SpringApplication.java
13  * @Package com.bie.main
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  *
19  */
20 public class SpringApplication {
21 
22     public static void main(String[] args) {
23         // 获取到注解配置类
24         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(PersonPropertyValues.class);
25         Student student = ac.getBean(Student.class);
26         System.out.println(student);
27 
28         ConfigurableEnvironment environment = ac.getEnvironment();
29         String address = environment.getProperty("student.address");
30         System.out.println(address);
31         // 调用关闭的时候,调用destory销毁方法。
32         ac.close();
33     }
34 
35 }

11、自动装配@Autowired、@Qualifier、@Primary。自动装配,Spring利用依赖注入(DI)完成对IOC容器中各个组件的依赖关系赋值。

 1 package com.bie.config;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.beans.factory.annotation.Qualifier;
 5 import org.springframework.context.annotation.Bean;
 6 import org.springframework.context.annotation.ComponentScan;
 7 import org.springframework.context.annotation.Configuration;
 8 import org.springframework.context.annotation.Primary;
 9 
10 import com.bie.dao.PersonDao;
11 
12 /**
13  * 
14  *
15  * @Title: SpringApplicationConfig.java
16  * @Package com.bie.config
17  * @Description: TODO
18  * @author biehl
19  * @date 2019年12月9日
20  * @version V1.0
21  * 
22  * 
23  *          1、自动装配@Autowired、@Qualifier、@Primary。
24  * 
25  *          2、 自动装配,Spring利用依赖注入(DI)完成对IOC容器中各个组件的依赖关系赋值。
26  * 
27  *          3、自动装配@Autowired。首先使用@Controller、@Service、@Repository注入到spring容器中。
28  *          然后使用@Autowired进行自动装配,实现依赖注入(DI)。完成对IOC容器中各个组件的依赖关系赋值。
29  *          1)、默认优先按照类型去容器中找对应的组件。找到就赋值。
30  *          2)、如果Ioc容器中该类型的组件有多个,如果找到多个类型相同的组件,再将属性的名称作为组件的id去容器中查找。
31  *             3)、@Qualifier(value = "personDao2")可以明确指定自己要装配的id,而不是使用属性名称。
32  *             4)、自动装配@Autowired,默认一定要将属性赋值成功。否则未找到就报异常。@Autowired(required = false)。
33  *             5)、@Primary让spring自动装配的时候默认使用首选的bean。此时也可以使用@Qualifier(value = "personDao")到底使用那个bean实例。    
34  */
35 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
36 @Configuration
37 @ComponentScan({ "com.bie.service", "com.bie.dao", "com.bie.controller" })
38 public class SpringApplicationConfig10 {
39 
40     /**
41      * 再次向spring容器中注入一个bean对象
42      * 
43      * @return
44      */
45     @Primary
46     @Bean(value = "personDao2")
47     public PersonDao personDao() {
48         PersonDao personDao = new PersonDao();
49         personDao.setLabel("2");
50         return personDao;
51     }
52 
53 }

可以结合controller、service、dao进行测试。

 1 package com.bie.controller;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.stereotype.Controller;
 5 
 6 import com.bie.service.PersonService;
 7 
 8 /**
 9  * 
10  *
11  * @Title: PersonController.java
12  * @Package com.bie.controller
13  * @Description: TODO
14  * @author biehl
15  * @date 2019年12月9日
16  * @version V1.0
17  *
18  */
19 @Controller
20 public class PersonController {
21 
22     @Autowired // 自动装配
23     private PersonService personService;
24 
25 }
 1 package com.bie.service;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.beans.factory.annotation.Qualifier;
 5 import org.springframework.stereotype.Service;
 6 
 7 import com.bie.dao.PersonDao;
 8 
 9 /**
10  * 
11  *
12  * @Title: PersonService.java
13  * @Package com.bie.service
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  *
19  */
20 @Service
21 public class PersonService {
22 
23     @Qualifier(value = "personDao")
24     @Autowired(required = false) // 自动装配,required = false表示如果未找到就不找了。
25     private PersonDao personDao2;
26 
27     public void show() {
28         System.out.println(personDao2);
29     }
30 
31     @Override
32     public String toString() {
33         return "PersonService [personDao=" + personDao2 + "]";
34     }
35 
36 }
 1 package com.bie.dao;
 2 
 3 import org.springframework.stereotype.Repository;
 4 
 5 /**
 6  * 
 7  *
 8  * @Title: PersonDao.java
 9  * @Package com.bie.dao
10  * @Description: TODO
11  * @author biehl
12  * @date 2019年12月9日
13  * @version V1.0
14  *
15  */
16 @Repository
17 public class PersonDao {
18 
19     private String label = "1";// 标签。判断是使用了那个名称的PersonDao
20 
21     public String getLabel() {
22         return label;
23     }
24 
25     public void setLabel(String label) {
26         this.label = label;
27     }
28 
29     @Override
30     public String toString() {
31         return "PersonDao [label=" + label + "]";
32     }
33 
34 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 import com.bie.config.SpringApplicationConfig10;
 6 import com.bie.dao.PersonDao;
 7 import com.bie.service.PersonService;
 8 
 9 /**
10  * 
11  *
12  * @Title: SpringApplication.java
13  * @Package com.bie.main
14  * @Description: TODO
15  * @author biehl
16  * @date 2019年12月9日
17  * @version V1.0
18  *
19  */
20 public class SpringApplication {
21 
22     public static void main(String[] args) {
23         // 获取到注解配置类
24         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig10.class);
25         PersonService personService = ac.getBean(PersonService.class);
26         System.out.println(personService);
27 
28 //        PersonDao personDao = ac.getBean(PersonDao.class);
29 //        System.out.println(personDao);
30 
31         // 调用关闭的时候,调用destory销毁方法。
32         ac.close();
33     }
34 
35 }

12、 自动装配@Resource、@Inject。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.Bean;
 4 import org.springframework.context.annotation.ComponentScan;
 5 import org.springframework.context.annotation.Configuration;
 6 import org.springframework.context.annotation.Primary;
 7 
 8 import com.bie.dao.PersonDao;
 9 
10 /**
11  * 
12  *
13  * @Title: SpringApplicationConfig.java
14  * @Package com.bie.config
15  * @Description: TODO
16  * @author biehl
17  * @date 2019年12月9日
18  * @version V1.0
19  * 
20  * 
21  *          1、Spring还支持使用@Resource(JSR250规范)、@Inject(JSR330规范)。是java规范的注解。
22  *          2、@Resource是java规范,和@Autowired一样实现了自动装配功能,但是默认是按照组件名称进行装配的。
23  *          不支持@Primary,也不支持@Autowired(required = false)。
24  *          3、@Inject,需要导入javax.inject的jar包。和@Autowired功能一样。没有required=false。
25  * 
26  */
27 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
28 @Configuration
29 @ComponentScan({ "com.bie.service", "com.bie.dao", "com.bie.controller" })
30 public class SpringApplicationConfig11 {
31 
32     /**
33      * 再次向spring容器中注入一个bean对象
34      * 
35      * @return
36      */
37     @Primary
38     @Bean(value = "personDao2")
39     public PersonDao personDao() {
40         PersonDao personDao = new PersonDao();
41         personDao.setLabel("2");
42         return personDao;
43     }
44 
45 }

将@Resource、@Inject替换@Autowired进行测试。

 1 package com.bie.service;
 2 
 3 import javax.annotation.Resource;
 4 import javax.inject.Inject;
 5 
 6 import org.springframework.stereotype.Service;
 7 
 8 import com.bie.dao.PersonDao;
 9 
10 /**
11  * 
12  *
13  * @Title: PersonService.java
14  * @Package com.bie.service
15  * @Description: TODO
16  * @author biehl
17  * @date 2019年12月9日
18  * @version V1.0
19  *
20  */
21 @Service
22 public class PersonService {
23 
24     // @Qualifier(value = "personDao")
25     // @Autowired(required = false) // 自动装配,required = false表示如果未找到就不找了。
26     //@Resource(name = "personDao2") // 按照名称进行装配.
27     @Inject //
28     private PersonDao personDao2;
29 
30     public void show() {
31         System.out.println(personDao2);
32     }
33 
34     @Override
35     public String toString() {
36         return "PersonService [personDao=" + personDao2 + "]";
37     }
38 
39 }

13、自动装配方法、构造器位置的自动装配。@Autowired可以标注到构造器、方法、参数、属性字段。都是从容器中获取到参数组件的值。

 1 package com.bie.bean;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.stereotype.Component;
 5 
 6 /**
 7  * 
 8  *
 9  * @Title: Boos.java
10  * @Package com.bie.bean
11  * @Description: TODO
12  * @author biehl
13  * @date 2019年12月12日
14  * @version V1.0
15  * 
16  *          默认加在ioc容器中的组件,容器启动会调用无参构造器创建对象,再进行初始化赋值操作。
17  */
18 @Component
19 public class Boos {
20 
21     // 第一种方法,标注到对象上
22     // @Autowired
23     private Car car;
24 
25     public Car getCar() {
26         return car;
27     }
28 
29     // 第二种方法,标注到方法上。spring容器创建当前对象就会调用方法完成赋值。
30     // 方法使用的参数,自定义类型的值从IOC容器中获取。
31     // @Autowired
32     public void setCar(Car car) {
33         this.car = car;
34     }
35 
36     // 第三种方法,标注到构造器上面。spring启动的时候调用该含参构造器。
37     // 构造器要用的组件,也都是从spring容器中获取到的。
38 //    @Autowired
39 //    public Boos(Car car) {
40 //        this.car = car;
41 //        System.out.println("Boss的含参构造器......");
42 //    }
43     
44     // 第四种方法,标注到参数上面,和第三种方法一样。如果组件只有一个有参构造器,这个有参构造器可以省略@Autowired注解的。
45     // 参数位置的组件还是可以自动从容器中获取的。
46 //    public Boos(@Autowired Car car) {
47 //        this.car = car;
48 //        System.out.println("Boss的含参构造器......");
49 //    }
50 
51     @Override
52     public String toString() {
53         return "Boos [car=" + car + "]";
54     }
55 
56 }

@Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。

 1 package com.bie.config;
 2 
 3 import org.springframework.beans.factory.annotation.Autowired;
 4 import org.springframework.context.annotation.Bean;
 5 import org.springframework.context.annotation.ComponentScan;
 6 import org.springframework.context.annotation.Configuration;
 7 
 8 import com.bie.bean.Boos;
 9 import com.bie.bean.Car;
10 
11 /**
12  * 
13  *
14  * @Title: SpringApplicationConfig.java
15  * @Package com.bie.config
16  * @Description: TODO
17  * @author biehl
18  * @date 2019年12月9日
19  * @version V1.0
20  * 
21  * 
22  *          1、@Autowired可以标注到构造器、方法、参数、属性字段。都是从容器中获取到参数组件的值。
23  *          第一种方法, @Autowired可以标注到构造器。
24  *          第二种方法,@Autowired可以标注到方法。标注到方法上。spring容器创建当前对象就会调用方法完成赋值。
25  *          第三种方法, @Autowired可以标注到参数。标注到构造器上面。spring启动的时候调用该含参构造器。
26  *          第四种方法,@Autowired可以标注到属性字段。标注到参数上面,和第三种方法一样。如果组件只有一个有参构造器,这个有参构造器可以省略@Autowired注解的。
27  *          第五种方法,@Autowired可以标注到@Bean注解的参数上面,也可以省略@Autowired。
28  *                  @Bean加方法参数,参数从spring容器中获取到。默认是不写@Autowired,效果是一样的。都可以自动装配。
29  * 
30  */
31 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
32 @Configuration
33 @ComponentScan({ "com.bie.bean" })
34 public class SpringApplicationConfig12 {
35 
36     
37     //第五种方法,@Autowired可以标注到@Bean注解的参数上面,也可以省略@Autowired。
38     @Bean
39     public Boos boos(@Autowired Car car) {
40         Boos boos = new Boos();
41         boos.setCar(car);
42         return boos;
43     }
44 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 import com.bie.bean.Boos;
 6 import com.bie.bean.Car;
 7 import com.bie.config.SpringApplicationConfig12;
 8 import com.bie.service.PersonService;
 9 
10 /**
11  * 
12  *
13  * @Title: SpringApplication.java
14  * @Package com.bie.main
15  * @Description: TODO
16  * @author biehl
17  * @date 2019年12月9日
18  * @version V1.0
19  *
20  */
21 public class SpringApplication {
22 
23     public static void main(String[] args) {
24         // 获取到注解配置类
25         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig12.class);
26         Boos boos = ac.getBean(Boos.class);
27         Car car = ac.getBean(Car.class);
28         System.out.println(boos);
29         System.out.println(car);
30         // 调用关闭的时候,调用destory销毁方法。
31         ac.close();
32     }
33 
34 }

14、自动装配Aware注入Spring底层组件。自定义组件想要使用spring容器底层的一些组件,比如applicationContext、BeanFactory等等。只需要自定义组件实现xxxAware接口即可。在创建对象的时候,会调用接口规定的方法注入相关的组件。可以把Spring底层中的一些组件注入到自定义的bean容器中。 xxxAware的功能是使用xxxAwareProcessor进行处理的,每个xxxAware都有对应的xxxAwareProcessor。

 1 package com.bie.bean;
 2 
 3 import org.springframework.beans.BeansException;
 4 import org.springframework.beans.factory.BeanNameAware;
 5 import org.springframework.context.ApplicationContext;
 6 import org.springframework.context.ApplicationContextAware;
 7 import org.springframework.context.EmbeddedValueResolverAware;
 8 import org.springframework.stereotype.Component;
 9 import org.springframework.util.StringValueResolver;
10 
11 /**
12  * 
13  *
14  * @Title: Red.java
15  * @Package com.bie.bean
16  * @Description: TODO
17  * @author biehl
18  * @date 2019年12月12日
19  * @version V1.0
20  * 
21  *          ApplicationContextAware接口继承了Aware接口。
22  */
23 @Component // 将Red对象添加到ioc容器中
24 public class Red implements ApplicationContextAware, BeanNameAware, EmbeddedValueResolverAware {
25 
26     // ApplicationContext代表了IOC容器
27     private ApplicationContext applicationContext;
28 
29     /**
30      * ApplicationContext代表的是ioc容器
31      */
32     @Override
33     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
34         System.out.println("传入的ioc: " + applicationContext);
35         this.applicationContext = applicationContext;
36     }
37 
38     /**
39      * 设置IOC容器中bean实例的名称
40      */
41     @Override
42     public void setBeanName(String name) {
43         System.out.println("当前bean的名称: " + name);
44     }
45 
46     /**
47      * StringValueResolver是解析String字符串的占位符
48      */
49     @Override
50     public void setEmbeddedValueResolver(StringValueResolver resolver) {
51         String resolveStringValue = resolver.resolveStringValue("您好,${os.name},我是#{1008611}");
52         System.out.println("解析的字符串是 : " + resolveStringValue);
53     }
54 
55 }

@Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。

 1 package com.bie.config;
 2 
 3 import org.springframework.context.annotation.ComponentScan;
 4 import org.springframework.context.annotation.Configuration;
 5 
 6 /**
 7  * 
 8  *
 9  * @Title: SpringApplicationConfig.java
10  * @Package com.bie.config
11  * @Description: TODO
12  * @author biehl
13  * @date 2019年12月9日
14  * @version V1.0
15  * 
16  * 
17  *          1、自定义组件想要使用spring容器底层的一些组件,比如applicationContext、BeanFactory等等。
18  *          只需要自定义组件实现xxxAware接口即可。在创建对象的时候,会调用接口规定的方法注入相关的组件。
19  *          可以把Spring底层中的一些组件注入到自定义的bean容器中。 
20  *          2、xxxAware的功能是使用xxxAwareProcessor进行处理的,每个xxxAware都有对应的xxxAwareProcessor。
21  * 
22  */
23 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
24 @Configuration
25 @ComponentScan({ "com.bie.bean" })
26 public class SpringApplicationConfig13 {
27 
28 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 import com.bie.config.SpringApplicationConfig13;
 6 
 7 /**
 8  * 
 9  *
10  * @Title: SpringApplication.java
11  * @Package com.bie.main
12  * @Description: TODO
13  * @author biehl
14  * @date 2019年12月9日
15  * @version V1.0
16  *
17  */
18 public class SpringApplication {
19 
20     public static void main(String[] args) {
21         // 获取到注解配置类
22         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringApplicationConfig13.class);
23 
24         // 调用关闭的时候,调用destory销毁方法。
25         ac.close();
26     }
27 
28 }

15、自动装配@Profile环境搭建,自动装配@Profile根据环境注册bean。

  1 package com.bie.config;
  2 
  3 import java.beans.PropertyVetoException;
  4 
  5 import javax.sql.DataSource;
  6 
  7 import org.springframework.beans.factory.annotation.Value;
  8 import org.springframework.context.EmbeddedValueResolverAware;
  9 import org.springframework.context.annotation.Bean;
 10 import org.springframework.context.annotation.Configuration;
 11 import org.springframework.context.annotation.Profile;
 12 import org.springframework.context.annotation.PropertySource;
 13 import org.springframework.util.StringValueResolver;
 14 
 15 import com.mchange.v2.c3p0.ComboPooledDataSource;
 16 
 17 /**
 18  * 
 19  *
 20  * @Title: SpringApplicationConfig.java
 21  * @Package com.bie.config
 22  * @Description: TODO
 23  * @author biehl
 24  * @date 2019年12月9日
 25  * @version V1.0
 26  * 
 27  * 
 28  *          1、@Profile注解。spring提供了可以根据当前环境动态的激活和切换一系列bean组件的功能。
 29  * 
 30  *          2、@Profile做标识,当前环境被激活了才会被注册到spring容器中。
 31  *          指定组件在那个环境的情况下才会被注册到容器中。不指定,任何环境下都能注册这个组件。
 32  * 
 33  *          3、添加了环境标识的bean,只有这个环境被激活以后的时候才能注册到容器中。可以使用default默认的。默认是default环境。
 34  *             
 35  *             4、切换环境的几种方式。
 36  *                 方式一、-Dspring.profiles.active=test。使用命令行动态参数,在虚拟机参数位置加载。
 37  *                 方式二、使用代码的方式激活是那种环境。啊,真没有springboot好使方便哦。
 38  *                 方式三、@Profile(value = "dev")标注到类上,只有是指定的环境的时候,整个配置类里面的所有配置才能生效。
 39  *                 注意:注入到容器中的bean,没有标注环境标识的bean,在任何环境下都是加载的。
 40  */
 41 // @Configuration告诉Spring这是一个配置类,相当于bean.xml配置文件。
 42 @Profile(value = "test")
 43 @Configuration
 44 @PropertySource(value = {"classpath:/jdbc.properties"})
 45 public class SpringApplicationConfig14 implements EmbeddedValueResolverAware {
 46 
 47     // 值解析器
 48     private StringValueResolver valueResolver;
 49 
 50     private String jdbcUrl;
 51     private String driverClass; // 使用值解析器进行解析
 52     @Value(value = "${jdbc.username}")
 53     private String user;
 54 
 55     /**
 56      * 开发环境
 57      * 
 58      * @return
 59      */
 60     @Bean(value = "DataSourceDev")
 61     @Profile(value = "dev")
 62     public DataSource dataSourceDev(@Value(value = "jdbc.password") String password) {
 63         ComboPooledDataSource dataSource = new ComboPooledDataSource();
 64         try {
 65             dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/dev");
 66             dataSource.setDriverClass(driverClass);
 67             dataSource.setUser(user);
 68             dataSource.setPassword(password);
 69         } catch (PropertyVetoException e) {
 70             e.printStackTrace();
 71         }
 72         return dataSource;
 73     }
 74 
 75     /**
 76      * 生产环境
 77      * 
 78      * @return
 79      */
 80     @Bean(value = "DataSourceProd")
 81     @Profile(value = "prod")
 82     public DataSource dataSourceProd(@Value(value = "jdbc.password") String password) {
 83         ComboPooledDataSource dataSource = new ComboPooledDataSource();
 84         try {
 85             dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/prod");
 86             dataSource.setDriverClass(driverClass);
 87             dataSource.setUser(user);
 88             dataSource.setPassword(password);
 89         } catch (PropertyVetoException e) {
 90             e.printStackTrace();
 91         }
 92         return dataSource;
 93     }
 94 
 95     /**
 96      * 测试环境
 97      * 
 98      * @return
 99      */
100     @Bean(value = "DataSourceTest")
101     @Profile(value = "test")
102     // @Profile(value = "default")
103     public DataSource dataSourceTest(@Value(value = "jdbc.password") String password) {
104         ComboPooledDataSource dataSource = new ComboPooledDataSource();
105         try {
106             dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
107             dataSource.setDriverClass(driverClass);
108             dataSource.setUser(user);
109             dataSource.setPassword(password);
110         } catch (PropertyVetoException e) {
111             e.printStackTrace();
112         }
113         return dataSource;
114     }
115 
116     /**
117      * 值解析器
118      */
119     @Override
120     public void setEmbeddedValueResolver(StringValueResolver resolver) {
121         this.valueResolver = resolver;
122         driverClass = resolver.resolveStringValue("${jdbc.driver}");
123     }
124 }

测试,主类,如下所示:

 1 package com.bie.main;
 2 
 3 import org.springframework.context.annotation.AnnotationConfigApplicationContext;
 4 
 5 import com.bie.config.SpringApplicationConfig14;
 6 
 7 /**
 8  * 
 9  *
10  * @Title: SpringApplication.java
11  * @Package com.bie.main
12  * @Description: TODO
13  * @author biehl
14  * @date 2019年12月9日
15  * @version V1.0
16  *
17  */
18 public class SpringApplication {
19 
20     public static void main(String[] args) {
21         // 获取到注解配置类
22         AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
23         // 1、第一步,创建好ApplicationContext对象。
24         // 2、第二步,设置需要激活的对象。
25         ac.getEnvironment().setActiveProfiles("test");
26         // 3、第三步,注册配置类
27         ac.register(SpringApplicationConfig14.class);
28         // 4、第四步,启动刷新容器。
29         ac.refresh();
30 
31         String[] beanDefinitionNames = ac.getBeanDefinitionNames();
32         for (String s : beanDefinitionNames) {
33             System.out.println(s);
34         }
35         // 调用关闭的时候,调用destory销毁方法。
36         ac.close();
37     }
38 
39 }

作者:别先生

博客园:https://www.cnblogs.com/biehongli/

如果您想及时得到个人撰写文章以及著作的消息推送,可以扫描上方二维码,关注个人公众号哦。


原文地址:https://www.cnblogs.com/biehongli/p/12011378.html