Spring学习6(4)方法注入,bean之间的关系,多配置文件的整合,bean的作用域

版权声明:本文real_Rickys原创文章,未经real_Rickys允许不得转载。 https://blog.csdn.net/real_Rickys/article/details/83144227

Spring学习6(4)

 在上一篇笔记中述写了spring配置bean的基本格式和方式后,这篇笔记的主要内容是继续了解bean配置的一些进阶的功能和基本概念。

方法注入

 假设Boss配置为单例模式(一个容器中只存在一个实例的bean),如果我们希望每次调用Boss Bean的getCar()方法都能得到一新的car Bean,使用传统的注入就无法实现这样的要求了,因为boss是单例的。
 我们可以使用BeanFactoryAware接口,访问容器的引用,代码如下:

public Car getCar(){
	return (Car)factory.getBean("car");
}

 但是这样的操作会让代码和spring框架绑定,不是特别灵活,所以我们可以利用spring提供的新方法来完成同样的功能。

lookup方法注入

 spring IoC容器利用CGLib包可以拥有复写Bean方法的能力,从而可以为Bean动态创建子类或实现类。
 把car.java放到com.smart.injectfun包下,并且在这个包下创建MagicBoss.java,代码如下:

package com.smart.injectfun;
public interface MagicBoss{
	Car getCar();
}

 下面我们可以不写任何的实现类,仅仅通过配置就为该接口提供动态的实现:

<bean id="car" class="com.smart.injectfun.Car"
p:brand="HongQi" p:price="2000" scope="prototype"/>
<bean id="magicBoss" class="com.smart.injectfun.MagicBoss">
	<lookup-method name="getCar" bean="car"/>
</bean>

 注意每次都是要返回新的carBean,所以Car的scope要为prototype,所以lookup方法注入一般在希望通过一个singleton Bean获取一个prototype Bean时使用。

方法替换

 在spring容器中可以使用某个Bean的方法去替换另一个Bean的方法。
 下面的例子中Boss1的getCar()方法返回一辆宝马Z4:

package com.smart.injectfun;
public class Boss1{
	public Car getCar() {
		Car car = new Car();
		car.setBrand("宝马Z4");
		return car;
	}
}

 在Boss2中实现org.springframework.beans.factory.support.MethodReplacer接口,在接口方法reimplement()中放回一辆美人豹:

package com.smart.injectfun;
import java.lang.reflect.Method;
import org.springframework.beans.factory.support.MethodReplacer;
public class Boss2 implements MethodReplacer{
	public Object reimplement(Object arg0, Method arg1, Object[] arg2)
		throws Throwable{
		Car car = new Car();
		car.setBrand("美人豹");
		return car;
	}
}

 注意用于替换他人的Bean必须是新啊MethodReplacer接口。
 在配置中我们使用如下代码:

<bean id="boss1" class="com.smart.injectfun.Boss1">
	<replaced-method name="getCar" replacer="boss2"/>
</bean>
<bean id="boss2" class="com.smart.injectfun.Boss2"/>

<bean>之间的关系

 不但可以使用<ref>来引用另一个Bean,<bean>标签之间本身亦可以建立类似的关系。

继承

 spring允许当多个<bean>有重复的信息的时候,定义一个父<bean>来简化述写,下面是一个重复读很高,没有使用父<bean>的配置:

<bean id="car1" class="com.smart.tagdepend.Car"
	p:brand="HongQi" p:price="2000" p:color="black"/>
<bean id="car2" class="com.smrt.tagdepend.Car"
	p:brand="HongQi" p:price="2000" p:color="red"/>

 针对上述这种只有color属性不一样的<bean>配置情况,我们使用如下的代码来替代:

<bean id="abstractCar" class="com.smart.tagdepend.Car"
	p:brand="HongQi" p:price="2000" p:color="black" abstract="true"/>
<bean id="car3" p:color="red" parent="abstractCar"/>
<bean id="car4" p:color="green" parent="abstractCar"/>

 注意这里父<bean>要申明是abstract="true"这样就不会实例化为对应的Bean。在子<bean>中提供了父<bean>已有的配置信息将覆盖父<bean>中的配置。

依赖

 一般情况下,可以使用<<ef>提供依赖,但是有时候Bean之间的依赖关系不是那么明显。
 如一个系统在开启时会配置基础的环境信息,但是参数会随着环境演进而变化,我们需要对其进行定时存储,但是每次存储时我们去读取的是配置的信息,而没有去读取是否发生参数的改变,所以其中存在着隐形的依赖,即是只有更改过了参数刷新才有效。

<bean id="sysfresh" class="com.smart.tagdepend.SysInit"/>
<bean id="manager" class="com.smart.tagdepend.CacheManager" depends-on="sysfresh"/>

