【62】Spring总结之bean(3)
2016-06-22 21:16
351 查看
Spring核心机制:依赖注入
Java应用(从applets的小范围到全套n层服务端企业应用)是一种典型的依赖型应用,它就是由一些互相适当地协作的对象构成的。因此,我们说这些对象间存在依赖关系。加入A组件调用了B组件的方法,我们就可以称A组件依赖于B组件。我们通过使用依赖注入,Java EE应用中的各种组件不需要以硬编码方式耦合在一起,甚至无需使用工厂模式。当某个Java 实例需要其他Java 实例时,系统自动提供所需要的实例,无需程序显示获取,这种自动提供java实例我们谓之为依赖注入,也可以称之为控制反转(Inversion of Control IoC)。依赖注入通常有如下两种:
设置注入:IoC容器使用属性的setter方法来注入被依赖的实例。构造注入:IoC容器使用构造器来注入被依赖的实例。
设值注入
2 3 4 5 6 7 8 9 10 11 12 13 14 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 配置Chinese实例,其实现类是Chinese --> <bean id="chinese" class="com.spring.service.impl.Chinese"> <!-- 将StoneAxe注入给axe属性 --> <property name="axe" ref="stoneAxe" /> <property name="name" value="孙悟空"/> </bean> <!-- 配置stoneAxe实例 --> <bean id="stoneAxe" class="com.spring.service.impl.StoneAxe" /> </beans>
id:指定该Bean的唯一标识,程序会通过id属性值来访问该Bean实例。
class:指定该Bean的实现类,此处不可再用接口,必须是实现类,Spring容器会使用XML解析器读取该属性值,并利用反射来创建该实现类的实例。
从上面可以看出Bean于Bean之间的依赖关系放在配置文件里组织,而不是写在代码里。通过配置文件的指定,Spring能够精确地为每个Bean注入属性。因此,配置文件里的
构造注入
2 3 4 5 6 7 8 9 10 11 12 13 <?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 配置Chinese实例 --> <bean id="chinese" class="com.spring.service.impl.Chinese"> <!-- 使用构造注入,为Japanese实例注入SteelAxe实例--> <constructor-arg ref="stoneAxe"/> </bean> <!-- 配置stoneAxe实例 --> <bean id="stoneAxe" class="com.spring.service.impl.StoneAxe" /> </beans>
两种注入方式的对比
Spring支持两种依赖注入方式,这两种依赖注入方式并没有好坏之分,只是适合的场景有所不同。
设值注入有如下优点:
与传统的JavaBean的写法更相似,程序开发人员更加容易理解,接受。通过setter方法设定依赖关系显得更加直观、自然。对于复杂的依赖关系,如果采用构造注入,会导致构造器过于臃肿,难以阅读。Spring在创建Bean实例时,需要同时实例化其依赖的全部实例,因此导致性能下降。而设值注入,则可以避免这些问题。
尤其是在某些属性可选的情况下,多参数的构造器更加笨重。
但是构造器也有如下优势:
构造注入可以再构造器中决定依赖关系的注入顺序,优先依赖的优先注入。
对于依赖关系无须变化的Bean,构造注入更有用处。
因为没有setter方法,所有的依赖关系全部在构造器中设定,因此,无须担心后续的代码对依赖关系产生破坏。依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完全透明,更加符合高内聚的原则。
Spring会自动接管每个
创建bean的集中方式
1.最简单的声明 Bean
简单的 Bean 是由 标签包裹,其中两个属性:id 的作用是作为 Bean 的唯一标识,以后使用 Bean 的时候就使用 id 后面的名字即可;
class 的作用是作为制定该 Bean 的实现类,运行中 Spring 会 new 该实现类的对象,因此 class 必须指向实现类,而非其他接口等。
2.通过构造器声明
<bean id="HelloWorld" class="com.hundsun.spring.HelloWorld"> <constructor-arg value="TOM"></constructor-arg> </bean>
与简单声明 Bean 方法有所区别的是, 标签中增加了一个 标签,此标签中有 value 属性。多出的这个 constructor-arg 标签的作用就是为了填充目标实现类中含有参数的构造器中的参数。
3.通过工厂方法创建 Bean
工厂方法创建 Bean 的方法适用于单例类实例,即实例中只含有静态方法。例如代码
<bean id="staticFunction" class="com.hundsun.spring.StaticHello" factory-bean="HelloWorld"></bean>
相对简单方法,多出来一个 factory-bean 的属性,该属性指向的就是 StaticHello 实现类中 HelloWorld 静态方法。
4.使用 Set 方法注入 Bean 属性
要为创建 Bean 的实现类中的私有属性注入值,需要使用 Set 方法注入,简单安全。要实现 set 方法注入 Bean 要做这样的步骤
1.在实现类中为目标私有属性生成 set 方法。2.在构造 Bean 的 XML 文件中增加
例如代码
<bean id="demo" class="com.hundsun.spring.HelloWorld"> <property name="message" value="你好"></property> </bean>
对应的 name 属性指的是 HelloWorld 实现类中 message 的私有属性,并且将 value 属性中的“你好”注入给 message。这个时候你若输出 message ,则会输出汉字“你好”。但是前提是你一定一定要在实现类中生成好 setMessage() 方法。
同样的,你可以给 Bean 属性赋值已有的其他 Bean,如代码所示。
<!-- 事先声明好的person的bean --> <bean id="Sam" class="com.hundsun.spring.entity.Person"></bean> <bean id="demo" class="com.hundsun.spring.HelloWorld"> <property name="message" value="你好"></property> <property name="person" ref="Sam"></property> </bean>
一个 id 名为 Sam 的 Bean 被一个 id 为 demo 的 Bean 引用,关键属性为 ref ,ref 直接指向了已有的 Bean。
假设我只希望名为 Sam 的 Bean 被 demo 引用,我可以使用注入内部 Bean,只需将上述代码修改为这样:
<bean id="demo" class="com.hundsun.spring.HelloWorld"> <property name="message" value="你好"></property> <property name="person"> <bean id="Sam" class="com.hundsun.spring.entity.Person"></bean> </property> </bean>
让Bean获取Spring容器
实现BeanFactoryAware接口的Bean,拥有访问的BeanFactory容器的能力,实现BeanFactoryAware接口的Bean实例将会拥有对容器的访问能力。BeanFactoryAware接口仅有如下一个方法:2 3 4 5 6 7 8 9 10 11 12 13 14 public class Chinese implements ApplicationContextAware{ //将BeanFactory容器以成员变量保存 private ApplicationContext ctx; /** * 实现ApplicationContextAware接口实现的方法 */ public void setApplicationContext(ApplicationContext cyx) throws BeansException { this.ctx = ctx; } //获取ApplicationContext的测试方法 public ApplicationContext getContext(){ return ctx; } }
2 3 4 5 6 7 8 9 10 11 12 13 14 public class Chinese implements ApplicationContextAware{ //将BeanFactory容器以成员变量保存 private ApplicationContext ctx; /** * 实现ApplicationContextAware接口实现的方法 */ public void setApplicationContext(ApplicationContext cyx) throws BeansException { this.ctx = ctx; } //获取ApplicationContext的测试方法 public ApplicationContext getContext(){ return ctx; } }
Bean的基本定义
default-lazy-init :延迟初始化default-merge:merge行为
default-autowire:自动装配行为
default-autowire-candidates:自动装配候选bean
default-init-method:初始化方法
default-destroy-method:回收方法
list、set、map、props
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.springframework.org/schema/beans" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd"> <!-- 定义一个普通的Axe Bean --> <bean id="steelAxe" class="com.spring.service.impl.SteelAxe" /> <bean id="stoneAxe" class="com.spring.service.impl.StoneAxe" /> <!--定义Chinese Bean --> <bean id="chinese" class="com.spring.service.impl.Chinese"> <property name="schools"> <list> <value>小学</value> <value>中学</value> <value>大学</value> </list> </property> <property name="scores"> <map> <entry key="语文" value="88" /> <entry key="数学" value="87" /> <entry key="外语" value="88" /> </map> </property> <property name="phaseAxes"> <map> <entry key="原始社会" value-ref="stoneAxe" /> <entry key="农业社会" value-ref="steelAxe" /> </map> </property> <property name="health"> <props> <prop key="血压">正常</prop> <prop key="身高">175</prop> </props> </property> <property name="axe"> <set> <value>普通字符串</value> <bean class="com.spring.service.impl.SteelAxe"></bean> <ref local="stoneAxe"/> </set> </property> <property name="books"> <list> <value>java 编程思想</value> <value>思考致富</value> <value>将才</value> </list> </property> </bean> </beans>
从上面的配置文件中可以看出,Spring对list属性和数组属性的处理是一样的。
当我们使用
所以这些元素又可以接受如下子元素:
value:指定集合元素是基本数据类型或者字符类型值。ref:指定集合元素师容器中另一个Bean实例。
bean:指定集合元素是一个嵌套Bean。
list、set、map、props:指定集合元素值又是集合。
使用
Bean 的作用域
标签中的 scope 属性,该属性作用是控制 Bean 的作用域,默认情况下,Bean 是单例,即如果创建,如果被再次使用的话不会创建新的,而取之前创建过的 Bean 使用,如果想要每次都创建新的实例,则需要修改 scope 属性。
scope 属性值有:singleton 一个 Bean 只有一个对象(默认)
prototype 每次都被重新创建一个实例
request 在一次 HTTP 请求中有效
session 在一次对话中有效
global-session 在整个 HTTP 请求中有效
初始化和销毁 Bean
两个属性:init-method=””
在初始化 Bean 时执行实例中的某个方法。
destory-method=””
在 Bean 销毁时执行实例中的某个方法。
如果希望设置默认初始化和销毁方法的话,可以在文件头部标签中增加两个属性:
default-init-method=””
default-destory-method=”“
我的微信二维码如下,欢迎交流讨论
欢迎关注《IT面试题汇总》微信订阅号。每天推送经典面试题和面试心得技巧,都是干货!
微信订阅号二维码如下:
参考:
http://howiefh.github.io/2015/03/06/spring-note-1/
http://www.yelook.com/1637.html
相关文章推荐
- 一个jar包里的网站
- 一个jar包里的网站之文件上传
- 一个jar包里的网站之返回对媒体类型
- Spring和ThreadLocal
- Spring Boot 开发微服务
- Spring AOP动态代理-切面
- Spring整合Quartz(JobDetailBean方式)
- Spring整合Quartz(JobDetailBean方式)
- 模拟Spring的简单实现
- Spring整合WebSocket应用示例(上)
- spring+html5实现安全传输随机数字密码键盘
- Spring中属性注入详解
- 监听器获取Spring配置文件的方法
- Java利用Sping框架编写RPC远程过程调用服务的教程
- springmvc 发送ajax出现中文乱码的解决方法汇总
- SpringMVC框架下JQuery传递并解析Json格式的数据是如何实现的
- 详解Java的MyBatis框架和Spring框架的整合运用
- struts2 spring整合fieldError问题
- spring的jdbctemplate的crud的基类dao