1、Spring中的Bean
- Spring的所有组件都被当作bean来管理。所有的对象都处于Spring的管理中。
- Spring负责管理和维护所有的Bean,用户无需关心Bean的实例化。
- 开发者使用Spring框架所作的主要是两件事:开发Bean和配置Bean。
- 对于Spring框架来说,它要做的就是根据配置文件来创建Bean实例,并调用Bean实例的方法来完成“依赖注入”——所谓IoC的本质。
Spring框架的本质:根据XML配置驱动Java代码。将代码的耦合提升到XML配置中。
2、实例化Bean的方式
1)设值注入:就是通过property元素控制调用setter方法
优点:
- 与传统开发更接近,依赖关系更直观。
- 可以延迟注入的时间,并按需注入。不必要实例化所有的依赖Bean。
- 在有些参数可选的时候,设置注入显示的更灵活。想设置值,就为之配置property元素,否则就不配置。
2)构造注入:就是constructor-arg控制调用有参数的构造器,由构造器来注入被依赖组件。
优点:
- 可以在构造器中决定依赖关系的注入顺序。
- 不提供setter方法,可以避免后续代码对原有bean的破坏。
- 只有组件的创建者可以实现依赖关系,更符合高内聚的原则。
实际开发中建议以设置注入为主,构造注入为辅。
3)调用工厂类的静态方法
- 使用静态工厂方法创建Bean实例时,class指定创建Bean实例的静态工厂方类。
- Spring还需要知道由哪个静态工厂方法来创建Bean实例。使用factory-method属性来指定静态工厂方法名,Spring将调用静态工厂方法,来返回一个Bean实例。
- 通过为bean元素添加constructor-arg元素来确定静态工厂方法的参数
4)调用实例工厂的实例工厂方法。
- 实例工厂方法与静态工厂方法只有一点不同:调用静态工厂方法只需使用工厂类即可,调用实例工厂方法则必须使用工厂实例。
- 配置实例工厂方法与配置静态工厂方法也基本相似,只有一点区别:配置静态工厂方法指定静态工厂类,配置实例工厂方法则指定工厂实例。
3、案例
题目一: 人借助工具砍柴,砍柴的工具只有斧子
题目二: 人借助工具砍柴,砍柴的工具多了,除了斧子还有锯子,电动工具。
1)设值注入实现题目一
- 创建两个接口
public interface Person {
//定义使用工具的方法
public void useTool();
}
public interface Tool {
//定义砍柴的工具只有斧子
public String Axe();
}
- 创建两个实现类
其中人的实现类实现了setter方法
public class Lsj implements Person {
private Tool tool;
public void setTool(Tool tool) {
this.tool = tool;
}
@Override
public void useTool() {
System.out.println("lsj,借助工具砍柴");
System.out.println(tool.Axe());
}
}
public class UseAxe implements Tool {
@Override
public String Axe() {
return "砍柴的工具只有斧子";
}
}
- 配置Bean文件
<?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="Lsj" class="com.no2.t1_1.domain.Lsj" >
<property name="tool" ref="useAxe"></property>
</bean>
<bean id="useAxe" class="com.no2.t1_1.domain.UseAxe"></bean>
</beans>
- 测试类
public class TestBean {
public static void main(String[] args){
ApplicationContext ctx=new ClassPathXmlApplicationContext("com/no2/t1_1/Beans.xml");
Person p = ctx.getBean("Lsj", Person.class);
p.useTool();
}
}
2)构造注入实现题目一
构造注入实现不同的在于person的实现类改用构造方法,以及Bean的配置文件。
- person实现类
public class Long implements Person {
private Tool tool;
//构造注入的构造函数
public Long(Tool tool){
this.tool=tool;
}
@Override
public void useTool() {
System.out.print("long,借助工具砍柴,");
System.out.println(tool.Axe());
}
}
- 配置文件
<?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="long" class="com.no2.t1_2.domain.Long">
<constructor-arg ref="tool"/>
</bean>
<bean id="tool" class="com.no2.t1_2.domain.UseAxe"></bean>
</beans>
3)静态工厂方法 实现题目二
题目二这里只创建了一个工具接口
public interface Tool {
//定义
public void useTool();
}
然后实现三种工具的实现类
public class Axe implements Tool {
private String mes;
public void setMes(String mes){
this.mes=mes;
}
@Override
public void useTool() {
System.out.print("long,借助工具砍柴,");
System.out.println("砍柴的工具多了,你借助的工具是"+mes);
}
}
public class Electric implements Tool {
private String mes;
public void setMes(String mes) {
this.mes = mes;
}
@Override
public void useTool() {
System.out.print("long,借助工具砍柴,");
System.out.println("砍柴的工具多了,你借助的工具是"+mes);
}
}
public class Saw implements Tool {
private String mes;
public void setMes(String mes) {
this.mes = mes;
}
@Override
public void useTool() {
System.out.print("long,借助工具砍柴,");
System.out.println("砍柴的工具多了,你借助的工具是"+mes);
}
}
最重要的是创建静态的工厂类
public class ToolFactory {
//返回工具实例的静态工厂方法
public static Tool getTool(String t){
if (t.equalsIgnoreCase("Axe")){
return new Axe();
}else if (t.equalsIgnoreCase("Saw")){
return new Saw();
}else{
return new Electric();
}
}
}
配置文件
<?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,该bean负责产生其他bean实例 -->
<bean id="Axe" class="com.no2.t1_3.factory.ToolFactory" factory-method="getTool">
<!-- 配置静态工厂的参数-->
<constructor-arg value="Axe"></constructor-arg>
<!-- 驱动Spring以value值为参数来执行Axe的set()方法 -->
<property name="mes" value="斧子"></property>
</bean>
<bean id="Saw" class="com.no2.t1_3.factory.ToolFactory" factory-method="getTool">
<!-- 配置静态工厂的参数-->
<constructor-arg value="Saw"></constructor-arg>
<!-- 驱动Spring以value值为参数来执行Axe的set()方法 -->
<property name="mes" value="锯子"></property>
</bean>
<bean id="Electric" class="com.no2.t1_3.factory.ToolFactory" factory-method="getTool">
<!-- 配置静态工厂的参数-->
<constructor-arg value="Electric"></constructor-arg>
<!-- 驱动Spring以value值为参数来执行Axe的set()方法 -->
<property name="mes" value="电动工具"></property>
</bean>
</beans>
4)实例工厂注入实现题目二
跟静态工厂方法不同的是工厂方法不再是静态的。
public class ToolFactory {
//获得Tool实例的实例工厂方法
public Tool getTool(String tool){
if (tool.equalsIgnoreCase("Axe")){
return new Axe();
}else if(tool.equalsIgnoreCase("Saw")){
return new Saw();
}else{
return new Electric();
}
}
}
以及修改配置文件
<?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,该bean负责产生其他bean实例 -->
<bean id="tooFactory" class="com.no2.t1_4.factory.ToolFactory"></bean>
<bean id="Axe" factory-bean="tooFactory" factory-method="getTool">
<!-- 配置实例工厂方法的参数 -->
<constructor-arg value="Axe"></constructor-arg>
</bean>
<bean id="Saw" factory-bean="tooFactory" factory-method="getTool">
<constructor-arg value="Saw"></constructor-arg>
</bean>
<bean id="Electric" factory-bean="tooFactory" factory-method="getTool">
<constructor-arg value="Electric"></constructor-arg>
</bean>
</beans>