Spring不是一个功能性质的框架,是一个框架的粘合剂!由Spring来维系框架和框架之间的关系,维系对象和对象之间的关系,对对象和框架之间的关系进行解耦!
Spring核心的两点:
IOC(Inversion of Control),DI((Dependency Injection)
对象和对象间的关系,不是由代码端由程序决定!而是由运行时
由容器决定!
注入依赖,对象和对象间的依赖关系是通过Spring注入得到的!IoC和DI可以理解为一个意思,不过现在一般都讲DI,因为DI描述的范围更广.AOP(Aspect Oriented Programming)
后面再介绍
在介绍Spring之前,先看以前维系对象和对象之间的关系是酱紫的:
class Girl{
private Tom tom = new Tom();
public void kiss(){
tom.kiss();
}
}
interface Boy{
public void kiss();
}
class Tom implement Boy{
public void kiss(){
System.out.println("tom was kissed !");
}
}
//在创建Girl对象时,就已经创建了Tom对象,Girl只是想kiss Tom,但是却要自己创建一个Tom对象,并且需要负责这个对象的创建和销毁,假如不想kiss Tom了,改成Jack,自己仍然要再创建一个Jack对象,需要的对象全部由自己创建,这种“原始社会”的状态也当然是不理想的!
社会进步了,找一个介绍所来生产Boy,想换就换,代码就变成了酱紫了:
class Girl{
private Boy boy = BoyFactory.create();
public void kiss(){
boy.kiss();
}
}
class BoyFactory{
public static Boy create(){
return new Tom();
}
}
interface Boy{
public void kiss();
}
class Tom implement Boy{
public void kiss(){
System.out.println("tom was kissed !");
}
}
//虽然这种方式比之前的要灵活一些,但是还是不够优秀,因为还需要由工厂生成对象,还需要修改工厂!
再变化 一下
class Girl{
private Boy boy;
public void kiss(){
tom.kiss();
}
}
interface Boy{
public void kiss();
}
class Tom implement Boy{
public void kiss(){
System.out.println("tom was kissed !");
}
}
//如果代码这样直接运行,肯定会报NullpointerException,因为boy对象根本不存在,但是用了Spring之后,它就能正常运行了,此时的Boy对象不是代码段写代码决定的,而在运行时,由Spring容器把这个Boy填充进去的,填充谁由容器决定!
class Girl{
private Boy boy; //要有set、get方法
public void kiss(){
boy.kiss();
}
}
interface Boy{
public void kiss();
}
class Tom implement Boy{
public void kiss(){
System.out.println("tom was kissed !");
}
}
//在Spring.xml中:
<beans>
<bean id="tom" class="com.test.Tom" />
<bean id="girl" class="com.test.Girl">
<property name="boy" ref="tom" />
</bean>
</beans>
//当调用时:
Girl girl = (Girl)BeanFactory.create("girl);
//这里的BeanFactory,Spring已经帮我们实现好了,直接用就可以
girl.kiss();
//此时运行的话,就会打印出“tom was kissed !",此时Spring.xml决定着对象与对象之间的关系!严格意义上说由运行时决定
//假如现在有另外一个对象Jack:
class Jack implement Boy{
public void kiss(){
System.out.println("jack was kissed !");
}
}
//此时只需要在Spring.xml中注入一个bean即可:
<bean id="jack" class="com.test.Jack" />
<bean id="girl" class="com.test.Girl">
<property name="boy" ref="jack" />
</bean>
//而此时的java类源码并没有发生任何变化,当再调用girl.kiss()时,就会打印”jack was kissed !"
//以上就是Spring的IoC、DI
对于Spring的注入方式,一共可分为三种:
- Set方式注入
- 构造函数注入
- 接口注入
对于Set方式注入:
实体类:Tom
public class Tom{
private String what;
public void setWhat(String what){
this.what = what;
}
public void eat(){
System.out.println("tom eat" + what);
}
}
//在测试类Test的main方法中
Resource resource = new ClassPathResource("spring.xml");
BeanFactory beanFactory = new XmlBeanFactory(resource);
Tom t = (Tom)beanFactory.getBean("tom");
t.eat();
此时打印出来的就是"tom eat meat".
//在spring.xml中
<bean id="tom" class="com.test.Tom">
<property name="what" value="meat" />
</bean>
//小结:
- 必须要有相关字段的set方法
- <property name="what" value="meat" />
如果填充的属性是基础数据类型或者包装类应该使用value!
其他对象应该使用ref!
对于构造函数注入:
实体类中必须要有构造函数:
public class Tom{
private String what;
public Tom(String what){
this.what = what;
}
public void eat(){
System.out.println("tom eat" + what);
}
}
//在spring.xml中
<bean id="tom" class="com.test.Tom">
<constructor-arg index="0" value="meat" />
//这里的index=“0”,代表构造函数中的第一个参数
</bean>
关于接口注入应用非常少,暂不介绍!应用中最多的是set方式注入
Spring的IoC与DI就是便于代码维护,软件工程中有一句话:世界上所有代码都至少经过三次以上的修改,只有有一个程序代码修改过两次,那是因为那个代码的工程师死在去第三次修改的路上!
Spring获取对象的方式有两种:
Tom t = (Tom)beanFactory.getBean("tom");
//tom必须是你xml定义的id!
Tom t = (Tom)beanFactory.getBean("tom");
//要求在xml中,Tom类对象只能有一个!