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 }