Spring Bean 方法注入

Spring 中可以通过配置覆盖或拦截指定的方法,通常通过代理模式实现。Spring 提供两种方法注入方式:查找方法注入和方法替换注入。

Spring 是通过 CGLIB 动态代理方式实现方法注入,也就是通过动态修改类的字节码来实现的,本质就是生成需方法注入的类的子类方式实现。

查找方法注入

用于注入方法返回结果,也就是说能通过配置方式替换方法返回结果

<lookup-method name="方法名" bean="bean名字"/>

访问级别必须是 public 或 protected,保证能被子类重载,可以是抽象方法,必须有返回值,必须是无参数方法,查找方法的类和被重载的方法必须为非 final

public class Decorator implements IHelloService {
    @Override
    public void sayHello() {
        printer.print("setter");
        System.out.println(message);
        createPrototypePrinter().print("prototype");
    }

    private Printer printer;

    public void setPrinter(Printer printer) {
        this.printer = printer;
    }

    public Printer createPrototypePrinter() {
        System.out.println("该方法不会被执行");
        return new Printer();
    }

    public Printer createSingletonPrinter() {
        System.out.println("该方法不会被执行");
        return new Printer();
    }
}

public class Printer {
    private int counter = 0;

    public void print(String type) {
        System.out.println(type + " printer: " + counter++);
    }
}

配置如下:

<bean id="decorator1" class="xxxx.Decorator" scope="singleton">
    <property name="printer" ref="prototypePrinter"/>  
    <lookup-method name="createPrototypePrinter" bean="prototypePrinter"/>  
    <lookup-method name="createSingletonPrinter" bean="singletonPrinter"/>  
</bean>
<bean id="decorator2" class="xxxx.Decorator" scope="prototype">  
    <property name="printer" ref="prototypePrinter"/>  
    <lookup-method name="createPrototypePrinter" bean="prototypePrinter"/>  
    <lookup-method name="createSingletonPrinter" bean="singletonPrinter"/>  
</bean>  

初始化 Bean 输出:

=======singleton sayHello======
setter printer: 0
hello
prototype printer: 0
setter printer: 1
hello
prototype printer: 0
=======prototype sayHello======
setter printer: 0
hello
prototype printer: 0
setter printer: 0
hello
prototype printer: 0

替换方法注入

和查找注入方法不一样的是,主要用来替换方法体。首先定义一个 MethodReplacer 接口实现

public class PrinterReplacer implements MethodReplacer {
    @Override
    public Object reimplement(Object obj, Method method, Object[] aobj) throws Throwable {
        System.out.println("Print Replacer");  
        // 注意此处不能再通过反射调用了,否则会产生循环调用,直到内存溢出  
        // method.invoke(obj, new String[]{"hehe"});  
        return null;  
    }
}

配置如下:

<bean id="replacer" class="xxxx.PrinterReplacer"/> 
<bean id="printer" class="xxxx.Printer">  
    <replaced-method name="print" replacer="replacer">  
        <arg-type>java.lang.String</arg-type>  
    </replaced-method>  
</bean>  

Tags:

Add a Comment

电子邮件地址不会被公开。 必填项已用*标注

2 × 4 =