Spring中的Lookup方法注入

时间:2014-03-19 10:27:32

标签: java spring dependency-injection

我正在阅读Spring http://docs.spring.io/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-method-injectionLookup method injection上的文章。

在此,有一个声明

If the method is abstract, the dynamically-generated subclass implements the method. 
Otherwise, the dynamically-generated subclass overrides the concrete method defined in the original class.

我不明白这两者之间的区别。有人可以用一个例子解释一下吗?

4 个答案:

答案 0 :(得分:2)

Lookup Method DI:-

What is Lookup Method-
Here lookup method means
if a method, if it is not having any implementation or
if a method, if it is required any depedency we can consider that method as a lookup method.

for ex.
1. In case of interface

interface Test{

 public void a(); //lookup method
 public void b(); //lookup method

}

2. In case of abstract class

abstract class Test{

    abstract public void a(); //lookup method

    public void b(){

    }  
}

3. In case of concrete class

class Test{

/* if you want to override method a() then you can call this method also like lookup method */
    public void a(){
        //implementation
    }

    public void b(){
        //implementation
    }
}

Note:-if you want to provide implementation to that method you can call that method as lookup method.

By using spring you can provide implementation,
for abstract classes you can provide implementation,
for interface you can provide implementation and
in case if you don’t satisfy existing implementation from concreate class that implementation also you can override.

**Example:-**

*Required jar file
commons-logging-1.1.3.jar
org.springframework.asm-3.0.1.RELEASE-A.jar
org.springframework.beans-3.0.1.RELEASE-A.jar
org.springframework.context-3.0.1.RELEASE-A.jar
org.springframework.core-3.0.1.RELEASE-A.jar
org.springframework.expression-3.0.1.RELEASE-A.jar
cglib-nodep-2.2.jar :- cglib jar will help to generate runtime proxy.

**Engine class**

package beans;

public class Engine {
    private String name;

    public void setName(String name) {
        this.name = name;
    }
    public String getName() {
        return name;
    }
}

**Car interface**

package beans;

public interface Car {

    //return Engine class object
    public Engine myCarEngine();
}

**Bus abstract class**

package beans;

abstract public class Bus {

    //return Engine class object
    abstract public Engine myBusEngine();
}

**Truk concrete class**

package beans;

public class Truck {

    //if you don't satisfy this existing implementation you can override by using lookup method.
    public Engine myTrukEngine(){
        Engine e=new Engine();
        e.setName("Eicher-Truck");
        return e;
    }
}

**spring.xml**

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"  "http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

  <!-- for car interface provide lookup method -->
    <bean id="c" class="beans.Car">
        <lookup-method name="myCarEngine" bean="e" />
    </bean>
    <bean id="e" class="beans.Engine">
        <property name="name" value="swift Car Engine" />
    </bean>


  <!-- for bus abstract provide lookup method -->
    <bean id="b" class="beans.Bus">
        <lookup-method name="myBusEngine" bean="e1" />
    </bean>
    <bean id="e1" class="beans.Engine">
        <property name="name" value="TATA BusEngine" />
    </bean>


  <!-- for Truck concrete provide lookup method -->
    <bean id="t" class="beans.Truck">
        <lookup-method name="myTrukEngine" bean="e2" />
    </bean>
    <bean id="e2" class="beans.Engine">
        <property name="name" value="BENZ Truck Engine" />
    </bean>

</beans>

**Client class**

package test;

import java.util.*;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import beans.Bus;
import beans.Car;
import beans.Truck;

public class Client {

    public static void main(String[] args) {

        ApplicationContext ap= new ClassPathXmlApplicationContext("resource/spring.xml");
        System.out.println("-----------Car----------");
        Car c=(Car)ap.getBean("c");
        System.out.println("Name of Class generated by spring at runtime="+c.getClass().getCanonicalName());
        System.out.println("Engine Name="+c.myCarEngine().getName());

        System.out.println("-----------Bus----------");
        Bus b=(Bus)ap.getBean("b");
        System.out.println("Name of  Class generated by spring at runtime="+b.getClass().getCanonicalName());
        System.out.println("Engine Name="+b.myBusEngine().getName());

        System.out.println("-----------Truk----------");
        Truck t=(Truck)ap.getBean("t");
        System.out.println("Name of Class generated by spring at runtime="+t.getClass().getCanonicalName());
        System.out.println("Engine Name="+t.myTrukEngine().getName());

    }


}

**OutPut:-**

———–Car———-
Name of Class generated by spring at runtime=beans.Car$$EnhancerByCGLIB$$68fda491
Engine Name=swift Car Engine

———–Bus———-
Name of Class generated by spring at runtime=beans.Bus$$EnhancerByCGLIB$$cfce5a7
Engine Name=TATA BusEngine

———–Truk———-
Name of Class generated by spring at runtime=beans.Truck$$EnhancerByCGLIB$$dc82ada3
Engine Name=BENZ Truck Engine

How to spring provide implementation :-
if we load spring.xml file into Ioc Container ,then Ioc container generate runtime proxy class by using cglib jar for provide implementation.
like..


//This class generate by Spring at runtime
class CarProxy extends Car{
    @Override
    public Engine myCarEngine(){

        //implementation
        return e;
    }
}

答案 1 :(得分:0)

这是Spring使用CGLib的地方。这并不重要 - 重点是您应该了解Spring正在创建一个代理对象,将该实例交给您的客户。

Spring使用CGLib为您生成的代理对象可以实现抽象方法,或覆盖具体方法。因此,如果您提供标记为抽象的方法,或者您提供的方法未标记为抽象(因此将覆盖您的方法),它会检查您的类以确定方法。

代理用于很多容器。它们在Java Enterprise世界中也很常见。如果您的类可能被运行时代理子类化,那么如果您还想要一个带有参数的公共构造函数,您会发现需要提供一个无参数构造函数(非公共构造函数)。

答案 2 :(得分:0)

我认为不同之处在于,一般的概念是不为查找方法提供任何实现,因为您希望将其注入。但这会导致您遇到问题: 1)如果在已经是抽象的类中将此方法定义为抽象,那么您的子类必须实现它。 2)如果在非抽象类中定义这样的方法,则必须使该类成为抽象。 为了避免这种强制改变,提供一个身体更方便。

答案 3 :(得分:0)

在多线程环境中,你有这样的要求,你想要在Single ton bean中注入一个原型bean,但是当bean范围是singleton时spring会返回一个bean只有一个对象。然后Prototype将不起作用它将作为单例因为它被Spring IOC容器注入一次。那时我们将使用Spring提供的查找方法注入。通过使用查找方法注入,我们将在每次调用时获得一个带有注入新Prototype Object的单例对象。但它将如何得到... ?现在,您将获得问题的答案,当您在SpringBeanConfiguratipon文件中将原型bean id配置为查找方法时,内部spring将通过扩展Prototype类创建Prototype $ Proxy类,并覆盖您的查找方法。如果你的查找方法是抽象的,它将实现否则覆盖。当你调用查找方法时,它将调用Proxy类方法,并且每次都会给出新的Object。