一 IOC 容器
1.1 Bean注册
1.1.1 使用包扫描+组件注解
- 开启包扫描 @ComponentScan/@ComponentScans
- 使用组件注解:@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:
package com.haan.springdemo.annotation;/*** @author hanliukui* @Date 2021/4/14 20:25*/public class Dog {private String name;public String getName() {return name;}public void setName(String name) {this.name = name;}public Dog() {System.out.println("dog constructor ...");}public void init(){System.out.println("dog init ...");}public void destroy(){System.out.println("dog destroy ...");}}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;/*** @author hanliukui* @Date 2021/4/14 20:25*/@Configurationpublic class MyApplication {/*** initMethod:指定Bean初始化方法* destroyMethod:指定Bean销毁时执行方法* @return*/@Bean(value = "dog",initMethod = "init",destroyMethod = "destroy")public Dog dog(){return new Dog();}public static void main(String[] args) {AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyApplication.class);System.out.println("初始化容器结束...");Dog dog = context.getBean(Dog.class);System.out.println("移除Bean dog...");context.removeBeanDefinition("dog");System.out.println("移除Bean dog 后...");context.close();System.out.println("关闭容器...");}}
控制台打印:
dog constructor ...dog init ...初始化容器结束...移除Bean dog...dog destroy ...移除Bean dog 后...关闭容器...
1.2.2 实现InitializingBean/DisposableBean
dog constructor ...dog init ...cat constructor ...InitializingBean afterPropertiesSet...初始化容器结束...移除Bean dog...dog destroy ...移除Bean dog 后...移除Bean cat...DisposableBean destroy...移除Bean cat 后...关闭容器...关闭容器后...
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
public class Person {private String name;private Integer age;private String mobile;// 无参构造函数public Person(){}// 有参构造函数public Person(String name,Integer age){this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = mobile;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", mobile='" + mobile + '\'' +'}';}}
(2)MyApplication.class
import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configurationpublic class MyApplication {@Beanpublic Person person1(){return new Person();}@Beanpublic Person person2(){return new Person("李白",112);}public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyApplication.class);System.out.println("=======================");Person person1 = (Person) applicationContext.getBean("person1");System.out.println(person1);Person person2 = (Person) applicationContext.getBean("person2");System.out.println(person2);}}
(3)输出结果
=======================Person{name='null', age=null, mobile='null'}Person{name='李白', age=112, mobile='null'}Process finished with exit code 0
在Spring中,我们可以使用XML配置,进行bean的属性赋值,同样基于注解,也有相对应的注解@Value。
1.3.1 使用@Value赋值
- 使用基本数值
- 可以使用SPEL:
#{} - 可以使用
${}:取出环境配置文件的值(环境变量中的值)
传统的方法是通过XML配置每一个Bean,并对这个Bean的所有Field进行声明式配置。
package com.haan.springdemo.annotation.propertiesassigning;import org.springframework.beans.factory.annotation.Value;public class Person {@Value(value = "张飞")private String name;@Value(value = "#{11+22}")private Integer age;@Value(value = "${person.mobile}")private String mobile;// 无参构造函数public Person(){}// 有参构造函数public Person(String name,Integer age){this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}public String getMobile() {return mobile;}public void setMobile(String mobile) {this.mobile = mobile;}@Overridepublic String toString() {return "Person{" +"name='" + name + '\'' +", age=" + age +", mobile='" + mobile + '\'' +'}';}}
配置文件:resource/person.properties
person.name=zhaoyunperson.age= 220person.mobile=10010
MyApplication.class
package com.haan.springdemo.annotation.propertiesassigning;import org.springframework.context.annotation.AnnotationConfigApplicationContext;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.PropertySource;import org.springframework.core.env.ConfigurableEnvironment;import java.util.Map;@Configuration@PropertySource(value = {"classpath:/person.properties"})public class MyApplication {@Beanpublic Person person1(){return new Person();}@Beanpublic Person person2(){return new Person("李白",112);}public static void main(String[] args) {AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyApplication.class);System.out.println("=======================");Person person1 = (Person) applicationContext.getBean("person1");System.out.println(person1);Person person2 = (Person) applicationContext.getBean("person2");System.out.println(person2);// 获取环境变量中配置文件中的key/valueSystem.out.println("读取配置文件导入的环境变量key/value=======");ConfigurableEnvironment environment = applicationContext.getEnvironment();String personName = environment.getProperty("person.name");System.out.println(personName);String personAge = environment.getProperty("person.age");System.out.println(personAge);String personMobile = environment.getProperty("person.mobile");System.out.println(personMobile);}}
输出结果:
=======================Person{name='张飞', age=33, mobile='10010'}Person{name='张飞', age=33, mobile='10010'}读取配置文件导入的环境变量key/value=======zhaoyun22010010Process finished with exit code 0
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"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"><context:property-placeholder location="classpath:person.properties"/><bean id="person" class="com.haan.springdemo.annotation.propertiesassigning.Person"><property name="name" value="张飞"/><property name="age" value="#{11+22}"/><property name="mobile" value="${person.mobile}"/></bean></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:解析完成自动装配功能;
