一 IOC 容器

1.1 Bean注册

给容器中注入组件的几种方式

1.1.1 使用包扫描+组件注解

  1. 开启包扫描 @ComponentScan/@ComponentScans
  2. 使用组件注解:@Component/@Service/@Repository/@Controller

1.1.2 使用@Bean注解

方便用于导入第三方包内组件

1.1.3 使用@Import

方式一:直接注入类

方式二:使用ImportSelector

方式三:使用ImportBeanDefinitionRigistrar

1.1.4 实现Spring的FactoryBean接口

1.2 Bean生命周期

bean的生命周期:

bean创建—-初始化——销毁的过程 容器管理bean的生命周期; 我们可以自定义初始化和销毁方法;容器在bean进行到当前生命周期的时候来调用我们自定义的初始化和销毁方法

构造(对象创建) 单实例:在容器启动的时候创建对象 多实例:在每次获取的时候创建对象

1.2.1 指定初始化和销毁方法;

通过@Bean指定init-method和destroy-method;

Dog.class:

  1. package com.haan.springdemo.annotation;
  2. /**
  3. * @author hanliukui
  4. * @Date 2021/4/14 20:25
  5. */
  6. public class Dog {
  7. private String name;
  8. public String getName() {
  9. return name;
  10. }
  11. public void setName(String name) {
  12. this.name = name;
  13. }
  14. public Dog() {
  15. System.out.println("dog constructor ...");
  16. }
  17. public void init(){
  18. System.out.println("dog init ...");
  19. }
  20. public void destroy(){
  21. System.out.println("dog destroy ...");
  22. }
  23. }
  1. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. /**
  5. * @author hanliukui
  6. * @Date 2021/4/14 20:25
  7. */
  8. @Configuration
  9. public class MyApplication {
  10. /**
  11. * initMethod:指定Bean初始化方法
  12. * destroyMethod:指定Bean销毁时执行方法
  13. * @return
  14. */
  15. @Bean(value = "dog",initMethod = "init",destroyMethod = "destroy")
  16. public Dog dog(){
  17. return new Dog();
  18. }
  19. public static void main(String[] args) {
  20. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyApplication.class);
  21. System.out.println("初始化容器结束...");
  22. Dog dog = context.getBean(Dog.class);
  23. System.out.println("移除Bean dog...");
  24. context.removeBeanDefinition("dog");
  25. System.out.println("移除Bean dog 后...");
  26. context.close();
  27. System.out.println("关闭容器...");
  28. }
  29. }

控制台打印:

  1. dog constructor ...
  2. dog init ...
  3. 初始化容器结束...
  4. 移除Bean dog...
  5. dog destroy ...
  6. 移除Bean dog 后...
  7. 关闭容器...

1.2.2 实现InitializingBean/DisposableBean

  1. dog constructor ...
  2. dog init ...
  3. cat constructor ...
  4. InitializingBean afterPropertiesSet...
  5. 初始化容器结束...
  6. 移除Bean dog...
  7. dog destroy ...
  8. 移除Bean dog 后...
  9. 移除Bean cat...
  10. DisposableBean destroy...
  11. 移除Bean cat 后...
  12. 关闭容器...
  13. 关闭容器后...

1.2.3 可以使用JSR250

@PostConstruct:在bean创建完成并且属性赋值完成;来执行初始化方法

@PreDestroy:在容器销毁bean之前通知我们进行清理工作

1.2.4 BeanPostProcessor【interface】:bean的后置处理器;

在bean初始化前后进行一些处理工作;

postProcessBeforeInitialization:在初始化之前工作

postProcessAfterInitialization:在初始化之后工作

1.3 属性赋值

首先我们创建一个类Person,在容器中注入Person有参构造和无参构造两个Bean,打印进行查看:
(1)Person.class

  1. public class Person {
  2. private String name;
  3. private Integer age;
  4. private String mobile;
  5. // 无参构造函数
  6. public Person(){
  7. }
  8. // 有参构造函数
  9. public Person(String name,Integer age){
  10. this.name = name;
  11. this.age = age;
  12. }
  13. public String getName() {
  14. return name;
  15. }
  16. public void setName(String name) {
  17. this.name = name;
  18. }
  19. public Integer getAge() {
  20. return age;
  21. }
  22. public void setAge(Integer age) {
  23. this.age = age;
  24. }
  25. public String getMobile() {
  26. return mobile;
  27. }
  28. public void setMobile(String mobile) {
  29. this.mobile = mobile;
  30. }
  31. @Override
  32. public String toString() {
  33. return "Person{" +
  34. "name='" + name + '\'' +
  35. ", age=" + age +
  36. ", mobile='" + mobile + '\'' +
  37. '}';
  38. }
  39. }

(2)MyApplication.class

  1. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.context.annotation.Configuration;
  4. @Configuration
  5. public class MyApplication {
  6. @Bean
  7. public Person person1(){
  8. return new Person();
  9. }
  10. @Bean
  11. public Person person2(){
  12. return new Person("李白",112);
  13. }
  14. public static void main(String[] args) {
  15. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyApplication.class);
  16. System.out.println("=======================");
  17. Person person1 = (Person) applicationContext.getBean("person1");
  18. System.out.println(person1);
  19. Person person2 = (Person) applicationContext.getBean("person2");
  20. System.out.println(person2);
  21. }
  22. }

