IoC
Inversion of Control:控制反转,就是将对象的创建权反转交给spring
IoC的好处
传统方式的程序编写,底层的实现切换了,需要修改源代码
使用spring之后,实现类都交给IoC容器中的BeanFactory来管理,通过工厂+反射+配置文件来实现程序的解耦合
<bean id="user" class="com.qf.demo.User"> class BeanFactory{ public static Object getBean(String id) {//id:bean标签的id Class clazz = Class.forName(className);//className:bean标签的class return clazz.newInstance(); } }
IoC和DI
<bean id="user" class="com.qf.demo.User"> <property name="id" value="1"/> <property name="name" value="qf"/> <property name="age" value="18"/> </bean>IoC:控制反转,就是将对象的创建权反转给spring
DI:依赖注入,前提必须有IoC的环境,然后Spring管理这个类的时候把这个类依赖的属性注入进来
描述:Class A中用到了Class B的对象b,一般情况下,需要在A的代码中显式的new一个B的对象。采用依赖注入技术之后,A的代码只需要定义一个私有的B对象,不需要直接new来获得这个对象,而是通过相关的容器控制程序来将B对象在外部new出来并注入到A类里的引用中。而具体获取的方法、对象被获取时的状态由配置文件(如XML)来指定
Spring的工厂类
- ApplicationContext是新版本spring的工厂类、BeanFactory是老版本spring的工厂类
- ApplicationContext继承了BeanFactory接口
- BeanFactory在调用getBean方法时才会生成类的实例;ApplicationContext在加载配置文件时就会生成类的实例
- ApplicationContext接口有两个实现类
- ClassPathXmlApplicationContext:加载类路径下的配置文件
- FileSystemXmlApplicationContext :加载文件系统下的配置文件
配置spring
applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.qf.demo.User"> <property name="id" value="1"/> <property name="name" value="qf"/> <property name="age" value="18"/> </bean> </beans>
bean配置
bean标签
- 标识
- id:使用了唯一约束;不能使用特殊字符
- name:未使用唯一约束;可以使用特殊字符,例如 /user
- 生命周期
- init-method:bean被初始化时执行的方法
- destroy-method:bean被销毁时执行的方法(bean必须是单例创建的才可以进行工厂关闭,多例的情况下无法工厂关闭)
- 测试,User类中定义两个方法init和destroy
1 package com.qf.demo; 2 3 public class User { 4 5 private Long id; 6 private String name; 7 private Integer age; 8 9 public void setId(Long id) { 10 this.id = id; 11 } 12 public void setName(String name) { 13 this.name = name; 14 } 15 public void setAge(Integer age) { 16 this.age = age; 17 } 18 19 @Override 20 public String toString() { 21 return "User [id=" + id + ", name=" + name + ", age=" + age + "]"; 22 } 23 24 public User(Long id, String name, Integer age) { 25 super(); 26 this.id = id; 27 this.name = name; 28 this.age = age; 29 } 30 public User() { 31 super(); 32 } 33 34 public void init() { 35 System.out.println("初始化----------"); 36 } 37 public void destroy() { 38 System.out.println("销毁----------"); 39 } 40 }
applicationContext.xml中配置spring管理User对象时配置init属性和destroy属性
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <bean id="user" class="com.qf.demo.User" init-method="init" destroy-method="destroy"> <property name="id" value="1"/> <property name="name" value="qf"/> <property name="age" value="18"/> </bean> </beans>
测试类
public class TestDemo { @Test public void test() { // ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); // ApplicationContext类里没有close方法 ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 = (User) context.getBean("user"); System.out.println(user1); // User user2 = (User) context.getBean("user"); // System.out.println(user2); context.close(); } }
console输出结果
初始化---------- User [id=1, name=qf, age=18] 销毁----------
注:如果bean中配置scope="prototype",测试会发现destroy不执行,即工厂无法close
- 作用域
- scope:bean的作用域属性
- singleton:默认的,spring采用单例模式创建对象
- prototype:spring采用多例模式创建对象
- request:在web项目中使用,spring创建完这个类对象后,将这个对象存入到request中
- session:在web项目中使用,spring创建完这个类对象后,将这个对象存入到session中
- globalSession:在web项目中使用,在porlet环境下,spring创建完这个类对象后,这个对象在其子系统中可以使用;没有porlet环境,相当于session
- scope:bean的作用域属性
-
- 测试1
- 修改applicationContext.xml的bean配置,配置scope属性
<bean id="user" class="com.qf.demo.User" scope="prototype">
- 测试方法
@Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); User user1 = (User) context.getBean("user"); User user2 = (User) context.getBean("user"); System.out.println(user2 == user1); }
- console输出结果
false
- 结论:采用多例模式创建对象,两次调用getBean方法创建了两个不同的对象
- 修改applicationContext.xml的bean配置,配置scope属性
- 测试2
- 在测试1的基础上修改scope属性值为singleton
- console输出结果
true
- 结论:采用单例模式创建对象,两次调用getBean方法创建了两个相同的对象
- 测试1
Spring的bean管理方式
xml方式
注解方式
XML方式管理Bean
spring的bean的实例化
- 无参构造方式实例化bean
- 自定义bean
public class TestBean { public TestBean() { System.out.println("无参构造方式实例化完成"); } }
- 配置bean
<bean id="test" class="com.qf.demo.TestBean"></bean>
- 测试方法
@Test public void test() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); TestBean test = (TestBean) context.getBean("test"); System.out.println(test); }
- console输出
无参构造方式实例化完成 com.qf.demo.TestBean@635c714a
- 自定义bean
- 静态工厂方式实例化bean
- 创建静态工厂类
package com.qf.demo; public class TestBeanFactory { public static Bean getBean() { System.out.println("静态工厂实例化完成"); return new Bean(); } } class Bean{ }
- 配置bean
<bean id="test" class="com.qf.demo.TestBeanFactory" factory-method="getBean"></bean>
- 创建静态工厂类
- 实例工厂方式实例化bean
- 创建实例工厂类
package com.qf.demo; public class BeanInstance { public Bean getInstance() { System.out.println("实例工厂方式实例化bean完成"); return new Bean(); } }
- 配置bean
<bean id="instance" class="com.qf.demo.BeanInstance"/> <bean id="test" factory-bean="instance" factory-method="getInstance"/>
- 创建实例工厂类
属性注入
- 构造方法
- set方法
- p名称空间
- SpEL注入