引用

 假设一个<bean>要引用另一个<bean>的id属性值(一般是用来在运行时使用getBean(beanName)方法来获取对应的Bean,并且要有引用关系,我们可以通过下面的代码来实现:

<bean id="boss" class="com.smart.tagdepend.Boss">
	<property name="carId">
		<idref bean="car"/>
	</property>
</bean>

整合多个配置文件

 对于一个大型应用程序来说可能存在多个配置文件,spring提供了一种<import>元素标签将多个配置文件引入到一个文件中,进行配置文件继承,这样在spring加载的时候就只要指定这个合并好的文件即可。

<import resource="classpath:com/smart/impt/beans1.xml/>
<import resource="classpath:com/smart/impt/beans2.xml/>

 需要注意的是如果一个配置文件引用了其他配置文件的<bean>,是不用import的,只需要将这两个配置文件都放入配置文件列表即可。

Bean作用域

 用户不但可以在配置文件中配置Bean的属性和相互之间的关系,还可以控制作用域。下面是预定义的5中定义域:

  1. singleton:在容器中仅存在一个Bean实例。
  2. prototype:每次使用getBean()都会返回一个新的实例。
  3. request:每次Http请求都会创建一个新的Bean,该作用域适用于WebApplicationContext环境。
  4. session:同一个Http session共享一个Bean,仅使用于WebApplicationContext环境。
  5. globalSession:同一个全局Session共享一个Bean,一般用于portlet应用环境,仅适用于WebApplicationContext环境。

singleton作用域

 如下列一行配置代码,其意义是如图所示:

<bean id="car" class="com.smart.scope.Car" scope="singleton" />
<bean id="boss1" class="com.smart.scope.Boss" p:car-ref="car"/>
<bean id="boss2" class="com.smart.scope.Boss" p:car-ref="car"/>
<bean id="boss3" class="com.smart.scope.Boss" p:car-ref="car"/>

 结构如下:
在这里插入图片描述

prototype 作用域

 代码的结构和容器的结构如下:

<bean id="car" class="com.smart.scope.Car" scope="prototype" />
<bean id="boss1" class="com.smart.scope.Boss" p:car-ref="car"/>
<bean id="boss2" class="com.smart.scope.Boss" p:car-ref="car"/>
<bean id="boss3" class="com.smart.scope.Boss" p:car-ref="car"/>

在这里插入图片描述

与Web相关的Bean作用域

 在使用WebApplicationContext,使用与web有关的bean作用域需要进行一些额外的配置。我们在web.xml中为http请求配置“驱动”。
 同第四章配置contextLoaderListener,这里也有两种配置方法,首先是通过过滤器:

	<filter>
		<filter-name>requestContextFilter</filter-name>
		<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>requestContextFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>

 或者通过http请求监听器:

<listener>
		<listener-class>
			org.springframework.web.context.request.RequestContextListener
		</listener-class>
	</listener>

 完成了上述的配置后,就可以对bean进行配置。

request:

<bean id="car" class="com.smart.scope.Car" scope="request" />
 每次http请求调用car Bean时spring都会创建新的car,处理完毕后会销毁这个bean。

session:

<bean id="car" class="com.smart.scope.Car" scope="session" />
 其横跨整个session,只有http session结束后,实例才被销毁。

globalSession:

<bean id="car" class="com.smart.scope.Car" scope="globalSession" />
&emsp;仅在portlet的web应用中使用,如果不是,则相当于session。

web中的bean的依赖

 在web中相关作用域的Bean注入singleton或prototype中,需要额外的配置即是需要用Aop来设置代理,而不能直接引用。
 下面是一个非webBean引用webBean的实例代码:

<?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"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans-4.0.xsd
	http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop
	/spring-aop-4.0.xsd
	">
	
<bean id="car" class="com.smart.scope.Car" scope="request" />
<bean id="boss1" class="com.smart.scope.Boss" p:car-ref="car"/>
<bean id="boss2" class="com.smart.scope.Boss" p:car-ref="car"/>
<bean id="boss3" class="com.smart.scope.Boss" p:car-ref="car"/>
<bean name="car" class="com.smart.scope.Car" scope="request">
	<aop:scoped-proxy/>
</bean>
<bean id="boss" class="com.smart.scope.Boss">
	<property name="car" ref="car"/>
</bean>
</beans>

 这里car Bean是request作用域,为了能够被singleton引用,需要用aop配置一个代理类,aop会判断car Bean定位于那个Http请求线程中,并从对应的http请求线程获取对应car Bean。并且这里Boss是singleton作用域,所以每次调用carBean都会创建一个car,但是通过aop可以让boss每次引用都对应到http请求的car Bean中。

猜你喜欢

转载自blog.csdn.net/real_Rickys/article/details/83144227
今日推荐