注意事项
<bean id="helloWorld" class="com.lijunyang.model">
<property name="name" value="Spring"></property>
</bean>
利用类型返回IOC容器中的Bean(setter方法注入的),要求IOC容器中必须只有一个该类型的Bean。
IOC&DI 介绍
IOC 反转资源获取方向
容器主动的将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接收资源,类似订报纸的感觉,送报纸的工人,将报纸送到你的家里或者手上。举个简单的例子,买菜,原来要你自己到菜场去买,现在通过IOC思想反转资源获取的方向,就是你在网上订菜,然后菜由人专门送到你家里或手上。<br />**IOC的前生---分离接口与实现,需求生产html或pdf不同类型的报表**<br />**![image.png](https://cdn.nlark.com/yuque/0/2019/png/219938/1559371154536-1b980fd2-8e91-47bb-adb5-837fbd9ad70d.png#align=left&display=inline&height=306&name=image.png&originHeight=306&originWidth=1030&size=218451&status=done&width=1030)**<br />**IOC的前生---采用工厂设计模式**<br />**![image.png](https://cdn.nlark.com/yuque/0/2019/png/219938/1559371233036-b0e4de6d-6a6d-4a0c-a042-72073519f796.png#align=left&display=inline&height=308&name=image.png&originHeight=308&originWidth=757&size=186907&status=done&width=757)**<br />**IOC采用反转控制**<br />**![image.png](https://cdn.nlark.com/yuque/0/2019/png/219938/1559371107370-477b25f0-c396-4ed2-9a03-daa6c4791dda.png#align=left&display=inline&height=403&name=image.png&originHeight=403&originWidth=1048&size=304019&status=done&width=1048)**
DI IOC的另一种表现形式
组件以一些预先定义好的方式,例如setter方法,接受来自如容器的资源注入,相对IOC而言,这种表述更直接。
配置Bean
- 配置形式:基于XML文件的方式;基于注解的方式;
- Bean的配置方式:通过全类名(反射),通过工厂方法(静态工厂方法&实例工厂方法),FactoryBean
- IOC容器 BeanFactory & ApplicationContext 概述
- 依赖注入的方式:属性注入;构造器注入
- 注入属性值细节
- 自动转配
- Bean之间的关系:继承;依赖
- Bean的作用域: singleton;prototype;WEB环境作用域
- 使用外部属性文件
- spEL
- IOC容器中Bean的生命周期
- Spring4.x新特性:泛型依赖注入
Spring IOC容器
在Spring IOC容器读取Bean配置创建Bean实例之前,必须对它进行实例化,只有在容器实例化后,才可以从IOC容器里获取Bean实例并使用。
Spring提供了两种类型的IOC容器实现,
- BeanFactory IOC容器的基本实现
- ApplicationContext 提供了更多的高级特性,是BeanFactory的子接口。
BeanFactory是Spring框架的基础设施,面向Spring本身;
applicationContext面向使用Spring框架的开发者,几乎所有的应用场合都直接使用ApplicationContext而非底层的BeanFactory
无论使用何种方式,配置文件是相同的。
ApplicationContext
ApplicationContext的主要实现类:
ClassPathXmlApplicationContext 从类路径下加载配置文件
FileSystemXmlApplicationContext 从文件系统中加载配置文件
ConfigurableApplicationContext 扩展与ApplicationContext,新增加了两个主要方法:refresh()和close(),让ApplicationContext具有启动,刷新,和关闭上下文的能力
ApplicationContext 在初始化上下文时就实例化所有单例的Bean。
WebApplicationContext 是专门为WEB应用而准备的,它允许从相对与WEB根目录的路径中完成初始化工作
依赖注入的方式
属性注入
属性注入即通过setter方法注入Bean的属性值或依赖的对象
属性注入使用
属性注入是实际应用中最常用的注入方式
// src/applicationCentext.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"
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-3.0.xsd">
<bean id="helloWorld" class="com.lijunyang.model">
<property name="name" value="Spring"></property>
</bean>
</beans>
构造器注入
通过构造器注入Bean的属性值或依赖的对象,它保证了Bean实例在实例化后就可以使用。
构造器注入在
可以通过index和type来区分构造方法
// src/applicationCentext.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"
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-3.0.xsd">
<bean id="car2" class="com.lijunyang.model">
<constructor-arg value="Baoma" type="java.lang.String" />
<constructor-arg value="Shanghai" type="java.lang.String" />
<constructor-arg value="240" type="int" />
</bean>
<bean id="car" class="com.lijunyang.model">
<constructor-arg value="Audi" index="0" />
<constructor-arg value="Shanghai" index="1" />
<constructor-arg value="300000" type="double" />
</bean>
</beans>
public class Car {
private String brand;
private String corp;
private double price;
private int maxSpeed;
public Car(String brand, String corp, double price) {
super();
this.brand = brand;
this.corp = corp;
this.price = price;
}
public Car(String brand, String corp, int maxSpeed) {
super();
this.brand = brand;
this.corp = corp;
this.maxSpeed = maxSpeed;
}
}
public class Main {
public static void main(String[] args) {
// 创建 Spring IOC容器
org.springframework.context.ApplicationContext ctx =
new ClassPathXmlApplicationContext("applicationContext.xml");
// 从容器中取出 Bean实例
Car car = (Car) ctx.getBean("car");
System.out.println(car);
Car car2 = (Car) ctx.getBean("car2");
System.out.println(car2);
// brand=Audi corp=Shanghai price=300000
// brand=Baoma corp=Shanghai maxSpeed=240
}
}
工厂方法注入(很少使用,不推荐) 略
Spring 配置的细节
字面量
字面值:可用字符串表示的值,可以通过<value>元素标签或value属性进行注入。
基本数据类型及其封装类,String等类型都可以采取字面值注入的方式。
若字面值中包含特殊字符,可以使用<![CDATA[]]>把字面值包裹起来。
<bean id="car2" class="com.lijunyang.model.Car">
<constructor-arg type="java.lang.String">
<value>Baoma</value>
</constructor-arg>
<constructor-arg type="java.lang.String">
<value><![CDATA[<shanghai^>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>250</value>
</constructor-arg>
</bean>
引用其他Bean
- 组成应用程序的Bean经常需要相互协作以完成应用程序的功能,要使Bean能够互相访问,就必须在Bean配置文件中指定对Bean的引用
- 在Bean的配置文件中,可以通过元素或ref属性为Ben的属性或构造器参数指定对Bean的引用。
- 也可以在属性或构造器里包含Bean的声明,这样的Bean称之为内部Bean
// src/com/lijunyang/model/Person.java
public class Person {
private String name;
private int age;
private Car car;
// getter/setter toString
}
// src/applicationCentext.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"
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-3.0.xsd">
<bean id="car2" class="com.lijunyang.model.Car">
<constructor-arg type="java.lang.String">
<value>Baoma</value>
</constructor-arg>
<constructor-arg type="java.lang.String">
<value><![CDATA[<shanghai^>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>250</value>
</constructor-arg>
</bean>
<bean id="person" class="com.lijunyang.model.Person">
<property name="name" value="Tom">
<property name="age" value="24">
<property name="car" ref="car2">
/*
<property name="name">
<ref bean="car2" />
</property>
*/
/* 内部bean
<bean id="car2" class="com.lijunyang.model.Car">
<constructor-arg type="java.lang.String">
<value>Ford</value>
</constructor-arg>
<constructor-arg type="java.lang.String">
<value><![CDATA[<shanghai^>]]></value>
</constructor-arg>
<constructor-arg type="double">
<value>200000</value>
</constructor-arg>
</bean>
*/
</bean>
</beans>
输入参数详解: null值和级联属性
- 可以使用专门的
元素标签为Bean的字符串或其他对象类型的属性注入null值 - 和Struts,Hiberante等框架一样,Spring支持级联属性的配置
<bean id="person" class="com.lijunyang.model.Person">
<constructor-arg value="Jerry" type="java.lang.String" />
<constructor-arg value="25">
/* 设置null值
<constructor-arg>
<null/>
</constructor-arg>
*/
<constructor-arg ref="car2">
// 设置级联属性。注意:属性需要先初始化后才可以为级联属性赋值,否则会异常,和Struts2不同。
<property name="car.price" value="250000" />
</bean>
集合属性
- 在Spring中可以通过一组内置的xml标签
- 配置java.util.List类的属性,需要指定list标签,在标签里包含一些元素,这些标签可以通过
指定简单的常量值,通过指定对其他Bean的引用,通过 指定内置的Bean定义,通过 指定空元素,甚至可以内嵌其他集合。 - 数组的定义和List一样,都使用
- 配置java.util.Set需要使用set标签,定义元素的方法和List一样
// src/com/lijunyang/model/Person.java
public class Person {
private String name;
private int age;
private List<Car> cars;
// getter/setter toString
}
// src/applicationCentext.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"
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-3.0.xsd">
<bean id="person" class="com.lijunyang.model.Person">
<property name="name" value="Tom">
<property name="age" value="24">
<property name="cars">
<list>
<ref bean="car2" />
<bean class="com.lijunyang.model.Car">
<constructor-arg type="java.lang.String">
<value>Baoma</value>
</constructor-arg>
<constructor-arg type="java.lang.String">
<value><![CDATA[<shanghai^>]]></value>
</constructor-arg>
<constructor-arg type="int">
<value>250</value>
</constructor-arg>
</bean>
</list>
</property>
</bean>
</beans>
集合属性
- java.util.Map 通过
- 必须在
标签里定义键 - 因为键和值的类型没有限制,所以可以自由地为它们指定
,, 或 元素。 - 可以将Map的键和值作为
属性定义:简单常量使用key和value来定义;Bean引用通过key-ref和value-ref属性定义 - 使用
定义java.util.Properties,该标签使用多个 作为子标签,每个 标签必须定义key属性
public class Person {
private String name;
private int age;
private Map<String, Car> cars;
// getter/setter toString
}
// src/applicationCentext.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"
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-3.0.xsd">
<bean id="person" class="com.lijunyang.model.Person">
<property name="name" value="Tom">
<property name="age" value="24">
<property name="cars">
<map>
<entry key="AA" value-ref="car2" />
</map>
</property>
</bean>
</beans>
public class DataSource {
private Properties properties;
public Properties getProperties() {
return properties;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "DataSource [properties=" + properties + "]";
}
}
<bean id="dataSource"
class="com.lijunyang.model.DataSource">
<property name="properties">
<props>
<prop key="user">root</prop>
<prop key="password">1234</prop>
<prop key="jdbcUrl">jdbc:mysql:\\\test</prop>
<prop key="driverClass">com.mysql.jdbc.Driver</prop>
</props>
</property>
<bean>
使用utility scheme 定义
- 使用基本的集合标签定义集合时,不能将集合作为独立的Bean定义,导致其他Bean无法引用该集合,所以无法在不同的Bean之间共享集合
- 可以使用util.schema 里的集合标签定义独立的集合Bean,需要注意的是,必须在
根元素里添加 util schema 定义
<!-- 配置单例的集合bean,以供多个bean进行引用,需要导入util命名空间 -->
<util:list id="cars">
<ref bean="car2" />
</util:list>
使用p命名空间
<!-- 通过p命名空间为bean的属性赋值,需要先导入p命名空间。相对于传统的配置方式更加简洁 -->
<bean id="person5" class="com.lijunyang.model.Person" p:age="30" p:name="Queen"
p:cars-ref="cars" />