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初始化前后进行处理操作。
a)、postProcessBeforeInitialization方法是初始化之前进行后置处理工作,什么时候应用后置处理器,在已经创建bean实例,在bean实例任何初始化调用之前(比如InitializingBean、afterPropertiesSet、或者自定义init-method)进行工作。初始化即对象创建完成,并赋值好,调用初始化方法。BeanPostProcessor.postProcessBeforeInitialization();
b)、postProcessAfterInitialization方法是初始化之后进行后置处理工作,什么时候应用后置处理器,在bean后置处理器,这些初始化方法调用之后(比如InitializingBean、afterPropertiesSet、或者自定义init-method)进行工作。销毁即,单实例是容器关闭的时候,多实例是容器不会管理这个bean,容器不会调用销毁方法。BeanPostProcessor.postProcessAfterInitialization();
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/
如果您想及时得到个人撰写文章以及著作的消息推送,可以扫描上方二维码,关注个人公众号哦。