`
Breese
  • 浏览: 61618 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

spring 方法注入中的一些注意事项

 
阅读更多
在大部分情况下,容器中的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生命周期。)


分享到:
评论

相关推荐

    Spring中文帮助文档

    在应用服务器中使用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 ...

    spring通过构造函数注入实现方法分析

    主要介绍了spring通过构造函数注入实现方法,结合实例形式分析了spring通过构造函数注入的原理、实现步骤及相关操作注意事项,需要的朋友可以参考下

    高级开发spring面试题和答案.pdf

    事务注意事项; 为什么同一个类A调用b方法事务,A方法一定要有事务(编码式的不用) @transaction多个数据源事务怎么指定数据源 传播特性有几种?7种; 某一个事务嵌套另一个事务的时候怎么办? REQUIRED_NEW和...

    Spring API

    在应用服务器中使用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 ...

    spring依赖注入原理与用法实例分析

    主要介绍了spring依赖注入原理与用法,结合实例形式分析了spring框架依赖注入的概念、原理、用法案例及相关操作注意事项,需要的朋友可以参考下

    spring多数据源配置实现方法实例分析

    主要介绍了spring多数据源配置实现方法,结合实例形式分析了spring多数据源配置相关操作技巧与使用注意事项,需要的朋友可以参考下

    springmybatis

    MyBatis 目录(?)[-] mybatis实战教程mybatis in action之一开发环境搭建 mybatis实战教程mybatis in action之二以接口的方式编程 mybatis实战教程mybatis in action之...在 IUserOperation 接口中增加方法:public List...

    springboot参考指南

    Spring Beans和依赖注入 vi. 18. 使用@SpringBootApplication注解 vii. 19. 运行应用程序 i. 19.1. 从IDE中运行 ii. 19.2. 作为一个打包后的应用运行 iii. 19.3. 使用Maven插件运行 iv. 19.4. 使用Gradle插件运行 v...

    MyBatis 需要注意的地方junit注解

    3.mybatis的注意事项 1.xml中的sql不得有分号 2.sql语句操作的表明和列名 3.xml中的小于号:$lt;大于号¥&gt; 4.取变量时,如果dao层接口使用的是@param("别名")注解,则根据别名取值 5.mapper.xml中$和#取值的区别 ...

    基于java SSM框架实现物流配货项目设计源码和文档

    操作注意事项 本系统的后台用户名为:mr,密码为:mrsoft 操作流程 (1)用户登录系统后,可通过首页中的“修改密码”超链接,对用户密码进行修改。 (2)通过首页中的“固定客户管理”超链接,可进入客户管理页面。...

    基于java SSM框架实现物流配货项目设计源码和文档分享

    操作注意事项 本系统的后台用户名为:mr,密码为:mrsoft 操作流程 (1)用户登录系统后,可通过首页中的“修改密码”超链接,对用户密码进行修改。 (2)通过首页中的“固定客户管理”超链接,可进入客户管理页面。...

    基于javaWeb实现网上淘书吧项目设计源码和文档分享

    操作注意事项 本系统的后台用户名为:mr,密码为:mingrisoft 操作流程 (1)本系统分为前后台管理。前台主要包括图书展台、网上调查、购物车、收银台、会员管理、订单查询等内容。 (2)用户登录系统后,可进入系统...

    基于javaWeb实现网上淘书吧项目设计源码和文档

    操作注意事项 本系统的后台用户名为:mr,密码为:mingrisoft 操作流程 (1)本系统分为前后台管理。前台主要包括图书展台、网上调查、购物车、收银台、会员管理、订单查询等内容。 (2)用户登录系统后,可进入系统...

    基于java SSM框架实现华奥汽车销售集团网项目设计源码分享

    操作注意事项 本系统的后台用户名为:mr,密码为:mrsoft 操作流程 (1)本系统分为前后台管理,其中前台包括车辆信息查询、新闻查看、备件信息查询、连锁企业查看、集团信息浏览、集团服务投诉等内容。 (2)登录...

    基于java SSM框架实现华奥汽车销售集团网项目设计源码

    操作注意事项 本系统的后台用户名为:mr,密码为:mrsoft 操作流程 (1)本系统分为前后台管理,其中前台包括车辆信息查询、新闻查看、备件信息查询、连锁企业查看、集团信息浏览、集团服务投诉等内容。 (2)登录...

    基于java SSM框架实现都市供求信息网项目设计源码和文档分享

    操作注意事项 本系统的后台用户名为:mr,密码为:mrsoft 操作流程 (1)访客访问本站,即可浏览各种信息,如“招聘信息”、“房屋信息”、“求购信息”等,这些信息都提供了关键字查询,方便用户操作。 (2)通过...

    基于java SSM框架实现都市供求信息网项目设计源码和文档

    操作注意事项 本系统的后台用户名为:mr,密码为:mrsoft 操作流程 (1)访客访问本站,即可浏览各种信息,如“招聘信息”、“房屋信息”、“求购信息”等,这些信息都提供了关键字查询,方便用户操作。 (2)通过...

    Java毕业设计-基于ssm框架开发的Vue戒烟网站--论文-附毕设源代码+说明文档.rar

    最后,项目还附带了说明文档,对项目的使用方法、注意事项等进行了详细说明。这份文档对于初学者来说非常友好,能够帮助他们快速上手项目并进行二次开发定制。 总的来说,本资源是一个集前端展示、后端处理、论文...

    基于SSM的大学生校园图书角管理系统(源码+部署说明+演示视频).zip

    通过观看视频,用户可以更直观地了解系统的使用方法和注意事项。 总之,这个基于SSM的大学生校园图书角管理系统是一个实用的Web应用程序,可以帮助学校图书馆更好地管理图书资源。项目提供了完整的源代码、部署说明...

Global site tag (gtag.js) - Google Analytics