在大部分情况下,容器中的bean都是singleton类型的。如果一个singleton bean要引用另外一个singleton bean,或者一个非singleton bean要引用另外一个非singleton bean时,通常情况下将一个bean定义为另一个bean的property值就可以了。不过对于具有不同生命周期的bean来说这样做就会有问题了,比如在调用一个singleton类型bean A的某个方法时,需要引用另一个非singleton(prototype)类型的bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的的bean B实例。
上述问题的一个解决办法就是放弃控制反转。通过实现BeanFactoryAware接口(见这里)让bean A能够感知bean 容器,并且在需要的时候通过使用getBean("B")方式(见这里)向容器请求一个新的bean B实例。看下下面这个例子,其中故意使用了这种方法:
// a class that uses a stateful Command-style class to perform some processing
package fiona.apple;
// lots of Spring-API imports
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
public class CommandManager implements BeanFactoryAware {
private BeanFactory beanFactory;
public Object process(Map commandState) {
// grab a new instance of the appropriate Command
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
// the Command returned here could be an implementation that executes asynchronously, or whatever
protected Command createCommand() {
return (Command) this.beanFactory.getBean("command"); // notice the Spring API dependency
}
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = beanFactory;
}
}
上面的例子显然不是最好的,因为业务代码和Spring Framework产生了耦合。方法注入,作为Spring IoC容器的一种高级特性,可以以一种干净的方法来处理这种情况。
3.3.7.1. Lookup方法注入
这究竟是不是方法注入……
有点像Tapestry 4.0的页面,写上abstract属性,Tapestry会在运行时用具体实现将其覆盖。
在这篇Blog文章中你可以了解更过关于方法注入动机的内容。
Lookup方法注入利用了容器的覆盖受容器管理的bean方法的能力,从而返回指定名字的bean实例。在上述场景中,Lookup方法注入适用于原型bean。Lookup方法注入的内部机制是Spring利用了CGLIB库在运行时生成二进制代码功能,通过动态创建Lookup方法bean的子类而达到复写Lookup方法的目的。
如果你看下上个代码段中的代码(CommandManager类),Spring容器动态覆盖了createCommand()方法的实现。你的CommandManager类不会有一点对Spring的依赖,在下面这个例子中也是一样的:
package fiona.apple;
// no more Spring imports!
public abstract class CommandManager {
public Object process(Object commandState) {
// grab a new instance of the appropriate Command interface
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
}
在包含被注入方法的客户类中(此处是CommandManager),此方法的定义必须按以下形式进行:
<public|protected> [abstract] <return-type> theMethodName(no-arguments);
如果方法是抽象的,动态生成的子类会实现该方法。否则,动态生成的子类会覆盖类里的具体方法。让我们来看个例子:
<!-- a stateful bean deployed as a prototype (non-singleton) -->
<bean id="command" class="fiona.apple.AsyncCommand" scope="prototype">
<!-- inject dependencies here as required -->
</bean>
<!-- commandProcessor uses statefulCommandHelper -->
<bean id="commandManager" class="fiona.apple.CommandManager">
<lookup-method name="createCommand" bean="command"/>
</bean>
在上面的例子中,标识为commandManager的bean在需要一个新的command bean实例时,会调用createCommand方法。重要的一点是,必须将command部署为prototype。当然也可以指定为singleton,如果是这样的话,那么每次将返回相同的command bean实例!
请注意,为了让这个动态子类得以正常工作,需要把CGLIB的jar文件放在classpath里。另外,Spring容器要子类化的类不能是final的,要覆盖的方法也不能是final的。同样的,要测试一个包含抽象方法的类也稍微有些不同,你需要自己编写它的子类提供该抽象方法的桩实现。最后,作为方法注入目标的bean不能是序列化的(serialized)。
提示
有兴趣的读者也许已经发现ServiceLocatorFactoryBean(在org.springframework.beans.factory.config包里)的用法和ObjectFactoryCreatingFactoryBean的有些相似,不同的是它允许你指定自己的lookup接口,不一定非要用Spring的lookup接口,比如ObjectFactory。要详细了解这种方法请参考ServiceLocatorFactoryBean的Javadocs(它的确减少了对Spring的耦合)。
注:对于prototype作用域的bean,有一点非常重要,那就是Spring不能对一个prototype bean的整个生命周期负责:容器在初始化、配置、装饰或者是装配完一个prototype实例后,将它交给客户端,随后就对该prototype实例不闻不问了。不管何种作用域,容器都会调用所有对象的初始化生命周期回调方法。但对prototype而言,任何配置好的析构生命周期回调方法都将不会被调用。清除prototype作用域的对象并释放任何prototype bean所持有的昂贵资源,都是客户端代码的职责。(让Spring容器释放被prototype作用域bean占用资源的一种可行方式是,通过使用bean的后置处理器,该处理器持有要被清除的bean的引用。)
谈及prototype作用域的bean时,在某些方面你可以将Spring容器的角色看作是Java new操作的替代者。任何迟于该时间点的生命周期事宜都得交由客户端来处理。(在第 3.5.1 节 “生命周期回调”一节中会进一步讲述Spring容器中的bean生命周期。)
分享到:
相关推荐
四、注解注入的注意事项 - 当使用`@Autowired`时,如果找不到匹配的bean,Spring会抛出异常。为了避免这种情况,可以使用`@Autowired`的`required`属性设置为`false`,允许字段或方法为空。 - 如果多个bean满足注入...
对于Spring的文档,可能会涉及如何打开CHM(Compiled HTML Help)文件,以及阅读PDF文档时需要注意的事项。 `Spring3.2中文版.pdf`是Spring 3.2版本的中文文档,此版本进一步优化了对Java EE 6的支持,增强了数据...
本篇文章将深入探讨Spring注解的一些注意事项以及值的接收与传递的不同方式。 首先,我们来了解一下Spring中的主要注解。@Component、@Service、@Repository和@Controller分别用于标记普通bean、业务层bean、数据...
3. **Spring注入Bean到Job**:在Job执行时,我们可以直接注入其他由Spring管理的Bean,无需在Job中创建这些对象,从而减少了代码的复杂性,增强了可重用性。 4. **JobFactory的自定义**:Quartz默认使用...
标题中的"Spring注入map共2页.pdf.zip"指的是一个关于Spring框架中Map注入的教程文档,被压缩成PDF格式,并且包含两页内容。描述与标签的信息似乎有误,只给出了部分文件名,但我们可以根据标题来深入探讨Spring框架...
- **注意事项:**使用工厂方法时,Spring容器无法自动检测Bean的类型,因此在进行类型匹配或依赖注入时,需要明确指定Bean的类型。另外,如果工厂方法抛出异常,Spring容器会捕获并处理,导致Bean无法正常创建。 4...
本文将详细介绍如何在Spring Boot中创建线程池并配置`@Async`,以及需要注意的一些事项。 首先,我们需要在Spring Boot的主程序类上添加`@EnableAsync`注解,以启用异步方法的支持。例如: ```java import org....
五、最佳实践与注意事项 1. 避免过度依赖:虽然DI能够简化代码,但过度依赖Spring管理可能导致系统过于复杂,影响性能。合理设计Bean的依赖关系,避免循环依赖。 2. 使用接口而非实现类:在注入依赖时,尽量注入...
文档中提到的“Spring+MVC中文教程pdf”是一份专注于Spring MVC的学习资料,其内容涵盖了Spring MVC注解的使用方法以及在使用过程中需要注意的事项。文档中还提到了“持久层”内容的补充,暗示该教程可能涉及了数据...
### SSH注意事项:整合Spring与Hibernate #### 1. Spring中的Bean注入与配置 在Spring框架中,Bean的注入是其核心特性之一。例如,在`LoginAction`类中,开发者需正确声明和注入`UserDAO`接口的实现类。这通常通过...
**十二、其他注意事项** Spring有多个核心模块,如Core Container、Data Access/Integration、Web等,理解这些模块的功能有助于更好地使用Spring。此外,表单的action属性设置,以及SSH项目重构的步骤也是开发中需要...
5. **注意事项** - 在Spring中,确保配置了正确的事务管理器类型,对于MyBatis通常是`org.springframework.jdbc.datasource.DataSourceTransactionManager`。 - MyBatis的SqlSession应该在Spring的事务边界内使用...
5. 注意事项: - 避免直接在Service层中使用SqlSession,应依赖注入Mapper接口,由MyBatis-Spring管理SqlSession生命周期。 - 确保配置的Mapper接口和XML配置文件匹配,否则可能导致无法找到映射的方法。 - 在多...
"尚学堂Spring学习笔记" 本文档记录了尚学堂Spring学习笔记的重要知识点,涵盖了Spring...此外,本文档还记录了@Autowried、@Resource、@Component、@Repository、@Service、@Controller等注解的使用方式和注意事项。
* 注意事项: + 同一个 xml 文件中不能出现相同名称的 bean + 多个 xml 文件可以出现相同名称的 bean,后导入的配置的会覆盖前面的配置 + name:可以指定 bean 的名称,多个值可以使用逗号分隔 基于注解的配置 ...
在应用服务器中使用Hibernate的注意事项 12.3. JDO 12.3.1. 建立PersistenceManagerFactory 12.3.2. JdoTemplate和JdoDaoSupport 12.3.3. 基于原生的JDO API实现DAO 12.3.4. 事务管理 12.3.5. JdoDialect ...
整个文档中还提到了一些注意事项和版权声明,比如文档仅限个人使用或分发给其他用户,禁止收取费用。文档的翻译者为南磊,并感谢了对项目做出贡献的各位。 通过以上分析,我们可以看出MyBatis-Spring整合为Java...
4. **注意事项**: - 确保所有必需的库和配置都正确无误。 - Spring配置文件中的Bean定义与Struts2配置文件中的Action名称需对应。 - 考虑到性能影响,适当调整Spring的缓存策略和加载时机。 综上所述,Struts2...
ORM和数据访问章节介绍了如何在Spring框架中集成对象关系映射(ORM)工具,例如Hibernate和JPA,以及如何处理与ORM集成相关的注意事项。 视图技术章节涵盖了Spring对视图技术的支持,如Thymeleaf、FreeMarker、JSP...