一、思想
IOC:Inverse Of Control 反转控制
将我们创建对象的方式反转了,之前对象的创建由开发人员自己维护。包括依赖关系也是自己注入。使用了Spring 框架之后,对象的创建以及依赖关系也是自己。反转控制就是反转了对象的方式。从我们自己创建反转给了spring。
DI: Dependency Injection 依赖注入
实现 IOC 思想需要 DI 做支持。那么spring是如何通过 IOC 和 DI 创建对象和管理依赖关系呢?
注入方式:
- set 方法注入
- 构造方法注入
- 字段注入
注入类型:
- 值类型注入
- 引用类型注入 将依赖对象注入
二、spring中的工厂
1、ApplicationContext:
特点:每次容器启动时就会创建容器中配置的所有给对象,并提供更多的功能
我们创建容器时,通常是用实现ApplicationContext 接口的实现类 ClassPathXmlApplication对象,读取放到src 文件夹的xml文件。
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
2、BeanFactory(过时)
特点:
1、spring 原始接口,针对原始接口的实现类功能较为单一
2、BeanFactory接口实现类的容器.特点是每次在获得对象时才会创建对象
三、spring 配置详解
在上一篇文章中,简单进行了bean 对象的配置,此处我们详细配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd ">
<!-- 将User交给spring 容器 管理 -->
<bean name="user" class="com.test.bean.User" init-method="init" destroy-method="destroy" scope="singleton">
<property name="name" value="张三"/>
<property name="age" value="45"/>
</bean>
</beans>
- bean元素:使用该元素描述需要spring容器管理的对象
- class属性:被管理对象的完整类名
- name属性:给被管理的对象起个名字。获得对象时根据该名称获得对象。可以重复,可以使用特殊字符。
- id 属性: 与name 属性一样,但是名称不能重复,不能有特殊字符。
- scope属性:Bean 的作用范围。singleton:单例的。prototype:多例的。
- init-method属性:初始化方法。
- destroy-method属性:销毁方法。工厂关闭时会执行销毁的方法
四、Spring 的 Bean 的管理 XML 的方式
Spring 创建对象的方式
1、空参构造方式
<bean name="user" class="com.test.bean.User">
<property name="name" value="张三"/>
<property name="age" value="45"/>
</bean>
注意:需要该类提供空参的构造方法
2、静态工厂(了解)
public class UserBeanFactory {
public static User getUser() {
System.out.println("静态工厂创建对象");
return new User();
}
}
<!--2. 静态工厂创建对象 -->
<bean name="userBean" class="com.test.b_create.UserBeanFactory" factory-method="getUser">
</bean>
3、实例工厂(了解)
public class UserBeanFactory {
public User getUser2() {
System.out.println("实例工厂创建对象");
return new User();
}
}
<!--3. 实例化工厂创建对象 -->
<bean name="user2" factory-bean="createUser" factory-method="getUser2"></bean>
<bean name="createUser" class="com.test.b_create.UserBeanFactory"></bean>
以上bean 的测试可以通过junit 的方法测试
public void fun1() throws Exception {
ApplicationContext ac = new ClassPathXmlApplicationContext("com/test/b_create/applicationContext.xml");
User user = (User) ac.getBean("user");
System.out.println(user);
}
Spring 的 Bean 的属性注入
1、set方法注入
<!-- set 方法注入 -->
<bean name="user" class="com.test.bean.User">
<property name="name" value="张三"/>
<property name="age" value="45"/>
<property name="car" ref="car"></property>
</bean>
值类型注入:为user 对象注入 name 和 age 属性
引用类型注入:为 car 属性时使用的 ref
注意:需要为该 POJO 类提供 set 方法
2、构造函数注入
<!-- 构造函数构造
name:构造函数的参数名
index:构造函数的参数索引
type:构造函数的参数类型
-->
<bean name="user2" class="com.test.bean.User" >
<constructor-arg name="name" value="李四" index="0" type="java.lang.String"></constructor-arg>
<constructor-arg name="car" ref="car" index="1" type="com.test.bean.Car"></constructor-arg>
</bean>
3、p 名称空间注入
<!-- p名称空间注入,走set方法
值类型: p:属性名="值"
对象类型: p:属性名-ref="bean名称"
-->
<bean name="user3" class="com.test.bean.User" p:name="李四qq" p:car-ref="car">
</bean>
使用这种方式记得要导入p名称空间
4、spel 注入
<bean name="user4" class="com.test.bean.User">
<property name="name" value="#{user.name}"></property>
<property name="age" value="#{user.age}"></property>
<property name="car" ref="car"></property>
</bean>
5、复杂类型注入
- 数组
<!-- 数组中只准备一个值,直接使用value|ref即可 -->
<property name="arr" value="tom"></property>
<property name="arr">
<array>
<value>mary</value>
<value>mary2</value>
</array>
</property>
- List
<property name="list">
<list>
<value>tom</value>
<ref bean="car"/>
</list>
</property>
- Map
<property name="map">
<map>
<entry key="haha" value="22"></entry>
<entry key-ref="car" value-ref="user"></entry>
</map>
</property>
- Properties
<property name="prop">
<props>
<prop key="driver">com.mysql.jdbc.driver</prop>
<prop key="url">jdbc:mysql://localhost:8080/user</prop>
<prop key="username">root</prop>
<prop key="password">root</prop>
</props>
</property>
五、Spring 的 Bean 的管理注解方式
步骤:
1、准备工作:导包,为主配置文件导入约束
2、开启使用注解代理配置文件
<!-- 扫描指定包下的所用类中的注解-->
<context:component-scan base-package="com.test.bean"></context:component-scan>
3、在类中使用注解完成配置
将对象注册到容器
首先准备一个POJO类
public class User {
private Integer id;
private String name;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
然后使用注解将该对象注册到容器中。在不同层使用不同的注解。
@Component("user")
@Controller // Controller 层
@Service // Service 层
@Repository // Dao 层
这三个注解是@Component的衍生,为了让注解类本身的用途清晰
Bean 的作用范围的注解
@Scope
//对象的作用范围
@Scope(scopeName="singleton")
//@Scope(scopeName="prototype")
singleton 是单例的,prototype 是多例的。
属性注入的注解
@Value 值类型注入
@Autowired 自动装配,引用类型注入。常和@Qualifier 一起使用
@Resource 手动注入
@Value("张三")
private String name;
@Autowired //自动注入
private Car car;
//如果匹配多个类型一致的对象时,将无法确定具体注入哪一个对象
@Qualifier("car1")
//手动注入
@Resource(name="car") //直接指定注入那个bean
注意:可以不用提供set 方法
Bean 的生命的周期的配置
@PostConstruct //构造对象后就调用
public void init() {
System.out.println("初始化方法~~~");
}
@PreDestroy //销毁方法之前
public void destroy() {
System.out.println("销毁方法");
}
总结