IOC - 方法注入

当有两个bean A,B.其中A的内部会调用B,A是单例的,而A每次调用到B的时候都需要重新实例化B,为了解决这个需求难道我们得放弃Spring容器?并不用,Spring可以通过方法注入来实现动态改变A内的B

Spring的方法注入依赖于CGLIB,需要用到方法注入的方法必须满足以下声明规范

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

解释以下:
1. 方法必须是可以被子类覆写的public,protected,也可以abstract
2. 必须有返回值
3. 方法必须无参

下面演示下Spring的方法注入

public class User {
    private String username;
    private Bread bread;

    public void eat() {
        //必须通过getBread()调用bread
        System.out.println(username + " has eaten this bread -> " +getBread());
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Bread getBread() {
        return bread;
    }

    public void setBread(Bread bread) {
        this.bread = bread;
    }
}

User类里依赖了一个Bread类,User每次调用bread实例的时候,都必须重新实例化bread

Bread类如下

public class Bread {
    private int weight = 20;
    private double price = 50;

}

在Spring.xml中进行如下声明

Bread必须声明成prototype类型

<bean id="bread" class="com.spring.ioc.factory.Bread" scope="prototype"/>

User类中必须通过lookup-method声明方法注入时的方法getBread

<bean id="user" class="com.spring.ioc.factory.User" >
    <property name="username" value="tom"/>
    <lookup-method name="getBread" bean="bread"/>
</bean>

测试一下

@Test
public void bread(){
    User user= (User) context.getBean("user");
    user.eat();
    user.eat();
    user.eat();
}

运行结果

tom has eaten this bread -> com.spring.ioc.factory.Bread@4c6e276e
tom has eaten this bread -> com.spring.ioc.factory.Bread@534df152
tom has eaten this bread -> com.spring.ioc.factory.Bread@52e677af

可以看到每个Bread的hash值都是不一样说明方法注入成功了

为了实现类似的功能,同时避免显示声明对象,我们可以使用BeanFactoryAware或者ApplicationContextAware接口注入BeanFactory或者ApplicationContext,通过getBean方法就能每次获取到新的Bread对象

public class Student implements BeanFactoryAware, ApplicationContextAware {
    private BeanFactory beanFactory;
    private ApplicationContext context;

    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        this.beanFactory = beanFactory;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.context = applicationContext;
    }

    public void eat() {
        System.out.println(beanFactory.getBean("bread"));
        System.out.println(context.getBean("bread"));
    }

}
@Test
public void factoryBread(){
    Student student= (Student) context.getBean("student");
    student.eat();
}

运行结果

com.spring.ioc.factory.Bread@534df152
com.spring.ioc.factory.Bread@52e677af
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值