Spring学习小结

文章目录

  • 1. BeanFactory与ApplicationContext的关系
  • 2.只在Spring基础环境下,常用的三个ApplicationContext
  • 3.Spring开发中Bean的配置
  • 4. Bean的初始化和销毁方法配置
  • 5 Bean的实例化配置


1. BeanFactory与ApplicationContext的关系

  1. BeanFactory是Spring的早期接口,称为Spring的Bean工厂,ApplicationContext是后期更高级接口,称之为Spring容器;
  2. ApplicationContext在BeanFactory基础上对功能进行了扩展,例如:监听功能、国际化功能等。BeanFactory的API更偏向底层,ApplicationContext的API大多数是对这些底层API的封装;
  3. Bean创建的主要逻辑和功能都被封装在BeanFactory中,ApplicationContext不仅继承了BeanFactory,而且ApplicationContext内部还维护着BeanFactory的引用,所以,ApplicationContext与BeanFactory既有继承关系,又有融合关系。
  4. Bean的初始化时机不同,原始BeanFactory是在首次调用getBean时才进行Bean的创建,而ApplicationContext则是配置文件加载,容器一创建就将Bean都实例化并初始化好。

Spring学习小结_第1张图片

2.只在Spring基础环境下,常用的三个ApplicationContext

实现类 功能描述
ClassPathXmlApplicationContext 加载类路径下的xml配置的ApplicationContext
FileSystemXmlApplicationContext 加载磁盘路径下的xml配置的ApplicationContext
AnnotationConfigApplicationContext 加载注解配置类的ApplicationContext

3.Spring开发中Bean的配置

Bean的常用配置

Xml配置方式 功能描述
Bean的id和全限定名配置
通过name设置Bean的别名,通过别名也能直接获取到Bean实例
Bean的作用范围,BeanFactory作为容器时取值singleton和prototype
Bean的实例化时机,是否延迟加载。BeanFactory作为容器时无效
Bean实例化后自动执行的初始化方法,method指定方法名
Bean实例销毁前的方法,method指定方法名
设置自动注入模式,常用的有按照类型byType,按照名字byName
指定哪个工厂Bean的哪个方法完成Bean的创建

beanName
例如:
配置UserDaolmpl由Spring容器负责管理


此时存储到Spring容器(singleObjects单例池Map)中的Bean的beanName是testDaoService,值是TestDaoService对象,可以根据beanName获取Bean实例

applicationContext.getBean ( "testDaoService");

Spring学习小结_第2张图片

如果不配置id,则Spring会把当前Bean实例的全限定名作为beanName

applicationContext.getBean ( "com.hyl.service.TestDaoService");

Spring学习小结_第3张图片

如果起别名,在没有配置id的时候,默认第一个别名为beanName;
Spring学习小结_第4张图片

如果配置的有id,同时也起了别名,这时候别名对应的还是id名,beanName还是id。
Spring学习小结_第5张图片

默认情况下,单纯的Spring环境Bean的作用范围有两个: Singleton和Prototype

  1. singleton:单例,默认值,Spring容器创建的时候,就会进行Bean的实例化,并存储到容器内部的单例池中,每次getBean时都是从单例池中获取相同的Bean实例;
  2. prototype:原型,Spring容器初始化时不会创建Bean实例,当调用getBean时才会实例化Bean,每次getBean都会创建一个新的Bean实例。

Bean的延迟加载

当lazy-init设置为true时为延迟加载,也就是当Spring容器创建的时候,不会立即创建Bean实例,等待用到时在创建Bean实例并存储到单例池中去,后续在使用该Bean直接从单例池获取即可,本质上该Bean还是单例的。

4. Bean的初始化和销毁方法配置

  1. 我们可以直接在bean里面配置对应的映射方法。
init-method="方法名1" destroy-method="方法名2"
  1. 我们还可以通过实现InitializingBean 接口,完成一些Bean的初始化操作,如下:
public class UserDaoImpl implements UserDao,InitializingBean {

	public UserDaoImpl() {
		System.out.println ( "UserDaoImpl创建了...");
	}
	public void init() {
		System.out.println("初始化方法..."); 
	}
	public void destroy () {
		System.out.println("销毁方法...");
	}
	//执行时机早于init-method配置的方法
	public void afterPropertiesSet ( ) throws Exception {
		System. out.println ( "InitializingBean . . . " )
	}
}

5 Bean的实例化配置

Spring的实例化方式主要如下两种:
构造方式实例化:底层通过构造方法对Bean进行实例化
工厂方式实例化:底层通过调用自定义的工厂方法对Bean进行实例化

构造方式实例化Bean:
分为无参构造方法实例化和有参构造方法实例化,Spring中配置的几乎都是无参构;有参构造在实例化Bean时,需要参数的注入,通过标签,嵌入在标签内部提供构造参数
工厂方式实例化Bean,可分为如下三种:

静态工厂方法实例化Bean
实例工厂方法实例化Bean
实现FactoryBean规范延迟实例化Bean

静态工厂方法实例化Bean,其实就是定义一个工厂类,提供一个静态方法用于生产Bean实例,在将该工厂类及其静态方法配置给Spring即可。

//工厂类
public class UserDaoFactoryBean {
	//非静态工厂方法
	public static UserDao getUserDao(String name){
		//可以在此编写一些其他逻辑代码
		return new UserDaoImpl();
	}
}



	

UserDaoImpl实例对象会存在于单例池中。

实例工厂方法,也就是非静态工厂方法产生Bean实例,与静态工厂方式比较,该方式需要先有工厂对象,在用工厂对象去调用非静态方法,所以在进行配置时,要先配置工厂Bean,在配置目标Bean。

//工厂类
public class UserDaoFactoryBean2 {
	//非静态工厂方法
	public UserDao getUserDao(String name){
		//可以在此编写一些其他逻辑代码
		return new UserDaoImpl();
	}
}





	

在Spring容器创建时,就完成了Bean的实例化,单例池中既有工厂Bean实例,也有目标Bean实例.

注:
标签不仅仅是为构造方法传递参数,只要是为了实例化对象而传递的参数都可以通过标签完成,例如上面通过工厂方法实例化Bean所传递的参数也是要通过进行传递的

Spring提供的FactoryBean接口规范(源码)

package org.springframework.beans.factory;

public interface FactoryBean {
	//获得实例对象方法
    T getObject() throws Exception;
	//获得实例对象类型方法
    Class getObjectType();

    boolean isSingleton();
}

实现过程
定义工厂实现FactoryBean

public class UserDaoFactoryBean3 implements FactoryBean {
	public UserDao getObject() throws Exception {
		return new UserDaoImpl();
	}
	public Class getObjectType() {
		return UserDao.class;
	}
}


ps: 通过断点观察发现Spring容器创建时,FactoryBean被实例化了,并存储到了单例池singletonObjects中,但是getObject() 方法尚未被执行,UserDaoImpl也没被实例化,当首次用到UserDaoImpl时,才调用getObject() ,此工厂方式产生的Bean实例不会存储到单例池singletonObjects中,会存储到 factoryBeanObjectCache 缓存池中,并且后期每次使用到userDao都从该缓存池中返回的是同一个userDao实例。

你可能感兴趣的:(spring,学习,java)