美文网首页互联网科技JavaJava 杂谈
Spring IOC的一些高级特性

Spring IOC的一些高级特性

作者: java欧阳丰 | 来源:发表于2019-08-01 20:20 被阅读5次

Lookup方法注入

在大部分的应用场景中,容器中的大部分bean是singleton类型的。当一个单例bean需要和另外一个单例bean协作时,或者一个非单例bean要引用另外一个非单例bean时,通常情况下将一个bean定义为另外一个bean的属性值就行了。不过对于具有不同生命周期的bean来说这样做就会有问题了,比如在调用一个单例类型bean A的某个方法,需要引用另一个非单例(prototype)类型bean B,对于bean A来说,容器只会创建一次,这样就没法在需要的时候每次让容器为bean A提供一个新的bean B实例。

Lookup方法具有使容器覆盖受容器管理的bean方法的能力,从而返回指定名字的bean实例。在上述场景中,Lookup方法注入适用于原型bean。 Lookup方法注入的内部机制是Spring利用了CGLIB库在运行时生成二进制代码的功能,通过动态创建Lookup方法bean的子类从而达到复写Lookup方法的目的。

为了使动态子类起作用,Spring容器要子类化的类不能是final,并且需要覆写的方法也不能是final。同样的,要测试一个包含抽象方法的类也稍微有些不同,你需要子集编写它的子类提供该抽象方法的实现。最后,作为方法注入目标的bean不能是序列化的。在Spring 3.2之后再也没必要添加CGLIB到classpath,因为CGLIB的类打包在了org.springframework下并且在Spring核心JAR中有所描述。这样做既方便,又避免了与其他使用了不同版本CGLIB的项目的冲突。

假如现在有2个类:Clerk和ClerkManager,其中ClerkManager依赖于Clerk,即ClerkManager持有类型为Clerk的私有属性,现在我们想让Clerk been的作用域为singleton,而ClerkManager been的作用域为prototype,如果不做任何处理直接在ClerkManager been中设置Clerk属性,就会出现问题,即每次应用的Clerk been都是同一个,无法达到预期的效果。这个时候我们可以使用Spring的Lookup方法注入来达到在每次引用Clerk属性的时候都会动态创建一个新的Clerk been的目的。一下是Clerk和ClerkManager的代码:

package com.ioc.lookup;
 
public class Clerk {
    private String name;
    private int age;
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
 
}
package com.ioc.lookup;
 
public abstract class ClerkManager {
    private Clerk clerk;
    
    public Object process() {
        //调用createClerk()方法动态生成Clerk对象
        Clerk Clerk=createClerk();
        return Clerk;
    } 
    //这个动态生成Clerk对象的方法,这是个抽象方法,Spring容器会自动覆写createClerk()方法的实现。
    protected abstract Clerk createClerk();
 
    public Clerk getClerk() {
        return clerk;
    }
 
    public void setClerk(Clerk clerk) {
        this.clerk = clerk;
    }
    
}

接着我们在applicationContext.xml中配置如上类的bean:

    <bean id="clerk" class="com.ioc.lookup.Clerk" scope="prototype">
        <property name="name" value="Tom"></property>
        <property name="age" value="20"></property>
    </bean>
    <bean id="clerkManager" class="com.ioc.lookup.ClerkManager" scope="singleton">
        <lookup-method name="createClerk" bean="clerk"/>
    </bean>

最后编写一个测试类:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.ioc.lookup.ClerkManager;
 
public class LookuoDemo {
 
    public static void main(String[] args) {
 
        ApplicationContext applicationContext=new ClassPathXmlApplicationContext("classpath:applicationContext.xml");
        
        ClerkManager clerkManager=(ClerkManager) applicationContext.getBean("clerkManager");
        
        System.out.println("第一次注入的Clerk:"+clerkManager.process());
        
        System.out.println("第二次注入的Clerk:"+clerkManager.process());
 
    }
 
}

运行测试类,结果如下:

可以看到,两次注入的Clerk been是不一样的,因此达到了我们的目的。
谢谢你的阅读,如果您觉得这篇博文对你有帮助,请点赞和关注我哦,让更多的人看到!祝你每天开心愉快!

相关文章

网友评论

    本文标题:Spring IOC的一些高级特性

    本文链接:https://www.haomeiwen.com/subject/ozzcdctx.html