Spring的方法注入(Method Injection)

下面通过一个示例来说明方法注入:

假设一个单例bean A每次在调用process()方法时,都需要一个新的bean B实例。具体实现如下:

//spring的xml配置如下
<bean id="b" class="com.bean.B" scope="prototype">
<bean id="a" class="com.bean.A"/>
/*
 *ApplicationContextAware是spring提供的一个接口,
 *通过实现它的setApplicationContext方法,可以拿到spring的上下文参数
 *从而通过spring的上下文参数,获取spring容器管理的bean
 */
public class A implements ApplicationContextAware{
    private ApplicationContext applicationContext;
    public void setApplicationContext(
            ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
    public B createB() {
        return this.applicationContext.getBean(B.class);
    } 

    public void process(){
        B b = createB();
        b.execute();
    }
}
public class B{
    public void execute(){
        System.out.println("execute");
    }
}

通过以上代码我们可以看到,类A确实实现了在每次调用process()方法时,都有一个新的实例B为其服务。

但是也造成的类A的代码和Spring耦合在一起。那么怎样做才会更好呢,spring IoC给我们提供了一个更为高级的方式Method Injection,中文意思就是 “方法注入”。

关于方法注入的xml配置及注解配置,请看代码如下:

//spring的xml配置如下
<bean id="b" class="com.bean.B" scope="prototype">
<bean id="a" class="com.bean.A">
    <lookup-method name="createB" bean="b"/>方法注入的配置
<bean>
public class A { 
    //@Lookup("b")注解的方式实现方法注入的配置
    public B createB(){
        return null;
    }
    public void process(){
        B b = createB();
        b.execute();
    }
}
public class B{
    public void execute(){
        System.out.println("execute");
    }
}
public class Test{
    public static void main(String[] main){
        ClassPathXmlApplicationContext ctxt = 
            new ClassPathXmlApplicationContext("bean.xml");
        A a = ctxt.getBean(A.class);
        System.out.println(a.createB()==a.createB());
        System.out.println(a);
        a.process();
    }
}
//运行结果如下:
false
com.bean.A$$EnhancerBySpringCGLIB$$9f25fa1c@4671e53b
execute

上面代码的运行结果可能会让你出乎意料。这是因为Spring通过GCLIB动态代理生成字节码来实现对此方法的注入,,并且根据类B的配置属性scope="prototype"每次调用该方法都会生成一个新的实例B。

由于GCLIB是针对类来实现代理的,原理是对指定的类生成一个子类,并覆盖其中的方法实现代理。因为采用的是继承,所以不能对final修饰的类进行代理。 因此对于需要Spring容器子类化的类,不能使用final修饰,并且需要重写的方法也不能使用final修饰。

所以在进行方法注入时,需要注意注入的方法的标准格式如下:

<public|protected> [abstract] <return-type> theMethodName(no-arguments);

猜你喜欢

转载自blog.csdn.net/jbfx455l/article/details/82081237