先来理解几个概念:
POJO类:是Plain Ordinary Java Object 的缩写,实质上可以理解为简单的是实体类,具有一部分getter/setter方法的那种类就可以称作POJO,但不允许有业务方法,也不能携带有connection之类的方法。
public class simplePOJO {
private String message;
private int age;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
}
JavaBean:JavaBean 是一种JAVA语言写成的可重用组件。为写成JavaBean,类必须是具体的和公共的,并且具有无参数的构造器。
所以上面给出的POJO类其实也是一个JavaBean,两者在概念上有很大一部分是重叠的,有些Spring教程里(比如我现在看的) 直接把 POJO和JavaBean当成同义词。
依赖注入:这是一个听起来很高大上的名词,我举个例子来说明它的含义:
Class A 中用到了ClassB 的对象b,一般情况下,需要在A的代码中显示的new一个B的对象。
采用依赖注入后,A的代码只需要一个私有的B对象,不需要直接new来获得这个对象,
而是通过相关的容器(IOC容器)来将B对象在外部new出来并注入到A类的引用中,
而具体的获取方法、对象性被获取时的状态由配置文件(如XML)来指定
IOC容器:是Spring框架的核心,负责控制对象的生命周期与关系。它的主要目的是为Spring的依赖注入提供技术支持。
常用的IOC容器如下:
① BeanFactory容器: 这是一个最简单的容器,它主要的功能是为依赖注入 (DI) 提供支持。在资源宝贵的移动设备或者基于 applet 的应用当中, BeanFactory 会被优先选择。否则,一般使用的是 ApplicationContext,除非你有更好的理由选择 BeanFactory。
②ApplicationContext容器: 是 spring 中较高级的容器。和 BeanFactory 类似,它可以加载配置文件中定义的 bean,将所有的 bean 集中在一起,当有请求的时候分配 bean。ApplicationContext 包含 BeanFactory 所有的功能,一般情况下,相对于 BeanFactory,ApplicationContext 会更加优秀, 另外,它增加 了企业所需要的功能。
最常被使用的 ApplicationContext 接口实现:
FileSystemXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你需要提供给构
造器 XML 文件的完整路径。
ClassPathXmlApplicationContext:该容器从 XML 文件中加载已被定义的 bean。在这里,你不需要提供 XML文件的完整路径,只需正确配置 CLASSPATH 环境变量即可,因为,容器 会从 CLASSPATH 中搜索 bean 配置文件。
WebXmlApplicationContext:该容器会在一个 web 应用程序的范围内加载在 XML 文件中已被定义的 bean。
Spring装配Bean的过程就是实现依赖注入的过程。其实在上篇的HelloSping实例就用到了装配Bean的知识点。下面我在稍微深入一下
一、通过构造器注入:
在此之前,我们已经声明了一个Hello的接口:
package Hello;
public interface Hello {
public void sayHi();
}
现在,我们写一个类来实现Hello接口
package Hello;
public class GoodMorning implements Hello {
private String message;
private int date;
public GoodMorning(String message, int date) {
this.message = message;
this.date = date;
}
@Override
public void sayHi() {
System.out.println(message+" 今天是:"+date+"号!" );
}
}
然后我们修改下Beans.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="helloSpring" class="Hello.HelloSpring"></bean>
<!--配置GoodMorning类-->
<bean id="goodMorning" class="Hello.GoodMorning">
<!--<constructor-arg> 用来告诉Spring实例化GoodMorning时构造方法所需的参数,参数类型可以显示指定,也可以不写,容器也可以使用与简单类型匹配的类型-->
<constructor-arg type="java.lang.String" value="早上好"/>
<constructor-arg type="int" value="1"/>
<!--
也可以这样写 参数类型可以省略,但是参数顺序一定要和类中构造方法的顺序相同
<constructor-arg value="早上好"/>
<constructor-arg value="1"/>
-->
</bean>
</beans>
现在我们利用ApplicationContext容器来获取这个配置好的Bean。
package Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Hello helloSpring =(Hello) context.getBean("goodMorning");
helloSpring.sayHi();
}
}
当我们需要在构造方法中引用一个对象的时候,我们要怎么做?
我们先来修改一下GoodMorning类的构造方法以及在重载的sayHi的方法中调用了hello.sayHi方法:
package Hello;
public class GoodMorning implements Hello {
private String message;
private int date;
private Hello hello;
public GoodMorning(String message, int date, Hello hello) {
this.message = message;
this.date = date;
this.hello = hello;
}
@Override
public void sayHi() {
hello.sayHi();
System.out.println(message+" 今天是:"+date+"号" );
}
}
接下来,我们需要去Beans.xml配置文件中,在原有的基础上添加一行代码
<constructor-arg ref="helloSpring"/>
如图:
在这里,我们引用了上篇教程里已经装配好的 helloSpring对象, 因为它实也现了Hello接口,这里用到了java多态的知识点。
值得注意的是:如果你想要向一个对象传递一个引用,你需要使用 标签的 ref 属性,如果你想要直接传递值,那么你应该使用如上所示的 value 属性。
接下来我们直接运行刚刚的HelloTest类,
package Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class HelloTest {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml");
Hello helloSpring =(Hello) context.getBean("goodMorning");
helloSpring.sayHi();
}
}
可以看到,HelloTest的类完全没有修改,Spring自动帮我们完成的对象实例化的过程,这个过程也被叫做 “依赖注入”。
二、通过setter方法实现依赖注入
这个方法的前提是,你的类中要有一个无参的构造方法。
现在我们为GoodMorning类加入一个无参的构造方法,然后为每个属性添加getter和setter方法
package Hello;
public class GoodMorning implements Hello {
private String message;
private int date;
private Hello hello;
public GoodMorning(){
//无参的构造方法
}
public GoodMorning(String message, int date, Hello hello) {
this.message = message;
this.date = date;
this.hello = hello;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public int getDate() {
return date;
}
public void setDate(int date) {
this.date = date;
}
public Hello getHello() {
return hello;
}
public void setHello(Hello hello) {
this.hello = hello;
}
@Override
public void sayHi() {
hello.sayHi();
System.out.println(message+" 今天是:"+date+"号" );
}
}
然后我们要修改下Beans.xml配置文件的内容,为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="helloSpring" class="Hello.HelloSpring"></bean>
<!--配置GoodMorning类-->
<bean id="goodMorning" class="Hello.GoodMorning">
<property name="message" value="早上好"/>
<property name="date" value="1"/>
<property name="hello" ref="helloSpring"/>
</bean>
</beans>
name属性对于GoodMorning 类中的变量名。
然后现在运行下HelloTest类,不用进行任何修改。
运行结果也是一样的,Spring框架简化java开发的作用就开始体现出来了,通过面向接口编程,不用理会GoodMorning类中是怎么样实现以及xml配置文件中的配置方式。
值得一提的是,尽管<property>元素为Bean的属性装配值和引用不太复杂,Spring框架还提供了一种另外Bean属性装配方式,该方式的优点在于不需要那么多的尖括号。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p ="http://www.springframework.org/schema/p"
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="helloSpring" class="Hello.HelloSpring"></bean>
<!--另一种装配方式-->
<bean id="goodMorning" class="Hello.GoodMorning"
p:message="早上好"
p:date="1"
p:hello-ref="helloSpring" />
</beans>