Spring Ioc容器
1、具有依赖注入功能的容器。负责实例化,定位,配置应用程序中的对象及建立这些对象间的依赖。在Spring中BeanFactory是Ioc容器的实际代表者。BeanFactory接口提供了IoC容器的基本功能。Spring Ioc容器通过读取配置文件中的配置元数据,通过元数据对应用中各个对象进行实例化及装配。
Spring Ioc容器管理的对象:Bean
1、定义
- Bean就是由Spring容器初始化、装配及管理的对象,此外bean与应用程序中的其他对象没有什么区别.
- Bean在容器内部由BeanDefinition对象表示。
2、BeanDefinition
- 全限定类名(FQN):用于定义Bean的实现类;(必须的)
- Bean行为定义:包括作用域(单例、原型创建)、是否惰性初始化及生命周期等;
- Bean创建方式定义:说明是通过构造器还是工厂方法创建Bean;
- Bean之间关系定义:即对其他bean的引用,也就是依赖关系定义,也就是依赖注入。
3、Bean的作用域
- “singleton”(单例,通过单例缓存池实现)
- “prototype”(原型,每次创建全新的bean)
- 另外提供“request”、“session”、“global session”三种web作用域
Spring IoC容器创建Bean 的方式
1、根据Bean定义里的配置元数据使用反射机制来创建Bean。
- 使用构造
- 静态工程方法
- 实例工厂方法
- 使用 FactoryBean 方式
2、使用构造: 创建对象使用无参构造的方式,使用最多的一种方式,注入数据用setter 方法
Fox类
package ecut.ioc.creation;
public class Fox {
private String id ;
private String name ;
public Fox() {
super();
System.out.println( "Fox 无参构造" );
}
public Fox(String id , String name) {
super();
this.id = id;
this.name = name;
System.out.println( "Fox( String , String ) 构造" );
}
@Override
public String toString() {
return "Fox [id=" + id + ", name=" + name + "]";
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
constructor-creation.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-4.3.xsd">
<!-- 调用无参构造 -->
<bean id="fox1" class="ecut.ioc.creation.Fox" >
<property name="id" value="A001" />
<property name="name" value="苏妲己" />
</bean>
<!-- 使用名称调用有参构造 ,建议使用可读性好-->
<bean id="fox2" class="ecut.ioc.creation.Fox" >
<constructor-arg name="id" value="B001" />
<constructor-arg name="name" value="雪山飞狐" />
</bean>
<!-- 使用索引调用有参构造 -->
<bean id="fox3" class="ecut.ioc.creation.Fox" >
<constructor-arg index="0" value="B002" />
<constructor-arg index="1" value="旋涡鸣人" />
</bean>
</beans>
测试类
package ecut.ioc.creation;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanCreationByConstructor {
public static void main(String[] args) {
String configLocations = "classpath:ecut/**/constructor-creation.xml" ;
AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
//需要有无参构造,不然会抛出BeanCreationException,因为没有指定默认的构造函数
Fox fox1 = container.getBean( "fox1" , Fox.class );
System.out.println( fox1 );
Fox fox2 = container.getBean( "fox2" , Fox.class );
System.out.println( fox2 );
Fox fox3 = container.getBean( "fox3" , Fox.class );
System.out.println( fox3 );
container.close();
}
}
3、静态工程方法:某个类里面有一个方法专门用创建这个类的对象
Sun类
package ecut.ioc.creation;
public class Sun {
/*//"饿汉"式实现单例
private static final Sun SUN =new Sun();
private Sun(){
super();
System.out.println( "构造方法执行" );
}
//调用getInstance()方法获取sun类型实例,调用类的静态方法是主动使用会导致 类被初始化
public static Sun getInstance(){
System.out.println( "使用静态方法返回 Sun 类型的实例" );
//这个Sun 类型的实例是单例的
return SUN ;
}*/
//懒汉式,线程安全实现单例
private static Sun SUN ;
private Sun(){
super();
System.out.println( "构造方法执行" );
}
//调用getInstance()方法获取sun类型实例,调用类的静态方法是主动使用会导致 类被初始化
public static Sun getInstance(){
System.out.println( "使用静态方法返回 Sun 类型的实例" );
//同步锁是类对应对象
synchronized ( Sun.class ) {
SUN = new Sun();
}
//这个Sun 类型的实例是单例的
return SUN ;
}
}
static-factory-method.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-4.3.xsd">
<!-- factory-method指定的是静态方法,通过调用静态方法之前 -->
<bean id="sun"
class="ecut.ioc.creation.Sun"
factory-method="getInstance" />
</beans>
测试类
package ecut.ioc.creation;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanCreationByStaticFactory {
public static void main(String[] args) {
String configLocations = "classpath:ecut/**/static-factory-method.xml" ;
AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
System.out.println( "~~~~~~~~~~~~~~~~~" );
//构造方法只执行一次,默认情况下,容器创建就已经创建了这个bean
Sun s = container.getBean( "sun" , Sun.class );
System.out.println( s );
Sun x = container.getBean( "sun" , Sun.class );
System.out.println( x );
container.close();
}
}
4、实例工厂方法:要有一个具体的工厂实例,有这个工厂实例去造bean
Car类
package ecut.ioc.creation;
public class Car {
private String brand ; // 品牌
public Car(){
super();
System.out.println( "Car无惨构造执行" );
}
public String getBrand() {
return brand;
}
public void setBrand(String brand) {
this.brand = brand;
}
}
CarFactory类
package ecut.ioc.creation;
public class CarFactory {
private String brandName ;
public CarFactory() {
super();
}
public CarFactory(String brandName) {
super();
this.brandName = brandName;
System.out.println( "CarFactory( String ) 构造执行" );
}
public Car create(){
System.out.println( "准备创建 Car 的实例" );
Car c = new Car();
c.setBrand( brandName );
return c ;
}
}
instance-factory-method.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-4.3.xsd">
<!-- 先 创建 Car 工厂 -->
<bean id="carFactory" class="ecut.ioc.creation.CarFactory" >
<constructor-arg name="brandName" value="BYD" />
</bean>
<!-- 再 通过 工厂实例 ( carFactory ) 的 非静态方法来创建 Car -->
<bean id="car" factory-bean="carFactory" factory-method="create" />
</beans>
测试类
package ecut.ioc.creation;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanCreationByInstanceFactory {
public static void main(String[] args) {
String configLocations = "classpath:ecut/**/instance-factory-method.xml" ;
AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
System.out.println( "~~~~~~~~~~~~~~~~~" );
Car c = container.getBean( "car" , Car.class );
System.out.println( c.getBrand() );
container.close();
}
}
5、使用 FactoryBean 方式:FactoryBean 是一个接口,由FactoryBean类型的对象造另外一个对象
DateFactoryBean
package ecut.ioc.creation;
import java.util.Calendar;
import java.util.Date;
import org.springframework.beans.factory.FactoryBean;
//期望返回的类型xx,则xxFactoryBean implements FactoryBean<xx>
public class DateFactoryBean implements FactoryBean<Date>{
private int year ;
private int month ;
private int date ;
private int hour ;
private int minute ;
private int second ;
private static final Calendar CALENDAR = Calendar.getInstance();
public DateFactoryBean(){
super();
System.out.println( "DateFactoryBean()" );
}
@Override
public Date getObject() throws Exception {
System.out.println( "准备获取 Date 类型实例" );
CALENDAR.set( year, month - 1 , date , hour , minute , second );
Date date = CALENDAR.getTime();
return date ;
}
@Override
public Class<?> getObjectType() {
return Date.class;
}
@Override
public boolean isSingleton() {
return false;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public int getMonth() {
return month;
}
public void setMonth(int month) {
this.month = month;
}
public int getDate() {
return date;
}
public void setDate(int date) {
this.date = date;
}
public int getHour() {
return hour;
}
public void setHour(int hour) {
this.hour = hour;
}
public int getMinute() {
return minute;
}
public void setMinute(int minute) {
this.minute = minute;
}
public int getSecond() {
return second;
}
public void setSecond(int second) {
this.second = second;
}
}
约定:期望返回的类型xx,则xxFactoryBean implements FactoryBean<xx>
factory-bean-creation.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-4.3.xsd">
<!-- 以前: 指定 class 是什么类型,就返回什么类型的实例 -->
<bean id="d" class="java.util.Date" />
<!-- 以前: 指定 class 是什么类型,就返回什么类型的实例,且是使用无参构造 创建bean,则必须要有无参构造-->
<bean id="fox1" class="ecut.ioc.creation.Fox" >
<property name="id" value="A001" />
<property name="name" value="苏妲己" />
</bean>
<!-- 这里: 指定的 class 是 XxxFactoryBean ,但是返回的却不是 XxxFactoryBean 类型的实例 -->
<!-- 而是返回了 XxxFactoryBean 内部的 getObject 方法所返回的那个实例 -->
<bean id="birthdate" class="ecut.ioc.creation.DateFactoryBean" >
<property name="year" value="1997" />
<property name="month" value="7" />
<property name="date" value="1" />
<property name="hour" value="12" />
<property name="minute" value="30" />
<property name="second" value="18" />
</bean>
</beans>
测试类
package ecut.ioc.creation;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class BeanCreationByFactoryBean {
public static void main(String[] args) {
String configLocations = "classpath:ecut/**/factory-bean-creation.xml" ;
AbstractApplicationContext container = new ClassPathXmlApplicationContext( configLocations );
Date d = container.getBean( "birthdate" , Date.class );
System.out.println( d );
DateFormat df = new SimpleDateFormat( "yyyy-MM-dd HH:mm:ss" );
System.out.println( df.format( d ) );
container.close();
}
}
转载请于明显处标明出处