(3)输出结果

  1. =======================
  2. Person{name='null', age=null, mobile='null'}
  3. Person{name='李白', age=112, mobile='null'}
  4. Process finished with exit code 0

在Spring中,我们可以使用XML配置,进行bean的属性赋值,同样基于注解,也有相对应的注解@Value

1.3.1 使用@Value赋值

  1. 使用基本数值
  2. 可以使用SPEL: #{}
  3. 可以使用${} :取出环境配置文件的值(环境变量中的值)

传统的方法是通过XML配置每一个Bean,并对这个Bean的所有Field进行声明式配置。

  1. package com.haan.springdemo.annotation.propertiesassigning;
  2. import org.springframework.beans.factory.annotation.Value;
  3. public class Person {
  4. @Value(value = "张飞")
  5. private String name;
  6. @Value(value = "#{11+22}")
  7. private Integer age;
  8. @Value(value = "${person.mobile}")
  9. private String mobile;
  10. // 无参构造函数
  11. public Person(){
  12. }
  13. // 有参构造函数
  14. public Person(String name,Integer age){
  15. this.name = name;
  16. this.age = age;
  17. }
  18. public String getName() {
  19. return name;
  20. }
  21. public void setName(String name) {
  22. this.name = name;
  23. }
  24. public Integer getAge() {
  25. return age;
  26. }
  27. public void setAge(Integer age) {
  28. this.age = age;
  29. }
  30. public String getMobile() {
  31. return mobile;
  32. }
  33. public void setMobile(String mobile) {
  34. this.mobile = mobile;
  35. }
  36. @Override
  37. public String toString() {
  38. return "Person{" +
  39. "name='" + name + '\'' +
  40. ", age=" + age +
  41. ", mobile='" + mobile + '\'' +
  42. '}';
  43. }
  44. }

配置文件:resource/person.properties

  1. person.name=zhaoyun
  2. person.age= 220
  3. person.mobile=10010

MyApplication.class

  1. package com.haan.springdemo.annotation.propertiesassigning;
  2. import org.springframework.context.annotation.AnnotationConfigApplicationContext;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.context.annotation.PropertySource;
  6. import org.springframework.core.env.ConfigurableEnvironment;
  7. import java.util.Map;
  8. @Configuration
  9. @PropertySource(value = {"classpath:/person.properties"})
  10. public class MyApplication {
  11. @Bean
  12. public Person person1(){
  13. return new Person();
  14. }
  15. @Bean
  16. public Person person2(){
  17. return new Person("李白",112);
  18. }
  19. public static void main(String[] args) {
  20. AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyApplication.class);
  21. System.out.println("=======================");
  22. Person person1 = (Person) applicationContext.getBean("person1");
  23. System.out.println(person1);
  24. Person person2 = (Person) applicationContext.getBean("person2");
  25. System.out.println(person2);
  26. // 获取环境变量中配置文件中的key/value
  27. System.out.println("读取配置文件导入的环境变量key/value=======");
  28. ConfigurableEnvironment environment = applicationContext.getEnvironment();
  29. String personName = environment.getProperty("person.name");
  30. System.out.println(personName);
  31. String personAge = environment.getProperty("person.age");
  32. System.out.println(personAge);
  33. String personMobile = environment.getProperty("person.mobile");
  34. System.out.println(personMobile);
  35. }
  36. }

输出结果:

  1. =======================
  2. Person{name='张飞', age=33, mobile='10010'}
  3. Person{name='张飞', age=33, mobile='10010'}
  4. 读取配置文件导入的环境变量key/value=======
  5. zhaoyun
  6. 220
  7. 10010
  8. Process finished with exit code 0
  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:context="http://www.springframework.org/schema/context"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
  6. <context:property-placeholder location="classpath:person.properties"/>
  7. <bean id="person" class="com.haan.springdemo.annotation.propertiesassigning.Person">
  8. <property name="name" value="张飞"/>
  9. <property name="age" value="#{11+22}"/>
  10. <property name="mobile" value="${person.mobile}"/>
  11. </bean>
  12. </beans>

1.4 自动装配

Spring 利用依赖注入,完成对IOC容器中各个组件的依赖关系赋值。

1.4.1 @AutoWired 自动注入

1)、默认优先按照类型去容器中找对应的组件:applicationContext.getBean(BookDao.class);找到就赋值
2)、如果找到多个相同类型的组件,再将属性的名称作为组件的id去容器中查找
applicationContext.getBean(“bookDao”)
3)、@Qualifier(“bookDao”):使用@Qualifier指定需要装配的组件的id,而不是使用属性名
4)、自动装配默认一定要将属性赋值好,没有就会报错;
可以使用@Autowired(required=false);
5)、@Primary:让Spring进行自动装配的时候,默认使用首选的bean;
也可以继续使用@Qualifier指定需要装配的bean的名字
BookService{
@Autowired
BookDao bookDao;
}

1.4.2 其他方式

Spring还支持使用@Resource(JSR250)和@Inject(JSR330)[java规范的注解]
@Resource:
可以和@Autowired一样实现自动装配功能;默认是按照组件名称进行装配的;
没有能支持@Primary功能没有支持@Autowired(reqiured=false);
@Inject:
需要导入javax.inject的包,和Autowired的功能一样。没有required=false的功能;

@Autowired:Spring定义的; @Resource、@Inject都是java规范

AutowiredAnnotationBeanPostProcessor:解析完成自动装配功能;

构造器、参数、方法、属性都可以使用AutoWired