Spring之Bean(二)
2016-04-29 20:46
344 查看
关于Bean
Spring核心容器是一个超级大工厂,所有的对象(包括数据源、Hibernate SessionFactory等基础性资源)都会被当成Spring核心容器管理的对象。Spring把容器中一切对象统称为Bean。
对于Spring框架而言,一切Java对象都是Bean。只要是个Java类,Spring就可以管理该Java类,并将它当成Bean管理。下面定义Axe类和Person类两个类,其中的Person类的useAxe()方法需要调用Axe对象的chop()方法,像这种A对象需要调用B对象方法的情形,被称为依赖。该示例中Person类依赖于Axe对象。示例代码如下:
使用Spring框架后,Spring核心容器是整个应用中的超级大工厂,所有Java对象都交给Spring容器实现,这些对象被统称为Spring容器中的Bean。
Spring beans
Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中< bean/> 的形式定义。
Spring 框架定义的beans都是单件beans。在bean tag中有个属性”singleton”,如果它被赋为TRUE,bean 就是单件,否则就是一个 prototype bean。默认是TRUE,所以所有在Spring框架中的beans 缺省都是单件。
Spring的内部bean
当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,为了定义inner bean,在Spring 的 基于XML的 配置元数据中,可以在 或 元素内使用 元素,内部bean通常是匿名的,它们的Scope一般是prototype。
如何管理Bean
给Spring 容器配置元数据
Spring容器管理Bean可以通过XML配置文件,也可以用注解,或者基于java的配置。
该配置文件根源上是< beans…/>,里面包括多个< bean…/>元素,每个< bean…/>元素定义一个Bean。以上配置文件中一共定义3个Bean,其中前两个Bean是Axe和Person类,最后一个是直接使用了JDK提供的java.util.Date和javax.swing.JFrame类。由于Spring可以把“一切Java对象”当成容器中的Bean,所以不管Java类是JDK提供的,还是第三方框架提供的,或者是开发者自己实现的…..只要是个Java类,并将其配置到XML文件中,Spring容器就可以管理它。
配置文件中的< bean…/>元素默认以反射方式调用该类的无参构造器,以下面代码为例:
Spring框架解析该< bean…/>元素后将可以得到idStr和classStr两个字符串,idStr的值为“person”(解析< bean…>元素的id属性得到的值),classStr的值为“com.afy.spring.beans.Person”(解析< bean…/>元素的class属性得到的值)。Spring底层会执行如下格式的代码:
这段代码是基本的反射代码(不是Spring底层所有代码),Spring框架通过反射根据< bean…/>元素的属性指定的类名创建了一个Java对象,并以< bean…/>元素的id属性的值为key,将该对象放入Spring容器中,这个Java对象就称为Spring容器中的Bean。
可以简单地理解为每个< bean…/>元素默认驱动Spring调用该类无参构造器创建实例,并将该实例作为Spring容器中的Bean。
在Spring配置文件中配置Bean时,class属性的值必须是Bean实现类的完整类名(必须带包名),不能是接口或抽象类(除非有特殊配置),否则Spring无法使用反射创建该类的实例。
配置文件中还包含一个< property…/>子元素,< property…/>子元素驱动Spring在底层以反射执行一次setter方法。其中< property…/>的name属性值决定执行哪个setter方法,而value或ref决定执行setter方法的传入参数。
[] 如果传入参数是基本类型及其包装类、Spring等类型,则使用value属性指定传入参数。
[] 如果以容器中其他Bean作为传入参数,则使用ref属性指定传入参数。
Spring只要看到< property…/>子元素,Spring框架就会在底层以反射方式执行一次setter方法,那什么时候执行这个setter方法呢?该Bean一旦创建处理,Spring就会立即根据< property…/>子元素类执行setter方法。也就是说,< bean…/>元素驱动Spring调用无参构造器创建对象;< property…/>子元素驱动Spring执行setter方法,这两步是先后执行的,中间几乎没有任何间隔。如:
< property…/>子元素的name属性值为axe,该元素将驱动Spring以反射方式执行Person Bean的setAxe()方法;ref属性值为axe,该属性值指定以容器中名为axe的Bean作为执行setter方法的传入参数。Spring底层会执行如下格式的代码:
可以简单地理解为每个< property…/>元素默认驱动Spring调用一次setter方法。
由此可见上面配置3个< bean…/>元素时Spring会一次创建com.afy.spring.beans.Person、com.afy.spring.beans.Axe、java.util.Date这3个类的对象,并把它们当成容器中的Bean。
其中id为Person的< bean…/>元素还包括一个< property…/>子元素,因此Spring会在创建完person Bean之后,立即以容器中id为axe的Bean作为参数调用person Bean的setAxe()方法,这样会导致容器中id为axe的Bean被赋值给person对象的axe实例变量。
定义类的作用域
当定义一个< bean> 在Spring里,我们还能给这个bean声明一个作用域。它可以通过bean 定义中的scope属性来定义。如,当Spring要在需要的时候每次生产一个新的bean实例,bean的scope属性被指定为prototype。另一方面,一个bean每次使用的时候必须返回同一个实例,这个bean的scope 属性 必须设为 singleton。
Spring支持的几种bean的作用域
Spring框架支持以下五种bean的作用域:
singleton : bean在每个Spring ioc 容器中只有一个实例。
prototype:一个bean的定义可以有多个实例。
request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
缺省的Spring bean 的作用域是Singleton。
Spring框架中bean的生命周期
Spring容器 从XML 文件中读取bean的定义,并实例化bean。
Spring根据bean的定义填充所有的属性。
如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。
如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
如果bean实现了 DisposableBean,它将调用destroy()方法。
重要的bean生命周期方法
有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用。第二个方法是 teardown 它是在容器卸载类的时候被调用。
The bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。
在 Spring中如何注入一个java集合?
Spring提供以下几种集合的配置元素:
< list>类型用于注入一列值,允许有相同的值。
< set> 类型用于注入一组值,不允许有相同的值。
< map> 类型用于注入一组键值对,键和值都可以为任意类型。
< props>类型用于注入一组键值对,键和值都只能为String类型。
Spring容器访问Bean
配置完Bean后要通过Spring容器访问容器中的Bean。
在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用。
Spring 提供了两种类型的 IOC 容器实现:
1. BeanFactory: IOC 容器的基本实现;
2. ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口。
BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,是Spring容器最常用的接口,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory。该接口下有如下两个实现类:
1. ClassPathXmlApplicationContext:从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器;
2. FileSystemXmlApplicationContext:从文件系统的相对路径或绝对路径下去搜索配置文件,并根据配置文件来创建Sprig容器。
Java项目中,类加载路径是稳定的,因此通常是使用 ClassPathXmlApplicationContext创建Spring容器。
Spring容器获取Bean对象主要有如下两个方法:
1. Object getBean(String id):根据容器中Bean的id来获取指定Bean,获取Bean之后需要进行强制类型转换;
2. T getBean(String name,Class requireType):根据容器中Bean的id来获取指定Bean,但该方法带一个泛型参数,因此获取Bean之后无需进行类型转换。
获取Bean(即Java对象)之后,即可以通过对象来调用方法、访问实例变量,像普通使用Java对象一样使用。
Spring核心容器是一个超级大工厂,所有的对象(包括数据源、Hibernate SessionFactory等基础性资源)都会被当成Spring核心容器管理的对象。Spring把容器中一切对象统称为Bean。
对于Spring框架而言,一切Java对象都是Bean。只要是个Java类,Spring就可以管理该Java类,并将它当成Bean管理。下面定义Axe类和Person类两个类,其中的Person类的useAxe()方法需要调用Axe对象的chop()方法,像这种A对象需要调用B对象方法的情形,被称为依赖。该示例中Person类依赖于Axe对象。示例代码如下:
public class Axe{ public String chop(){ return "使用斧头砍柴"; } }
public class Person{ private Axe axe; //设置注入所需的setter方法 public void setAxe(Axe axe){ this.axe = axe; } public void useAxe(){ System.out.println("我打算去砍点柴!"); //调用axe的chop()方法, //表明Person对象依赖于axe对象 System.out.prntln(axe.chop); } }
使用Spring框架后,Spring核心容器是整个应用中的超级大工厂,所有Java对象都交给Spring容器实现,这些对象被统称为Spring容器中的Bean。
Spring beans
Spring beans 是那些形成Spring应用的主干的java对象。它们被Spring IOC容器初始化,装配,和管理。这些beans通过容器中配置的元数据创建。比如,以XML文件中< bean/> 的形式定义。
Spring 框架定义的beans都是单件beans。在bean tag中有个属性”singleton”,如果它被赋为TRUE,bean 就是单件,否则就是一个 prototype bean。默认是TRUE,所以所有在Spring框架中的beans 缺省都是单件。
Spring的内部bean
当一个bean仅被用作另一个bean的属性时,它能被声明为一个内部bean,为了定义inner bean,在Spring 的 基于XML的 配置元数据中,可以在 或 元素内使用 元素,内部bean通常是匿名的,它们的Scope一般是prototype。
如何管理Bean
给Spring 容器配置元数据
Spring容器管理Bean可以通过XML配置文件,也可以用注解,或者基于java的配置。
<?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:util="http://www.springframework.org/schema/util" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.0.xsd"> <!-- 配置名为person的Bean,其实现类是com.afy.spring.beans.Person --> <bean id="person" class="com.afy.spring.beans.Person"> <!--控制调用setAxe()方法,将容器axe Bean作为传入参数--> <property name="axe" ref="axe"></property> </bean> <bean id="axe" class="com.afy.spring.beans.Axe"/> <bean id="date" class="java.util.Date"/> </beans>
该配置文件根源上是< beans…/>,里面包括多个< bean…/>元素,每个< bean…/>元素定义一个Bean。以上配置文件中一共定义3个Bean,其中前两个Bean是Axe和Person类,最后一个是直接使用了JDK提供的java.util.Date和javax.swing.JFrame类。由于Spring可以把“一切Java对象”当成容器中的Bean,所以不管Java类是JDK提供的,还是第三方框架提供的,或者是开发者自己实现的…..只要是个Java类,并将其配置到XML文件中,Spring容器就可以管理它。
配置文件中的< bean…/>元素默认以反射方式调用该类的无参构造器,以下面代码为例:
<bean id="person" class="com.afy.spring.beans.Person">
Spring框架解析该< bean…/>元素后将可以得到idStr和classStr两个字符串,idStr的值为“person”(解析< bean…>元素的id属性得到的值),classStr的值为“com.afy.spring.beans.Person”(解析< bean…/>元素的class属性得到的值)。Spring底层会执行如下格式的代码:
//解析< bean.../>元素的id属性得到的值为“person” String idStr = ...; //解析< bean.../>元素的class属性得到该字符串值为“com.afy.spring.beans.Person” String classStr = ...; Class clazz = Class.forName(classStr); Object obj = clazz.newInstance(); //container代表Spring迭代器 container.put(idStr,obj);
这段代码是基本的反射代码(不是Spring底层所有代码),Spring框架通过反射根据< bean…/>元素的属性指定的类名创建了一个Java对象,并以< bean…/>元素的id属性的值为key,将该对象放入Spring容器中,这个Java对象就称为Spring容器中的Bean。
可以简单地理解为每个< bean…/>元素默认驱动Spring调用该类无参构造器创建实例,并将该实例作为Spring容器中的Bean。
在Spring配置文件中配置Bean时,class属性的值必须是Bean实现类的完整类名(必须带包名),不能是接口或抽象类(除非有特殊配置),否则Spring无法使用反射创建该类的实例。
配置文件中还包含一个< property…/>子元素,< property…/>子元素驱动Spring在底层以反射执行一次setter方法。其中< property…/>的name属性值决定执行哪个setter方法,而value或ref决定执行setter方法的传入参数。
[] 如果传入参数是基本类型及其包装类、Spring等类型,则使用value属性指定传入参数。
[] 如果以容器中其他Bean作为传入参数,则使用ref属性指定传入参数。
Spring只要看到< property…/>子元素,Spring框架就会在底层以反射方式执行一次setter方法,那什么时候执行这个setter方法呢?该Bean一旦创建处理,Spring就会立即根据< property…/>子元素类执行setter方法。也就是说,< bean…/>元素驱动Spring调用无参构造器创建对象;< property…/>子元素驱动Spring执行setter方法,这两步是先后执行的,中间几乎没有任何间隔。如:
<bean id="person" class="com.afy.spring.beans.Person"> <property name="axe" ref="axe"></property> </bean>
< property…/>子元素的name属性值为axe,该元素将驱动Spring以反射方式执行Person Bean的setAxe()方法;ref属性值为axe,该属性值指定以容器中名为axe的Bean作为执行setter方法的传入参数。Spring底层会执行如下格式的代码:
//基本的反射代码 String nameStr = ...;//解析< property.../>元素的name属性得到该字符串值为“axe” String refStr = ...;//解析< property.../>元素的ref属性得到该字符串值为“axe” String setterName = "set"+nameStr.substring(0,1).toUpdateCase()+nameStr.substring(1);//生成将要调用的setter方法 //或去Spring容器中名为refStr的Bean,该Bean会做为传入参数 Object paramBean = container.get(refStr); //此处的clazz是前面一段反射代码通过< bean.../>元素的class属性得到的class对象 Method setter = clazz.getMethod(setterName,paraBean.getBean()); //此处的obj参数是前段反射代码为< bean.../>元素创建的对象 setter.invoke(obj,paramBean);
可以简单地理解为每个< property…/>元素默认驱动Spring调用一次setter方法。
由此可见上面配置3个< bean…/>元素时Spring会一次创建com.afy.spring.beans.Person、com.afy.spring.beans.Axe、java.util.Date这3个类的对象,并把它们当成容器中的Bean。
其中id为Person的< bean…/>元素还包括一个< property…/>子元素,因此Spring会在创建完person Bean之后,立即以容器中id为axe的Bean作为参数调用person Bean的setAxe()方法,这样会导致容器中id为axe的Bean被赋值给person对象的axe实例变量。
定义类的作用域
当定义一个< bean> 在Spring里,我们还能给这个bean声明一个作用域。它可以通过bean 定义中的scope属性来定义。如,当Spring要在需要的时候每次生产一个新的bean实例,bean的scope属性被指定为prototype。另一方面,一个bean每次使用的时候必须返回同一个实例,这个bean的scope 属性 必须设为 singleton。
Spring支持的几种bean的作用域
Spring框架支持以下五种bean的作用域:
singleton : bean在每个Spring ioc 容器中只有一个实例。
prototype:一个bean的定义可以有多个实例。
request:每次http请求都会创建一个bean,该作用域仅在基于web的Spring ApplicationContext情形下有效。
session:在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
global-session:在一个全局的HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效。
缺省的Spring bean 的作用域是Singleton。
Spring框架中bean的生命周期
Spring容器 从XML 文件中读取bean的定义,并实例化bean。
Spring根据bean的定义填充所有的属性。
如果bean实现了BeanNameAware 接口,Spring 传递bean 的ID 到 setBeanName方法。
如果Bean 实现了 BeanFactoryAware 接口, Spring传递beanfactory 给setBeanFactory 方法。
如果有任何与bean相关联的BeanPostProcessors,Spring会在postProcesserBeforeInitialization()方法内调用它们。
如果bean实现IntializingBean了,调用它的afterPropertySet方法,如果bean声明了初始化方法,调用此初始化方法。
如果有BeanPostProcessors 和bean 关联,这些bean的postProcessAfterInitialization() 方法将被调用。
如果bean实现了 DisposableBean,它将调用destroy()方法。
重要的bean生命周期方法
有两个重要的bean 生命周期方法,第一个是setup , 它是在容器加载bean的时候被调用。第二个方法是 teardown 它是在容器卸载类的时候被调用。
The bean 标签有两个重要的属性(init-method和destroy-method)。用它们你可以自己定制初始化和注销方法。它们也有相应的注解(@PostConstruct和@PreDestroy)。
在 Spring中如何注入一个java集合?
Spring提供以下几种集合的配置元素:
< list>类型用于注入一列值,允许有相同的值。
< set> 类型用于注入一组值,不允许有相同的值。
< map> 类型用于注入一组键值对,键和值都可以为任意类型。
< props>类型用于注入一组键值对,键和值都只能为String类型。
Spring容器访问Bean
配置完Bean后要通过Spring容器访问容器中的Bean。
在 Spring IOC 容器读取 Bean 配置创建 Bean 实例之前, 必须对它进行实例化. 只有在容器实例化后, 才可以从 IOC 容器里获取 Bean 实例并使用。
Spring 提供了两种类型的 IOC 容器实现:
1. BeanFactory: IOC 容器的基本实现;
2. ApplicationContext: 提供了更多的高级特性. 是 BeanFactory 的子接口。
BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身;ApplicationContext 面向使用 Spring 框架的开发者,是Spring容器最常用的接口,几乎所有的应用场合都直接使用 ApplicationContext 而非底层的 BeanFactory。该接口下有如下两个实现类:
1. ClassPathXmlApplicationContext:从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器;
2. FileSystemXmlApplicationContext:从文件系统的相对路径或绝对路径下去搜索配置文件,并根据配置文件来创建Sprig容器。
Java项目中,类加载路径是稳定的,因此通常是使用 ClassPathXmlApplicationContext创建Spring容器。
public class BeanTest{ public static void main(String[] args){ //1. 创建 Spring 的 IOC 容器 ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); //2. 从 IOC 容器中获取id为person的Bean Person p = ctx.getBean("person",Person.class) //3. 使用 bean p.useAxe(); } }
Spring容器获取Bean对象主要有如下两个方法:
1. Object getBean(String id):根据容器中Bean的id来获取指定Bean,获取Bean之后需要进行强制类型转换;
2. T getBean(String name,Class requireType):根据容器中Bean的id来获取指定Bean,但该方法带一个泛型参数,因此获取Bean之后无需进行类型转换。
获取Bean(即Java对象)之后,即可以通过对象来调用方法、访问实例变量,像普通使用Java对象一样使用。
相关文章推荐
- JAVA EE的学习路线
- JDK1.7 ImageIO的一个梗
- 为何从ThreadLocal中获得的对象是线程安全的? Java7 Java8
- 【Java】访问控制权限
- [Java视频笔记]day11
- Java问题探讨之String的不可变性
- 轻松搞定java内存模型(二)类的加载以及初始化
- 总结javaweb 目录结构
- Java中用到的一些基本概念
- Spring与Quartz的整合实现定时任务调度
- java文件拷贝类
- 改变myeclipse背景颜色
- 调用第三方api之图灵机器人
- Java应用调优指南之-工具篇
- Java mail学习之邮件基础
- spring和mybatis整合的dao两种开放方式
- JAVA模拟post请求
- java排序之归并排序
- (34)Spring Boot的启动器Starter详解【从零开始学Spring Boot】
- Struts2之Crud综合实例