Spring学习总结(6)——Spring之核心容器bean
一、Bean的基础知识
1.在xml配置文件中,bean的标识(id 和 name)
id:指定在benafactory中管理该bean的唯一的标识。name可用来唯一标识bean 或给bean起别名。
- <bean id="helloWorld" class="com.name.HelloWorld">
- ........
- <span style="color:#000000;"> </bean></span>
2.bean的class
class属性指定了bean的来源,即bean的实际路径。注意要指定全路径,而不可只写类名。
3.Singleton的使用
在spring中,bean可被定义为2中部署模式中的一种。singleton和prototype模式。
singloeton:只有一个共享的实例存在,所有对这个bean的请求都会返回这个唯一实例。
prototype:对这个bean的每次请求都会都会创建一个新的bean实例。根据已经存在的bean而clone出来的bean。默认为singleton模式。
改写成prototype模式写法如下:
- <bean id="student3" class="com.mucfc.beanfactory.Student" scope="prototype">
- .......
- </bean>
4.bean的属性
spring中,bean的属性值有2种注入方式。setter注入和构造函数注入。
setter注入是在调用无参的构造函数或无参的静态工厂方法实例化配置文档中定义的bean之后,通过调用bean上的setter方法实现的。
构造函数的依赖注入是通过调用带有很多参数的构造方法实现的,每个参数表示一个对象或者属性。
这里不懂看此文
5.对属性null值的处理
- <bean id="student5" class="com.mucfc.beanfactory.Student">
- <property name="std_name">
- <value></value>
- </property>
- <property name="std_id">
- <value>2005</value>
- </property>
- </bean>
或者
- <bean id="student5" class="com.mucfc.beanfactory.Student">
- <property name="std_name">
- <value/>
- </property>
- <property name="std_id">
- <value>2005</value>
- </property>
- </bean>
以上等同于this.std_name=null
6.使用依赖depends-on
此属性可在使用该bean之前,强制初始化一个或多个bean的初始化。例如
- <bean id="school" class="com.mucfc.beanfactory.School"
- depends-on="student6">
- <property name="student" ref="student6" />
- </bean>
其中student6如下:
- <bean id="student6" class="com.mucfc.beanfactory.Student">
- <property name="std_name" value="水水" />
- <property name="std_id" value="3009" />
- </bean>
7.指定bean引用
- <property name=" xxx" ref="yyyy "/>
或者
- <property name="xxxx">
- <ref bean="yyt"/>
- <property/>
8、ref local指定同一个xml文件中的引用
二、bean的生命周期
beanfactory中bean的生命周期图
2.1 实例bean
1.当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor接口,在实例化Bean之前,将调用接口的postProcessBeforeInstantiation()方法;
2.根据配置情况调用Bean构造函数或工厂方法实例化Bean;
3.如果容器注册了InstantiationAwareBeanPostProcessor接口,在实例化Bean之后,调用该接口的postProcessAfterInstantiation()方法,可在这里对已经实例化的对象进行一些"梳妆打扮";
4.如果Bean配置了属性信息,容器在这一步着手将配置值设置到Bean对应的属性中,不过在设置每个属性之前将先调用InstantiationAwareBeanPostProcessor接口的postProcessPropertyValues()方法;
2.2 初始化和使用bean
1:BeanNameAware的setBeanName():
如果Bean类有实现org.springframework.beans.BeanNameAware接口,工厂调用Bean的setBeanName()方法传递Bean的ID。
2:BeanFactoryAware的setBeanFactory():
如果Bean类有实现org.springframework.beans.factory.BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身。
3:BeanPostProcessors的ProcessBeforeInitialization()
如果有org.springframework.beans.factory.config.BeanPostProcessors和Bean关联,那么其postProcessBeforeInitialization()方法将被将被调用。
4:initializingBean的afterPropertiesSet():
如果Bean类已实现org.springframework.beans.factory.InitializingBean接口,则执行他的afterProPertiesSet()方法
5:Bean定义文件中定义init-method:
可以在Bean定义文件中使用"init-method"属性设定方法名称例如:
如果有以上设置的话,则执行到这个阶段,就会执行initBean()方法
6:BeanPostProcessors的ProcessaAfterInitialization()
如果有任何的BeanPostProcessors实例与Bean实例关联,则执行BeanPostProcessors实例的ProcessaAfterInitialization()方法
BeanPostProcessor后处理器定义了两个方法:
其一是postProcessBeforeInitialization()在第8步调用;其二是Object postProcessAfterInitialization(Object bean, String beanName)方法,这个方法在此时调用,容器再次获得对Bean进行加工处理的机会;
如果在<bean>中指定Bean的作用范围为scope="prototype",将Bean返回给调用者,调用者负责Bean后续生命的管理,Spring不再管理这个Bean的生命周期。如果作用范围设置为scope="singleton",则将Bean放入到Spring IoC容器的缓存池中,并将Bean引用返回给调用者,Spring继续对这些Bean进行后续的生命管理;
2.2 销毁bean
此时,Bean已经可以被应用系统使用,并且将保留在BeanFactory中知道它不在被使用。有两种方法可以将其从BeanFactory中删除掉
1:DisposableBean的destroy()
在容器关闭时,如果Bean类有实现org.springframework.beans.factory.DisposableBean接口,则执行他的destroy()方法
2:Bean定义文件中定义destroy-method
在容器关闭时,可以在Bean定义文件中使用"destroy-method"属性设定方法名称,例如:
如果有以上设定的话,则进行至这个阶段时,就会执行destroy()方法,如果是使用ApplicationContext来生成并管理Bean的话则稍有不同,使用ApplicationContext来生成及管理Bean实例的话,在执行BeanFactoryAware的setBeanFactory()阶段后,若Bean类上有实现org.springframework.context.ApplicationContextAware接口,则执行其setApplicationContext()方法,接着才执行BeanPostProcessors的ProcessBeforeInitialization()及之后的流程。
三、Beanfactory中bean生命周期实例
下面我们来看看一个实例吧,自己新建一个工程,导入需要的Spring包,然后建立如下Worker.java(这里是bean初始化和使用时会用到的函数 )
- package com.mucfc.beanlive;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.BeanFactoryAware;
- import org.springframework.beans.factory.BeanNameAware;
- import org.springframework.beans.factory.DisposableBean;
- import org.springframework.beans.factory.InitializingBean;
- //①管理Bean生命周期的接口
- public class Worker implements BeanFactoryAware,BeanNameAware,InitializingBean,DisposableBean{
- private String name;
- private String workType;
- private int salary;
- public BeanFactory beanFactory;
- private String beanName;
- public void Worker(){
- System.out.println("调用worker()构造函数");
- }
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public String getWorkType() {
- return workType;
- }
- public void setWorkType(String workType) {
- this.workType = workType;
- }
- public int getSalary() {
- return salary;
- }
- public void setSalary(int salary) {
- this.salary = salary;
- }
- public void printInfo() {
- System.out.println("name:" + name + ";workType:" + workType + ";salary:"
- + salary);
- }
- //⑤DisposableBean接口方法
- @Override
- public void destroy() throws Exception {
- System.out.println("----------------销毁bean----------------------");
- System.out.println("调用DisposableBean.destroy()。");
- }
- //④InitializingBean接口方法
- @Override
- public void afterPropertiesSet() throws Exception {
- System.out.println("调用InitializingBean.afterPropertiesSet()。");
- }
- //③BeanNameAware接口方法
- @Override
- public void setBeanName(String arg0) {
- System.out.println("----------------初始化bean----------------------");
- System.out.println("调用BeanNameAware.setBeanName()。");
- this.beanName = arg0;
- }
- //②BeanFactoryAware接口方法
- @Override
- public void setBeanFactory(BeanFactory arg0) throws BeansException {
- System.out.println("调用BeanFactoryAware.setBeanFactory()。");
- this.beanFactory = arg0;
- }
- //⑥通过<bean>的init-method属性指定的初始化方法
- public void myInit() {
- System.out.println("调用init-method所指定的myInit(),将salary设置为600。");
- this.salary = 600;
- }
- //⑦通过<bean>的destroy-method属性指定的销毁方法
- public void myDestroy() {
- System.out.println("调用destroy-method所指定的myDestroy()。");
- }
- }
Worker类在②、③、④、⑤处实现了BeanFactoryAware、BeanNameAware、InitializingBean、DisposableBean这些Bean级的生命周期控制接口;在⑥和⑦处定义了myInit()和myDestroy()方法,以便在配置文件中通过init-method和destroy-method属性定义初始化和销毁方法。
MyInstantiationAwareBeanPostProcessor通过扩展InstantiationAwareBeanPostProcessor适配器InstantiationAwareBeanPostProcessorAdapter提供实现:
(这是实例化bean时会用到的函数)
- package com.mucfc.beanlive;
- import java.beans.PropertyDescriptor;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.PropertyValues;
- import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessorAdapter;
- public class MyInstantiationAwareBeanPostProcessor extends
- InstantiationAwareBeanPostProcessorAdapter {
- // ①接口方法:在实例化Bean前进行调用
- public Object postProcessBeforeInstantiation(Class beanClass,
- String beanName) throws BeansException {
- System.out.println("----------------实例化bean----------------------");
- // ①-1仅对容器中worker Bean进行处理
- if ("worker".equals(beanName)) {
- System.out
- .println("InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation");
- }
- return null;
- }
- // ②接口方法:在实例化Bean后调用
- public boolean postProcessAfterInstantiation(Object bean, String beanName)
- throws BeansException {
- // ②-1仅对容器中car Bean进行处理
- if ("worker".equals(beanName)) {
- System.out
- .println("InstantiationAware BeanPostProcessor.postProcess AfterInstantiation");
- }
- return true;
- }
- // ③接口方法:在设置某个属性时调用
- public PropertyValues postProcessPropertyValues(PropertyValues pvs,
- PropertyDescriptor[] pds, Object bean, String beanName)
- throws BeansException {
- // ③-1仅对容器中wroker Bean进行处理,还可以通过pdst入参进行过滤,
- // 仅对car的某个特定属性时进行处理。
- if ("worker".equals(beanName)) {
- System.out
- .println("Instantiation AwareBeanPostProcessor.postProcess PropertyValues");
- }
- return pvs;
- }
- }
在MyInstantiationAwareBeanPostProcessor中,我们通过过滤条件仅对work Bean进行处理,而对其他的Bean一概视而不见。
此外,我们还提供了一个BeanPostProcessor实现类,在该实现类中,我们也只对work Bean进行处理,对配置文件所提供的属性设置值进行判断,并执行相应的"补缺补漏"的操作:
BeanPostProcessor实现类(这里是bean初始化和使用时会用到的函数 )
- package com.mucfc.beanlive;
- import org.springframework.beans.BeansException;
- import org.springframework.beans.factory.config.BeanPostProcessor;
- public class MyBeanPostProcessor implements BeanPostProcessor{
- @Override
- public Object postProcessAfterInitialization(Object bean, String beanName)
- throws BeansException {
- if(beanName.equals("worker")){
- Worker worker = (Worker)bean;
- if(worker.getWorkType() == null){
- System.out.println("调用BeanPostProcessor.postProcess AfterInitialization(), getWorkType为空,设置为默认临时工");
- worker.setWorkType("临时工");
- }
- }
- return bean;
- }
- @Override
- public Object postProcessBeforeInitialization(Object bean, String beanName)
- throws BeansException {
- if(beanName.equals("worker")){
- Worker worker = (Worker)bean;
- if(worker.getSalary() >= 1000){
- System.out.println("调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。");
- worker.setSalary(800);
- }
- }
- return bean;
- }
- }
在MyBeanPostProcessor类的postProcessBeforeInitialization()方法中,我们首先判断处理的Bean是否名为worker,如果是,进一步判断该Bean的workerType属性是否为空,如果为空,将该属性设置为"临时工"。在postProcessAfterInitialization()方法中,我们也是只对名为woker的Bean进行处理,判断其salary是否超过最大速度1000,如果超过,将其设置为800。(黑心老板啊!!!!!)
至于如何将MyInstantiationAwareBeanPostProcessor和MyBeanPostProcessor这两个后处理器注册到BeanFactory容器中
现在,我们在Spring配置文件中定义Car的配置信息,如代码清单3 29所示:
然后就是beans.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" xmlns:p="http://www.springframework.org/schema/p"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd">
- <bean id="worker" class="com.mucfc.beanlive.Worker"
- init-method="myInit"
- destroy-method="myDestroy"
- p:name="小强"
- p:salary="1000"
- />
- </beans>
使用方法:
- package com.mucfc.beanlive;
- import org.springframework.beans.factory.BeanFactory;
- import org.springframework.beans.factory.config.ConfigurableBeanFactory;
- import org.springframework.beans.factory.xml.XmlBeanFactory;
- import org.springframework.core.io.ClassPathResource;
- import org.springframework.core.io.Resource;
- public class Test {
- private static void LifeCycleInBeanFactory(){
- //①下面两句装载配置文件并启动容器
- Resource res = new ClassPathResource("beans.xml");
- BeanFactory bf = new XmlBeanFactory(res);
- //②向容器中注册MyBeanPostProcessor后处理器
- ((ConfigurableBeanFactory)bf).addBeanPostProcessor(new MyBeanPostProcessor());
- //③向容器中注册MyInstantiationAwareBeanPostProcessor后处理器
- ((ConfigurableBeanFactory)bf).addBeanPostProcessor(
- new MyInstantiationAwareBeanPostProcessor());
- //④第一次从容器中获取worker,将触发容器实例化该Bean,这将引发Bean生命周期方法的调用。
- Worker worker1 = (Worker)bf.getBean("worker");
- System.out.println("第一次从容器中获取worker");
- worker1.printInfo();
- System.out.println("修改第一次从容器中获取worker的workType");
- worker1.setWorkType("正式工");
- System.out.println("第一次从容器中获取worker(修改过后的)");
- worker1.printInfo();
- //⑤第二次从容器中获取worker,直接从缓存池中获取
- System.out.println("第二次从容器中获取worker");
- Worker worker2= (Worker)bf.getBean("worker");
- worker2.printInfo();
- //⑥查看worker1和worker2是否指向同一引用
- System.out.println("查看worker1和worker2是否指向同一引用 ");
- System.out.println("worker1==worker2:"+(worker1==worker2));
- //⑦关闭容器
- ((XmlBeanFactory)bf).destroySingletons();
- }
- public static void main(String[] args) {
- LifeCycleInBeanFactory();
- }
- }
输出结果:
图片看不清的话,看文字吧:
四月 07, 2015 3:43:54 下午 org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
信息: Loading XML bean definitions from class path resource [beans.xml]
----------------实例化bean----------------------
InstantiationAware BeanPostProcessor. postProcess BeforeInstantiation
InstantiationAware BeanPostProcessor.postProcess AfterInstantiation
Instantiation AwareBeanPostProcessor.postProcess PropertyValues
----------------初始化bean----------------------
调用BeanNameAware.setBeanName()。
调用BeanFactoryAware.setBeanFactory()。
调用BeanPostProcessor.postProcess BeforeInitialization(), 将salary调整为800。
调用InitializingBean.afterPropertiesSet()。
调用init-method所指定的myInit(),将salary设置为600。
调用BeanPostProcessor.postProcess AfterInitialization(), getWorkType为空,设置为默认临时工
第一次从容器中获取worker
name:小强;workType:临时工;salary:600
修改第一次从容器中获取worker的workType
第一次从容器中获取worker(修改过后的)
name:小强;workType:正式工;salary:600
第二次从容器中获取worker
name:小强;workType:正式工;salary:600
查看worker1和worker2是否指向同一引用
worker1==worker2:true
四月 07, 2015 3:43:54 下午 org.springframework.beans.factory.xml.XmlBeanFactory destroySingletons
信息: Destroying singletons in org.springframework.beans.factory.xml.XmlBeanFactory@16905e: defining beans [worker]; root of factory hierarchy
----------------销毁bean----------------------
调用DisposableBean.destroy()。
调用destroy-method所指定的myDestroy()。
我们可以看到第二次获取worker时,直接从容器的缓存中获取,它们两个的指向的是同一个引用!切记!
四、ApplicationContext与beanfactory的区别
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
Spring学习总结(6)——Spring之核心容器bean的更多相关文章
- Spring学习1:Spring基本特性
http://longliqiang88.github.io/2015/08/14/Spring%E5%AD%A6%E4%B9%A01%EF%BC%9ASpring%E5%9F%BA%E6%9C%AC ...
- Spring学习笔记之 Spring IOC容器(一)之 实例化容器,创建JavaBean对象,控制Bean实例化,setter方式注入,依赖属性的注入,自动装配功能实现自动属性注入
本节主要内容: 1.实例化Spring容器示例 2.利用Spring容器创建JavaBean对象 3.如何控制Bean实例化 4.利用Spring实现bean属性sett ...
- Spring之核心容器bean
摘要:Spring的核心容器实现了Ioc,其目 的是提供一种无侵入式的框架.在本文中,首先讲解了Spring的基础bean的相关知识,然后介绍了Spring是如何对bean进行管理的. 在Spring ...
- spring学习笔记(一) Spring概述
博主Spring学习笔记整理大部分内容来自Spring实战(第四版)这本书. 强烈建议新手购入或者需要电子书的留言. 在学习Spring之前,我们要了解这么几个问题:什么是Spring?Spring ...
- Spring学习1-初识Spring
一.简介 1.Spring是一个开源的控制反转(Inversion of Control ,IoC)和面向切面(AOP)的容器框架.它的主要目得是简化企业开发. 2.为何要使用Spring? ...
- Spring学习,初识Spring
Spring概述 将Spring理解为管理对象间依赖关系的容器 “解耦” 根据功能的不同,可以将一个系统中的代码分为 主业务逻辑 与 系统级业务逻辑 两类 ```Spring 是为了解决企业级开发的复 ...
- Spring学习 6- Spring MVC (Spring MVC原理及配置详解)
百度的面试官问:Web容器,Servlet容器,SpringMVC容器的区别: 我还写了个文章,说明web容器与servlet容器的联系,参考:servlet单实例多线程模式 这个文章有web容器与s ...
- 1.1(Spring学习笔记)Spring基础(BeanFactory、ApplicationContext 、依赖注入)
1.准备工作 下载Spring:http://repo.spring.io/libs-release-local/org/springframework/spring/ 选择需要下载的版本 ...
- Java架构师之路 Spring学习笔记(一) Spring介绍
前言 这是一篇原创的Spring学习笔记.主要记录我学习Spring4.0的过程.本人有四年的Java Web开发经验,最近在面试中遇到面试官总会问一些简单但我不会的Java问题,让我觉得有必要重新审 ...
- Spring学习(五)--构建Spring Web应用程序
一.Spring MVC起步 看过猫和老鼠的小伙伴都可以想象Tom猫所制作的捕鼠器:它的目标 是发送一个小钢球,让它经过一系列稀奇古怪的装置,最后触发捕鼠 器.小钢球穿过各种复杂的配件,从一个斜坡上滚 ...
随机推荐
- modSecurity规则学习(七)——防止SQL注入
1.数字型SQL注入 /opt/waf/owasp-modsecurity-crs/rules/REQUEST-942-APPLICATION-ATTACK-SQLI.conf"] [lin ...
- 用Struts2搭建一个登录例子【本人亲测好用】
今天尝试struts2的搭建,遇到不少的问题,终于一一解决,逛了很多地方,最终完成搭建 1.首先要下载struts2的一些组件,我下载的是版本2.3.4.1,Eclipse是4.6版本的.由于版本的不 ...
- 系统管理员的 SELinux 指南:这个大问题的 42 个答案
安全.坚固.遵从性.策略是末世中系统管理员的四骑士.除了我们的日常任务之外 —— 监控.备份.实施.调优.更新等等 —— 我们还需要负责我们的系统安全.即使这些系统是第三方提供商告诉我们该禁用增强安全 ...
- 请允许我成为你的夏季——shiro、jdbcInsertall
这两天总是觉得自己被关进了一个大笼子,日子拮据.生活不就是这样吗,一边觉得自己很差劲,一边又想成为一个更好的自己.可那又有什么办法呢,万物皆有裂痕,但那又怎样,那是光照进来的地方啊. 开始学习shir ...
- iOS基本UI控件总结
包括以下几类: //继承自NSObject:(暂列为控件) UIColor *_color; //颜色 UIImage *_image; //图像 //继承自UIView:只能相应手势UI ...
- IntelliJ IDEA 详细图解最常用的配置 ,适合刚刚用的新人。(转)
IntelliJ IDEA使用教程 (总目录篇) 刚刚使用IntelliJ IDEA 编辑器的时候,会有很多设置,会方便以后的开发,磨刀不误砍柴工. 比如:设置文件字体大小,代码自动完成提示,版本管理 ...
- 具体解释NoSQL数据库使用实例
一.NoSQL基础知识 1.关于NoSQL 在"NoSQL"一词.实际上是一个叫Racker的同事创造的,当约翰埃文斯埃里克要组织一次活动来讨论开源的分布式数据库. 这个名称和概念 ...
- vue ---- 组件传值之间使用 v-model
父子组件通信,都是单项的,很多时候需要双向通信.方法如下: 1.父组件使用:msg.sync="aa" 子组件使用$emit('update:msg', 'msg改变后的值xxx ...
- js的style和getArribute("属性名")
getAttribute()是HTML DOM的一个方法,用以获取HTML元素的属性(如id,name,type以及其他自定义属性). style是HTML DOM的一个关于样式的对象,style对象 ...
- string StartsWith 方法 Https
public ActionResult Index() { string url = "Https://www.baodu.com"; ...