一、概念
1.依赖注入
依赖注入DI(Dependency injection):接管对象的创建工作,并将该对象的引用注入需要该对象的组件。
A用到了B中的一些方法,若B是一个接口,有好多接口B的实现类,A的可重用性大大降低,使用new的话无法使用B的其他实现。为了能依赖注入,需要编写特定的set方法或者构建方法。
1.0版本:Spring同时支持sertter和构造器方式的依赖注入。
2.5版本:Spring可通过Autowired注解,支持基于field方式的依赖注入,但是缺点是程序必须引org.springframework.beans.factory.annotation.Autowired。
2.控制反转IOC
控制反转IOC(Inversion of Control)是一种设计思想,用来降低耦合度。是说创建对象的控制权进行转移,以前创建对象的主动权和创建时机是由自己把控的,而现在这种权力转移到第三方。
使用IOC前 使用IOC后
3.Spring的配置
使用Spring,程序几乎将所有重要的对象创建工作将交给Spring,配置如何注入依赖。Spring支持XML或注解两种方式。
需要创建一个ApplicationContext对象,代表一个Spring控制反转容器,org.springframework.context.ApplicationContext接口有多个实现,包括ClassPathXMLApplicationContext和FileSystemXmlApplicationContext和WebXmlApplicationContext,两个实现都需要至少一个包含beans信息的XML文件。两个都是用来加载XML配置文件,一个是类加载,一个是文件加载。
- FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构造器 XML 文件的完整路径。
- ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML 文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器会从 CLASSPATH 中搜索 bean 配置文件,myeclipse中直接放到src中即可。
- WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
二、IOC的使用
1.通过构造器创建bean实例
构造器创建bean实例文件(1)创建配置文件config.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-3.0.xsd ">
<!--构造器创建bean实例-->
<bean name="product" class="Product">
<property name="description" value="测试的东西"></property>
</bean>
</beans>
(2)创建实体类Product.java
public class Product {
private String name;
private String description;
private float price;
public Product() {
System.out.println("==============Product()==============");
}
public Product(String name, String description, float price) {
this.name = name;
this.description = description;
this.price = price;
}
public String getName() {
System.out.println("!!!!!!get name()!!!!!!");
return name;
}
public void setName(String name) {
System.out.println("!!!!!!set name()!!!!!!");
this.name = name;
}
public String getDescription() {
System.out.println("!!!!!!getDescription()!!!!!!");
return description;
}
public void setDescription(String description) {
System.out.println("!!!!!!setDescription()!!!!!!");
this.description = description;
}
public float getPrice() {
System.out.println("!!!!!!getPrice()!!!!!!");
return price;
}
public void setPrice(float price) {
System.out.println("!!!!!!setPrice()!!!!!!");
this.price = price;
}
}
(3)创建运行类Run.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Run{
public static void main(String[] args){
ApplicationContext context = new FileSystemXmlApplicationContext
("config.xml");
Product product1 = context.getBean("product", Product.class);
product1.setName("set的name");
System.out.println("得到: " + product1.getName()+"\t"+product1.getDescription());
}
}
(4)通过一个run.bat编译运行。
@echo off
set jarPath= %cd%\lib\commons-logging-1.1.jar;%cd%\lib\org.springframework.asm-3.0.1.RELEASE-A.jar;%cd%\lib\org.springframework.beans-3.0.1.RELEASE-A.jar;%cd%\lib\org.springframework.context-3.0.1.RELEASE-A.jar;%cd%\lib\org.springframework.core-3.0.1.RELEASE-A.jar;%cd%\lib\org.springframework.expression-3.0.1.RELEASE-A.jar;
javac -encoding UTF-8 -cp %jarPath% Run.java
javac Product.java
java -cp %jarPath% Run
pause
运行结果
2.通过静态工厂方法创建bean实例
静态工厂方法创建Bean实例,静态工厂是一个Java类,那么该class属性指定的就是该工厂的实现类,而不再是Bean的实现类,告诉Spring这个Bean应该由哪个静态工厂创建,另外我们还需要添加factory-method属性来指定由工厂的哪个方法来创建Bean实例,因此使用静态工厂方法创建Bean实例需要为<bean/>元素指定如下属性:
- class:指定静态工厂的实现类,告诉Spring该Bean实例应该由哪个静态工厂创建(指定工厂地址)
- factory-method:指定由静态工厂的哪个方法创建该Bean实例(指定由工厂的哪个车间创建Bean)
如果静态工厂方法需要参数,则使用<constructor-arg.../>元素传入
与上面构造器创造创建bean有些许差别
(1)config.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-3.0.xsd ">
<!--工厂方法创建bean实例-->
<bean id="product2" class="ProductFactory"
factory-method="setProduct">
<!-- 为静态工厂的setProduct()方法传参 -->
<constructor-arg value="传参么么哒"/>
<!-- 调用setDescription()方法为msg属性注入参数值 -->
<property name="description" value="注入的description"/>
</bean>
</beans>
(2)ProductFactory.java
public class ProductFactory {
public static Product setProduct(String arg){
Product ptest = new Product(arg);
return ptest;
}
}
(3)Run.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Run{
public static void main(String[] args){
ApplicationContext context = new FileSystemXmlApplicationContext
("config.xml");
Product product1 = context.getBean("product2", Product.class);
System.out.println("得到description: " + product1.getDescription()+" "+"得到name"+product1.getName());
}
}
其他的Product.java和run.bat参考1中做法,运行结果为:
静态工厂方法运行结果
3.通过实例工厂方法创建bean实例
静态工厂通过class指定静态工厂实现类然后通过相应的方法创建即可,调用实例工厂则需要先创建该工厂的Bean实例,然后引用该实例工厂Bean的id创建其他Bean,在实例工厂中通过factory-bean指定工厂Bean的实例,在调用实例化工厂方法中,不用在<bean/>中指定class属性,因为这时,不用直接实例化该Bean,而是通过调用实例化工厂的方法,创建Bean实例,调用实例化工厂需要为<bean/>指定一下两个属性
- factory-bean :该属性指定工厂Bean的id
- factory-method:该属性指定实例工厂的工厂方法。
在2的基础上修改了config.xml和ProductFactory.java
(1)config.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-3.0.xsd ">
<bean name="MyProductFactory" class="ProductFactory"/>
<!-- 由实例工厂Bean的setProduct()方法,创建Bean, -->
<bean id="product3" factory-bean="MyProductFactory" factory-method="setProduct">
<!-- 为该方法传入参数-->
<constructor-arg value="传参33"/>
<property name="description" value="注入的name33"/>
</bean>
<bean id="product4" factory-bean="MyProductFactory" factory-method="setProduct">
<!-- 为该方法传入参数-->
<constructor-arg value="传参44"/>
<property name="description" value="注入的name44"/>
</bean>
</beans>
(2)ProductFactory.java
public class ProductFactory {
public Product setProduct(String arg){
Product ptest = new Product(arg);
return ptest;
}
}
(3)Run.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Run{
public static void main(String[] args){
ApplicationContext context = new FileSystemXmlApplicationContext
("config.xml");
Product product3 = context.getBean("product3", Product.class);
System.out.println("得到product3"+product3.getName()+product3.getDescription());
Product product4 = context.getBean("product4", Product.class);
System.out.println("得到product4"+product4.getName()+product4.getDescription());
}
}
其他的Product.java和run.bat参考1中做法,运行结果为:
实例工厂方法运行结果
4.注意
(1)在配置spring标签是name和id的区别
id和name都是spring 容器中中bean 的唯一标识符。 同一个配置文件id和name不能重复。
- id: 一个bean的唯一标识 , 命名格式必须符合XML ID属性的命名规范
- name: 可以用特殊字符,并且一个bean可以用多个名称:name=“bean1,bean2,bean3” ,用逗号或者分号或者空格隔开。如果没有id,则name的第一个名称默认是id。
(2)调用实例工厂创建Bean和调用静态工厂的区别。
其实调用实例工厂创建Bean和调用静态工厂创建Bean的区别就在于,调用实例工厂将工厂单独拿了出来(先实例化工厂)创建一个工厂Bean,通过工厂<bean>的class属性指定工厂的实现类,然后再需要创建其他Bean时,只需要在该<bean/>元素添加factory-bean、factory-method指定该Bean是有哪个实例工厂的哪个方法创建就可以了,放在现实生活中就是:我们先找一个地方创建一个工厂,id指定工厂注册名字(xxx有限公司),class指定公司所在地,工厂里面有车间(创造其他Bean的方法),那好有了工厂我们再需要创建其他Bean时,只需要指定这个Bean是由,哪个工厂的哪个车间创建的即可,也就是只需要在该<bean/>元素添加factory-bean、factory-method属性即可
网友评论