IOC的概念:
Ioc—Inversion of Control,即“控制反转”,不是什么技术,而是一种设计思想。在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制。即将对象的创建权交给了Spring容器管理;
DI的概念:
DI—Dependency Injection,即“依赖注入”:组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。
理解DI的关键是:“谁依赖谁,为什么需要依赖,谁注入谁,注入了什么”,那我们来深入分析一下:
●谁依赖于谁:当然是应用程序依赖于IoC容器;
●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源;
●谁注入谁:很明显是IoC容器注入应用程序某个对象,应用程序依赖的对象;
●注入了什么:就是注入某个对象所需要的外部资源(包括对象、资源、常量数据)。
IOC容器装配Bean:
1.三种实例化Bean的方式:
*使用类构造器实例化(默认无参数)
实例1,创建一个类Bean1,然后配置applicationContext.xml文件,配置文件一般命名为apllicationContext.xml,代码如下:
package com.spring.Bean;
/**
* 默认构造方法实例化
* @author 哎呦不错呦
*
*/
public class Bean1 {
public Bean1() {
}
}
下面在applicationContext.xml中进行配置;代码如下:
<!-- 默认情况下使用无参的构造方法 -->
<bean id="bean1" class="com.spring.Bean.Bean1"></bean>
*使用静态工厂实例化(简单工厂模式)
实例2:创建一个java类Bean2,然后在创建一个工厂类Bean2Factory,在工厂类中创建一个静态方法,调用静态方法返回Bean2对象。下面是代码:
package com.spring.Bean;
/**
* 静态工厂实例化
* @author 哎呦不错呦
*
*/
public class Bean2 {
}
package com.spring.Bean;
public class Bean2Factory {
public static Bean2 getBean2() {
System.out.println("你使用静态工厂调用了Bean2的方法");
return new Bean2();
}
}
接下来在配置applicationContext.xml文件。在xml文件中配置工厂类,并配置好factory-mothod方法;
<!-- 使用静态工厂实例化 -->
<bean id="bean2" class="com.spring.Bean.Bean2Factory" factory-method="getBean2"></bean>
*使用实例工厂方法实例化(工厂方法模式)
实例3:创建一个类Bean3,然后在创建一个工厂类Bean3Factory,编写方法返回Bean3对象,代码如下:
package com.spring.Bean;
/**
* 实例工厂实例化
* @author 哎呦不错呦
*
*/
public class Bean3 {
}
package com.spring.Bean;
/**
* Bean3Factory工厂类
* @author 哎呦不错呦
*
*/
public class Bean3Factory {
public Bean3 getBean3() {
System.out.println("使用了实例工厂实例化方法");
return new Bean3();
}
}
接下来再配置applicationContext.xml配置文件:
<!-- 使用实例工厂实例化 -->
<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
<bean id="bean3Factory" class="com.spring.Bean.Bean3Factory" ></bean>
最后是以上3种方法的测试类代码:
package com.spring.Bean;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* 测试
* @author 哎呦不错呦
*
*/
public class SpringTest {
/**
* 无参构造方法实例化
*/
@Test
public void demo1() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Bean1 bean1 = (Bean1) applicationContext.getBean("bean1");
System.out.println(bean1);
}
/**
* 静态工厂实例化
*/
@Test
public void demo2() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Bean2 bean2 = (Bean2) applicationContext.getBean("bean2");
System.out.println(bean2);
}
/**
* 实例工厂实例化
*/
@Test
public void demo3() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
Bean3 bean3 = (Bean3) applicationContext.getBean("bean3");
System.out.println(bean3);
}
}
Bean的作用域:(如下表说明)
类别 |
说明 |
singleton |
在Spring IoC容器中仅存在一个Bean实例,Bean以单例方式存在 |
prototype |
每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,相当于执行new XxxBean() |
request |
每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 |
session |
同一个HTTP Session 共享一个Bean,不同Session使用不同Bean,仅适用于WebApplicationContext 环境 |
globalSession |
一般用于Porlet应用环境,该作用域仅适用于WebApplicationContext 环境 |
Spring容器中Bean的声明周期:
1.instantiate bean对象实例化
2.populate properties 封装属性
3.如果Bean实现BeanNameAware 执行 setBeanName
4.如果Bean实现BeanFactoryAware 或者 ApplicationContextAware 设置工厂 setBeanFactory 或者上下文对象 setApplicationContext
5.如果存在类实现 BeanPostProcessor(后处理Bean) ,执行postProcessBeforeInitialization
6.如果Bean实现InitializingBean 执行 afterPropertiesSet
7.调用<bean init-method="init"> 指定初始化方法 init
8.如果存在类实现 BeanPostProcessor(处理Bean) ,执行postProcessAfterInitialization
9.执行业务处理
10.如果Bean实现 DisposableBean 执行 destroy
11.调用<bean destroy-method="customerDestroy"> 指定销毁方法 customerDestroy
注意:主要记住第5步及第8步;
Bean的属性注入:(Spring支持构造方法注入和setter方法注入)
1.构造器注入:
实例4:创建一个类Car,代码如下:
package com.study.SpringDemo5;
public class Car {
private String name;
private Double price;
public Car(String name, Double price) {
super();
this.name = name;
this.price = price;
}
public Car() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {//当创建对象时,自动调用此方法打印
return "Car [name=" + name + ", price=" + price + "]";
}
}
然后再配置applicationContext.xml文件;代码如下:
<bean id="car" class="com.study.SpringDemo5.Car">
<constructor-arg name="name" value="奥迪"></constructor-arg>
<constructor-arg name="price" value="500000"></constructor-arg>
<!-- 如果构造器注入属性的时候,参数为一个对象时可以使用ref属性 -->
<!-- <constructor-arg index="0" ref="car2" ></constructor-arg> -->
<constructor-arg index="0" value="别克" type="String"></constructor-arg>
<constructor-arg index="1" value="150000" type="Double"></constructor-arg>
</bean>
<!-- setter方法的注入 -->
<bean id="car2" class="com.study.SpringDemo5.Car2">
<property>标签中name就是属性名称,value是普通的属性的值,ref:引用其它对象
<property name="name" value="丰田"></property>
<property name="price" value="180000"></property>
</bean>
2.setter方法注入
实例5:创建一个类Car2,下面是实例代码:
package com.study.SpringDemo5;
public class Car2 {
private String name;
private Double price;
public void setName(String name) {
this.name = name;
}
public void setPrice(Double price) {
this.price = price;
}
@Override
//加载类的对象时方法自动执行
public String toString() {
return "Car2 [name=" + name + ", price=" + price + "]";
}
}
接下来再配置applcationContext.xml文件。代码如下:
<!-- setter方法的注入 -->
<!-- <bean id="car2" class="com.study.SpringDemo5.Car2">
<property>标签中name就是属性名称,value是普通的属性的值,ref:引用其它对象
<property name="name" value="丰田"></property>
<property name="price" value="180000"></property>
</bean> -->
p名称空间的使用:
为了简化XML文件配置,Spring从2.5开始引入一个新的p名称空间
p:<属性名>="xxx" 引入常量值
p:<属性名>-ref="xxx" 引用其它Bean对象
实例图片:
SpEl注入:
SpEL:spring expression language ,spring表达式语言,对依赖注入进行简化。
语法:#{表达式} 例子: <bean id="" value="#{表达式}">
SpEL如何使用呢?(使用方式)
#{'神回复:哈哈'}使用字符串
#{topicId3} 使用另一个bean
#{topicId4.content.toUpperCase()} 使用指定名属性,并使用方法
#{T(java.lang.Math).PI} 使用静态字段或方法
实例6:上述方式的实例,代码如下:
创建两个类,Person类,PersonInfo类,代码如下:
package com.study.SpringDemo5;
public class Person {
private String name;
private Car2 car2;
public void setName(String name) {
this.name = name;
}
public void setCar2(Car2 car2) {
this.car2 = car2;
}
@Override
public String toString() {
return "Person [name=" + name + ", car2=" + car2 + "]";
}
}
package com.study.SpringDemo5;
public class PersonInfo {
private String name;
public void setName(String name) {
this.name = name;
}
public String getName() {
return name;
}
public String showName() {
return name;
}
}
接下来编写applicationContext.xml代码,代码如下所示:
<!-- SpEL表达式 -->
<!-- <bean id="person" class="com.study.SpringDemo5.Person">
<property name="name" value="#{personInfo.name}"></property>
<property name="name" value="#{personInfo.showName()}"></property>
<property name="car2" value="#{car2}"></property>
</bean>
<bean id="personInfo" class="com.study.SpringDemo5.PersonInfo">
<property name="name" value="王五"></property>
</bean> -->
集合属性的注入:
实例7:创建一个类CollectionBean,在类中编写set集合、list集合、map集合等属性,代码如下:
package com.study.SpringDemo6;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
public class CollectionBean {
private List<String> list;
private Set<String> set;
private Map<String,String>map;
private Properties properties;
public void setList(List<String> list) {
this.list = list;
}
public void setSet(Set<String> set) {
this.set = set;
}
public void setMap(Map<String, String> map) {
this.map = map;
}
public void setProperties(Properties properties) {
this.properties = properties;
}
@Override
public String toString() {
return "CollectionBean [list=" + list + ", set=" + set + ", map=" + map + ", properties=" + properties + "]";
}
}
接下来就是编写applicationContext.xml代码,代码如下:
<!-- demo6集合属性注入 -->
<bean id="collectionBean" class="com.study.SpringDemo6.CollectionBean">
<!-- 注入list集合 -->
<property name="list">
<list>
<value>苹果</value>
<value>香蕉</value>
</list>
</property>
<!-- 注入set集合 -->
<property name="set">
<set>
<value>百度</value>
<value>头条</value>
</set>
</property>
<!-- 注入map集合 -->
<property name="map">
<map>
<entry key="红色" value="苹果"></entry>
<entry key="蓝色" value="蓝莓"></entry>
</map>
</property>
<!-- 注入properties -->
<property name="properties">
<props>
<prop key="username">账号</prop>
<prop key="password">密码</prop>
</props>
</property>
</bean>
最后编写测试类,测试这个实例的代码:
package com.study.SpringDemo6;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.study.SpringDemo5.Car;
public class SpringTest6 {
@Test
public void demo1() {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
CollectionBean collectionBean = (CollectionBean) applicationContext.getBean("collectionBean");
System.out.println(collectionBean);
}
}
加载配置文件的方法:
第一种写法:
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml","applicationContext2.xml",);
第二种写法:
在applicationContext.xml中加入applicationContext.xml文件
<import resource="applicationContext2.xml"/>
spring开发的时候需要的文件:(包含jar包以及applicatonContext.xml配置文件,还有log4j.properties)如下图所示
参考:传智播客 www.itcast.com