1. IOC的概念
控制反转(Inversion of Control,缩写为IoC),是Spring的核心理念之一,可以用来减低计算机代码之间的耦合度。Spring用的是最常见的方式叫做依赖注入(Dependency Injection,简称DI)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
2.程序demo
HelloService.java
public interface HelloService {
//functions
}
HelloJAVA.java
public class HelloJAVA implements HelloService{
private String name;
public HelloJAVA() {
System.out.println("hello,JAVA");
}
public void setName(String name) {
System.out.println("set方法: " + name );
this.name = name;
}
public void sayhello() {
System.out.println("Hello, " + this.name);
}
}
HelloPHP.java
public class HelloPHP {
public HelloPHP() {
System.out.println("Hello,PHP");
}
}
ApplicationContext.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="hello" class="v01.helloWorld.HelloJAVA">
<property name="name" value="Spring"></property>
</bean>
</beans>
Main.java
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//1.创建IOC容器
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
}
}
运行结果:
说明Spring创建IOC容器的时候就已经为我们调用了构造器创建了Hello类对象,同时调用了set方法对属性进行了赋值。
将xml文件中bean的class换成“v01.helloWorld.HelloPHP”
运行结果:
对上面的程序进行分析:
有了IOC之后,更换实现类无需再在代码中找到所有的实现类的实例化对象,只需要修改配置文件即可进行实现类的轻松更改。
<bean id="hello" class="v01.helloWorld.Hello">
看到这个全类名就会想到Spring使用的是反射的形式来创建bean实例,所以就要求Hello类中要有一个无参的构造函数(默认情况下就是有的,但是如果写了一个有参构造就要显式写一个无参构造,否则运行不通过)
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
使用了工厂模式,ApplicationContext就是一个工厂类,通过context.getbean()去获取类的实例化对象。
总结来说,IOC的实现原理就是反射+工厂。
3. Spring三种实例化bean的方式(代码来自官方文档)
|-构造器实例化(推荐)
|-静态工厂实例化
|-普通工厂方法实例化
4.Bean Scopes
Spring官方给出了7种scope,实际上常用的就前两种singleton-单例(默认)和prototype
I.既然说到单例,那就自然会想到懒汉模式和饿汉模式,那么Spring创建对象的时候是在加载的时候还是第一次调用的时候呢?
--虽然用到的时候再加载会更加节省资源。但是Spring在加载bean的时候就已经帮我们创建好bean了,它的理念是正常情况下bean都是要被调用的,很少会出现一个bean写不来但是不调用的情况,这样的话两种方式资源的消耗都是差不多的。但是创建时加载有一个好处就是节省调用时的时间,如果每个bean调用时再去创建其实是很消耗时间的,但是加载时就创建好只是启动的时候耗时,用户感觉不到。当然Spring也可以设置调用时再实例化对象。(下面两种方式)
II.默认情况下Spring用的就是singleton,什么情况下需要用到prototype呢?
--比如Struts2使用的就是多例模式,在整合Spring的时候就需要配置prototype。
<bean id="hello" class="v01.helloWorld.HelloPHP" scope="prototye">
5. 依赖注入DI(Dependency Injection)
|-基于构造器的依赖注入
|-基于Setter的依赖注入
理解就行,实际开发大部分是用annotation(看后面)
6. 基于xml进行自动装配
|-no:没有自动转配(默认)
|-byType:根据属性数据类型进行自动装配
|-byName:根据属性名称进行自动装配
|-constructor:实质上就是byType的基于构造器注入
全局配置自动装配
<beans default-autowire="byName">
局部配置自动装配
<bean autowire="byName">
7. 基于annotation进行自动装配
有了annotation之后,Spring的世界开始变得无比简单和整洁,写了这么多,终于可以跟繁琐的xml配置say Byebye了。
<?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.xsd">
<context:annotation-config/>
<bean id="hello" class="v01.helloWorld.HelloPHP" scope="prototye">
<!-- 此处无需再配置关系 -->
</bean>
</beans>
之后只需要在需要注入的setter或者构造器上面写上@Autowired就可以实现自动注入啦!
你以为这样就完了嘛?最神奇的还在后面,annotation终极体,一行配置搞定所有。
<?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.xsd">
<context:component-scan base-package="org.example"/>
</beans>
之后只需要去接口的实现类写上annotation就可以啦!(懒得写demo了,贴上写在实现类上的annotation定义)