`
xplq
  • 浏览: 90040 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

Lookup方法之处理遗留代码

阅读更多
“Lookup方法”可以使Spring替换一个bean原有的,获取其它对象具体的方法,并自动返回在容器中的查找结果。
其实,Lookup方法的工作机制是在不修改原系统代码的情况下,可以轻易的换成别的类型相容的对象而不会影响原系统。Spring是使用CGLIB在字节码级别动态实现出Bean的子类,并重写指定方法的方式来实现这个神奇的功能的。
这个是CGLIG动态生成的类,而不是原来的Bean的实例。所以请记住在任何时候只要定义了一个Bean的Lookup方法,那么这个Bean的实例将是一个CGLIB动态生成的实例而不是原来类的实例。

原文地址:http://blog.csdn.net/qking93415981/archive/2007/08/10/1735617.aspx
UserDao.java
package com.modellite.spring;

public class UserDao
{
	private String name;

	public UserDao(String name)
    {
	    super();
	    this.name = name;
    }

	public UserDao()
	{
	// TODO Auto-generated constructor stub
	}

	public void setName(String name)
    {
    	this.name = name;
    }
	public void create(){
		System.out.println("create users from -"+name);
	}
}



UserManager.java
在这段代码中UserManager依靠getUserDao方法来获取UserDao对象。由于在getUserDao方法里显示的声明了如何去实例一个UserDao,所以上面的代码不符合IoC模式的风格。虽然使用GetUserDao封装了UserDao的创建过程,但是UserManager和UserDao的关系仍然非常紧密。
package com.modellite.spring;

public class UserManager
{
	public UserDao getUserDao()
	{
		return new UserDao("UserManager.getUserDao()");
	}

	public void createUser()
	{
		UserDao dao = getUserDao(); // 通过getUserDao获得userDao
		dao.create();
	}
}

配置文件:
<?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"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/aop
	 http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
	 http://www.springframework.org/schema/beans 
	 http://www.springframework.org/schema/beans/spring-beans-2.5.xsd 
	 http://www.springframework.org/schema/context 
	 http://www.springframework.org/schema/context/spring-context-2.5.xsd 
	 http://www.springframework.org/schema/jee 
	 http://www.springframework.org/schema/jee/spring-jee-2.5.xsd 
	 http://www.springframework.org/schema/tx 
	 http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
	<bean id="userManager" class="com.modellite.spring.UserManager">
		<lookup-method name="getUserDao" bean="userDao" />		
	</bean>
	<bean id="userDao" class="com.modellite.spring.UserDao">
		<constructor-arg>
           <value>lookup method</value>
       </constructor-arg>		
	</bean>
</beans>


测试类
ApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
 UserManager manager=(UserManager) ctx.getBean("userManager");
System.out.println(manager.toString());  //打印userManager的信息
manager.createUser();  

Spring还允许Lookup方法中定义的方法带有参数,但是Sping不会处理这些参数。
修改UserManager:
package com.modellite.spring;

public class UserManager
{
	public UserDao getUserDao(String daoName){
	{
		return new UserDao("UserManager.getUserDao()");
	}

	public void createUser()
	{
		UserDao dao = getUserDao(); // 通过getUserDao获得userDao
		dao.create();
	}
}

虽然方法上由参数,但是上面的代码可以正常工作。Spring不会处理这些参数。

Spring对Lookup方法也存在一些限制:
方法不能是private的,但可以是protected的。
方法不能是静态的。
在抽象类和接口上应用Lookup方法有一个比较有趣的用法,就是在抽象类上定义Lookup方法。你一定记得经典的工厂模式吧。定义一个抽象工厂,然后为每一类具体产品实现一个具体产品的工厂。
一个抽象工厂:
package com.modellite.spring;
public abstract class Factory{
   public abstract UserDao getProduct();
}

具体一类产品的工厂:
package com.modellite.spring;
 public class UserDaoFactory extends Factory{
   public UserDao getProduct(){
          return new UserDao("UserDaoFactory");
   }
}



用户可以通过:
new UserDaoFactory().getProduce();
来获取具体的UserDao产品。
    但是如果有很多产品就需要做出实现出很多工厂如,DocumentDaoFactory、GroupDaoFactory等等,这样系统中会出现大量的工厂。工厂的泛滥并不能说明系统的设计是合理的。
    既然Spring可以在抽象类上使用Lookup方法,那么我们就可以不同实现真的去实现那么多的子类了。我们可以在抽象类上直接定义Lookup方法和目标对象。用户直接通过抽象类来获得需要的产品对象。看下面这个例子:
Factory.java
package com.modellite.spring;
 public abstract class Factory {
   public abstract Object getProduct();
}

配置文件添加
<!--如果指定userDaoFactory的类为一个抽象类,并且再这个bean里定义了Lookup方法,那么Spring会自动生成这个抽象类的子类实现。 -->
<bean name="userDaoFactory" class="com.modellite.spring.Factory" scope="prototype">
      <lookup-method name="getProduct" bean="userDao" />
</bean>

UserDao并没有改变,我们通过抽象的Factory获得了具体的UserDao的实例。这样即使系统中很多的具体产品我们也不需要实现每类产品的工厂类了。只需要在系统中配置多个抽象工厂,并且配置每个工厂的singlton为false,在用户使用时使用不同抽象工厂的实例就可以了。
<bean name="userDaoFactory" class="com.modellite.spring.Factory" scope="prototype">
       <lookup-method name="getProduct" bean="userDao" />
  </bean>
  <bean name="documentDaoFactory" class="com.modellite.spring.Factory" scope="prototype">
       <lookup-method name="getProduct" bean="documentDao" /> 
 </bean>

Spring不关心抽象类中的定义的lookup方法是否时抽象的,Spring都会重写这个方法。

    既然Sping可以动态实现抽象类的子类那么,它能不能动态创建出实现一个接口的类呢。答案时肯定的。上面的例子可以直接把Factory变成一个接口,仍然可以正常工作。
    这里需要注意的是,只要在一个Bean上明确的定义了Lookup方法,Spring才会使用CGLIB来做原对象的字节码代理。如果一个没有定义Lookup方法的抽象类或接口是不能直接被Spring实例的。

    本文介绍了Lookup方法的使用和工作原理,希望读者能够对Lookup方法有了比较深入的了解。虽然我的例子可以简化工厂模式,但是我并不鼓励大家在实际系统中这样做。因为我始终认为“工厂模式”只要在遗留系统中才会碰到。使用IoC模式基本上可以替代所有的对象创建模式。本章的例子只是为了说明Lookup方法如何使用,和Lookup方法的一些特殊情况。Lookup方法一般只在处理遗留代码时使用。

分享到:
评论

相关推荐

    requestUtils lookup方法简介

    requestUtils lookup方法简介

    LOOKUP函数处理内存数组

    在Excel中,LOOKUP函数是一种强大的工具,尤其在处理内存数组时,它的功能更为突出。内存数组,也称为工作区数组或动态数组,是Excel在内存中存储的一组数据,无需预先定义单元格范围,这使得它在进行复杂计算和数据...

    Revit lookup2016-2022源代码

    2. **用户界面**:这部分代码涉及了Revit Lookup的界面设计,如对话框、菜单项和按钮等,以及它们与后台数据处理的连接。 3. **数据解析和展示**:源码中包含了如何解析Revit模型中的参数信息,并将其以用户友好的...

    lookup窗体 --- 用x++代码创建.docx

    ### lookup窗体 -- 用X++代码创建 #### 概述 在Microsoft Dynamics AX系统中,`lookup`窗体是一种非常实用的功能,主要用于提供一种快速查找和选择数据的方式。这通常用于那些需要从一个较大的数据集中选取特定记录...

    【含源码和addin】RevitLookup 2020

    【亲测可用】Revit 2020 Lookup Tables是Revit表格查找工具,是revit开发必不可少的一个组件,需要的朋友可以下载! 用法:将RevitLookup.addin和RevitLookup.dll放到C:\ProgramData\Autodesk\Revit\Addins\2019下...

    hash_lookup3

    `lookup3.c`是`hash_lookup3`函数的C语言实现,包含了函数的具体代码逻辑。`hash.txt`和`lookup3.txt`可能分别提供了关于`hash_lookup3`的详细说明和使用示例,帮助开发者理解和应用这个哈希函数。 在实际应用中,...

    vc错误查看工具lookup

    用户只需输入或复制粘贴错误代码,Lookup就能快速返回相关的错误信息,包括错误类型、错误原因以及可能的解决方法。 使用Lookup工具可以节省开发者大量的时间,避免在文档和搜索引擎中反复搜索,提高开发效率。对于...

    RevitLookup-2020.0.0.4.rar

    7. 错误处理和日志记录:为了确保插件的稳定性和可靠性,Revit Lookup会包含错误处理代码,以及用于记录和分析问题的日志系统。 通过深入研究Revit Lookup的源代码,开发者可以提升Revit插件开发的技能,更好地理解...

    RevitLookup-2020.0.0.4.zip

    开发者可以利用RevitLookup来测试他们的代码,确保元素属性的读取和设置正确无误。 在安装RevitLookup-2020.0.0.4.zip后,用户只需运行MSI文件,按照安装向导的提示进行操作即可完成安装。安装完毕后,在Revit中...

    NetBeans lookup的例子

    5. **查找和使用服务**:在需要使用`MyService`的地方,添加代码进行Lookup查询,并调用找到的服务实例的方法。 通过以上步骤,你就完成了一个基本的NetBeans Lookup查询示例。在实际开发中,Lookup机制可以用于...

    RevitLookup-2019.0.0.3.rar

    RevitLookup的使用方法相对简单。首先,你需要将压缩包"RevitLookup-2019.0.0.3"解压,其中包含了必要的DLL文件和安装说明。然后,将这些文件复制到Revit的插件目录下,通常是在"Add-Ins"子目录内。重启Revit后,你...

    RevitLookup-2021.0.0.13

    5. **快速定位问题**:在开发过程中,RevitLookup能快速定位并解决代码错误,提高开发效率。 Revit二次开发涉及到的知识点包括: 1. **C#编程语言**:Revit API主要使用C#进行开发,因此需要掌握基本的C#语法和...

    vs ErrorLookUp 工具

    ErrorLookUp工具就是为了帮助开发者和系统管理员理解这些错误代码的含义,从而快速定位和解决编程或系统问题。 该工具的核心功能是通过`defines.db3`数据库文件,它包含了大量系统错误代码及其对应的定义和描述。`...

    Revit Lookup2017-2020.zip

    6. **提高效率**:对于Revit的二次开发者来说,Revit Lookup极大地提高了工作效率,减少了在源代码和Revit模型间反复切换的时间。 7. **社区支持**:由于Revit Lookup是开源工具,开发者社区对其持续维护和更新,...

    RevitLookup-2019源码

    RevitLookup-2019源码是针对Revit 2019版本的源代码,允许开发者查看和分析其内部运作机制。 源代码的获取对于开发者来说至关重要,因为它提供了直接编译和修改项目的机会。当你下载了"RevitLookup-2019.0.0.6"这个...

    RevitLookup-2019

    5. **调试工具**:对于开发Revit API应用的程序员来说,RevitLookup能帮助快速定位和修复代码问题,因为它可以直接展示API对象的属性和方法。 在压缩包中,`RevitLookup.addin`文件是Revit的加载项配置文件,包含了...

    RevitLookup 2020.0.0.1

    RevitLookup的使用方法通常包括以下步骤: 1. **安装**:通过运行msi安装包,将RevitLookup集成到Revit环境中。 2. **启动**:在Revit中,通过插件菜单或快捷键启动RevitLookup。 3. **选择元素**:在Revit模型中...

    RevitLookup.dll

    编译的基于revit2017的lookup工具,帮助更好的开发revit插件。 RevitLookUp工具可以帮助我们调试Revit数据库,并能够辅助我们理解和查找元素以及它们的参数。但是网站上只有源码需要自己编译。

    RevitLookUp

    RevitLookUp不仅支持查看元素的基本属性,还可能包含自定义属性,这使得它在处理复杂定制模型时特别有用。此外,它还可能提供了一些高级功能,例如导出属性信息到文件,方便进一步的数据分析和报告。 总之,Revit...

Global site tag (gtag.js) - Google Analytics