一、理解IOC控制反转和DI依赖注入
IOC:就是将原本在程序中手动创建对象的权利,交给Spring框架管理。
DI:依赖注入,就是在Spring框架负责创建Bean对象时,动态的将依赖对象注入到Bean组件。
IoC和DI的区别?
IOC:指将对象的创建权,反转到Spring容器。
DI:指Spring创建对象的过程中,将对象依赖的属性通过配置进行注入。
二、Spring的核心配置文件
applicationContext.xml
在程序中读取Spring配置文件的方式:
在程序中读取Spring配置文件,通过Spring框架获得Bean,完成相应操作
加载classpath (src):
new ClassPathXmlApplicationContext("applicationContext.xml");
加载磁盘路径:
new FileSystemXmlApplicationContext("applicationContext.xml");
创建Spring 核心工厂对象
通过工厂的getBean 获得配置实例对象 (IHelloService) applicationContext.getBean("helloService");
三、Spring工厂接口
BeanFactory接口和ApplicationContext接口区别?
*ApplicationContext接口间接继承于BeanFactory接口,其实Spring的核心工厂是BeanFactory。但是在现在的开发中,BeanFactory用的已经非常少了。
那么,BeanFactory和ApplicationContext最明显的区别是什么呢?
1、BeanFactory采取延迟加载策略,第一次getBean时才会初始化Bean。而ApplicationContext是在加载配置文件时初始化Bean。
2、ApplicationContext是对BeanFactory的扩展,提供了更多功能。
国际化处理、事件传递、Bean自动装配、各种不同应用层的Context实现。
由上可见,ApplicationContext是对BeanFactory的加强扩展。ApplicationContext的功能比BeanFactory更加多,所以现在开发中基本都在使用ApplicationContext,web项目中使用WebApplicationContext,很少用到BeanFactory。
四、IoC容器装配Bean(xml配置方式)
1、Spring提供配置Bean三种实例化方式
1)使用类构造器实例化(默认无参数)
<bean id="bean1" class="cn.itcast.spring.b_instance.Bean1"></bean>
2)使用静态工厂方法实例化(简单工厂模式)
<bean id="bean2" class="cn.itcast.spring.b_instance.Bean2Factory" factory-method="getBean2"></bean>
3)使用实例工厂方法实例化(工厂方法模式)
<bean id="bean3Factory" class="cn.itcast.spring.b_instance.Bean3Factory"></bean>
<bean id="bean3" factory-bean="bean3Factory" factory-method="getBean3"></bean>
2、Bean的其它属性配置
1)<bean>元素的id属性 和 name属性的区别
早期Spring开发中 Bean的 id属性 ,遵守xml语法 id约束
* id 的命名要满足XML对ID属性命名规范 必须以字母开始,可以使用字母、数字、连字符、下划线、句话、冒号
使用name属性,就可以使用很多特殊字符 , 早期在struts1 和 spring整合
<bean name="/login" class="....LoginAction" /> name中含有/ ,使用id会报错
****** 如果元素没有id只有name ,name 属性值可以作为id 使用
2)<bean>元素scope属性
* scope="singleton" 单例 ,在Spring IoC容器中仅存在一个Bean实例 (默认的scope)
* scope="prototype" 多例 ,每次从容器中调用Bean时,都返回一个新的实例,即每次调用getBean()时 ,相当于执行new XxxBean()
* scope="request" 用于web开发,将Bean放入request范围 ,request.setAttribute("xxx") , 在同一个request 获得同一个Bean
* scope="session" 用于web开发,将Bean 放入Session范围,在同一个Session 获得同一个Bean
* scope="globalSession" 一般用于Porlet应用环境 , 分布式系统存在全局session概念 ,如果不是porlet环境,globalSession 等同于Session
在开发中主要使用 scope="singleton"、 scope="prototype"
3、Bean的生命周期
在配置 <bean> 元素,通过 init-method 指定Bean的初始化方法,通过 destroy-method 指定Bean销毁方法
* destroy-method 只对 scope="singleton" 有效
* 销毁方法,必须关闭ApplicationContext对象,才会被调用
ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
applicationContext.close();
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
第三步和第四步,使Bean 了解Spring容器
第五步和第八步,使用BeanPostProcessor 就是钩子函数,作用用来对Bean对象进行扩展
问题: 在userDAO对象所有方法上 添加运行时间监控
解决: 使用 BeanPostProcessor 完成