Spring Bean的作用域以及lookup-method标签的使用

Spring Framework支持五种作用域,如下图所示:


singleton:表示一个容器中只会存在一个bean实例,无论在多少个其他bean里面依赖singleton bean,整个容器都只会存在一个实例。相当于是容器的全局变量。

prototype:一个容器中可能会存在多个bean实例,prototype bean的实例产生有两种情况,一种是其他bean请求依赖prototype 容器会为其他bean分别创建一个实例。另外一种就是通过ApplicationContextAware 接口的 getBean方法获取 bean的时候 容器也会创建一个新的实例。

request:这个不用多说,即容器会为每一个HTTP请求都会创建一个实例。

session:容器会为每个session创建一个bean实例


那么问题来了,由于bean的作用域不同,其实例创建的时间也不会相同,如果程序中存在一个 singleton bean 依赖了一个 request bean ,直接通过 @Autowired注解项目在启动的时候会报错的,如何解决这个问题呢?Spring 提供了lookup-method方法来解决这个问题。下面来看一个例子:

1 首先新建一个User类

public class User {
	
	private String name;
	
	private String password;

	private int age;
	//省略setter 和 getter
}
2 将这个User类注册成为 request 作用域的bean 在springContext.xml文件中

<bean id="user" class="com.zsq.cn.login.entity.User" scope="request">
		<property name="name" value="zsq" />
	</bean>
3 新建一个controller

@Controller
public class LoginController extends BaseException{
	@Autowired
	private LookupMethodService lookupMethodService;
	
	@RequestMapping("/")
	public String home(Model model){
		User user = lookupMethodService.getUser();
		System.out.println(user.toString());
		return "home/index";
	}
}
4 新建一个service 以及其实现类

public interface LookupMethodService {

	User getUser();
}

@Service
public abstract class LookupMethodServiceImpl implements LookupMethodService {

	@Override
	public User getUser() {
		return creatUser();
	}
	
	public abstract User creatUser();
}

5 在springContext.xml文件中配置

<bean id="lookupMethodServiceImpl" class="com.zsq.cn.login.service.impl.LookupMethodServiceImpl">
		<lookup-method name="creatUser" bean="user" />
	</bean>


通过5 的配置 4中的抽象方法 createUser将返回2中bean定义的一个新的实例。

每次通过1 的请求时容器都会创建一个name=“”zsq“”的新实例。

当然spring提供了一种更加简单的方式来处理作用域不一样时属性注入的问题。

即使用@Scope标签的proxyMode属性。比如我要将一个Student注册为作用域为session的bean,并在单实例的loginController中注入。

1 首先建立一个

@Component
@Scope(value="session",proxyMode=ScopedProxyMode.TARGET_CLASS)
//如果Student是一个类,并没有实现任何接口,那么将proxyMode设置为ScopedProxyMode.TARGET_CLASS,将采用CGLIB代理,
//如果Student实现了一个接口,那么可以将proxyMode设置为ScopedProxyMode.INTERFACES,将采用JDK的动态代理,
public class Student {

	private String name;

	private int age;

	//省略setter、getter
}

如果要在xml文件中实现这一步可以在springContext.xml文件中注入

<bean id="student" calss="com.zsq.cn.login.entity.Student" scope="session">
	<property name="name">zsq</property>
	<property name="age">22</property>
	//下面两个二选一
	<aop:scoped-proxy />//如果Student是一个类,并没有实现任何接口这样配置将采用CGLIB代	
	<aop:scoped-proxy proxy-target-class="false" />//如果Student实现了一个接口,这样配置将采用JDK动态代理	
	</bean>

2 在loginController中注入student

	@Autowired
	private Student student;


	@RequestMapping("/")
	public String home(Model model){
		model.addAttribute("user", new User());

		student.setAge(22);

		return "home/index";
	}




















  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当然,除了使用注解方式,我们还可以使用XML配置来实现Spring Lookup Method。下面是一个使用XML配置的示例: 首先,定义一个抽象类: ``` public abstract class AbstractBean { public void doSomething() { getDependency().execute(); } public abstract Dependency getDependency(); } ``` 接下来,定义一个具体的子类: ``` public class ConcreteBean extends AbstractBean { private Dependency dependency; @Override public Dependency getDependency() { if (dependency == null) { dependency = createDependency(); } return dependency; } protected Dependency createDependency() { // 返回一个新的Dependency对象 } } ``` 注意到这里的`createDependency()`方法没有被`@Lookup`注解标记,这是因为我们将会在XML中配置这个方法。 接下来,我们需要在XML中配置这个类: ``` <bean id="concreteBean" class="com.example.ConcreteBean"> <lookup-method name="createDependency" bean="dependency"/> </bean> <bean id="dependency" class="com.example.Dependency"/> ``` 注意到这里的`lookup-method`元素,它告诉Spring在运行时为`createDependency()`方法生成一个代理,并将其返回值注入到`ConcreteBean`对象中。 现在,我们可以在其他类中注入`concreteBean`对象,并调用它的`doSomething()`方法,它将会使用`ConcreteBean`中的`createDependency()`方法来获取一个新的`Dependency`对象,并执行它的`execute()`方法。 这就是使用XML配置的Spring Lookup Method的一个简单示例。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值