Spring框架下Bean的方法注入(Method injection)

通常情况下我们在spring中定义的常用bean都是单例模式(singleton)的例如@Service、@Controller定义的bean,任何一个类都只有一个对象,只进行一次初始化这些类的属性永远是最后一次调用它时的值。但是针对不同的业务场景我们可能会定义一些bean,这些bean的属性在不同场景下它的属性值是不同的,因此这时候我们就不能使用单例模式了而使用原型模式(prototype),这种模式相当于new一个对象。参见spring官方文档。
1.4.6. Method injection
In most application scenarios, most beans in the container are singletons. When a singleton bean needs to collaborate with another singleton bean, or a non-singleton bean needs to collaborate with another non-singleton bean, you typically handle the dependency by defining one bean as a property of the other. A problem arises when the bean lifecycles are different. Suppose singleton bean A needs to use non-singleton (prototype) bean B, perhaps on each method invocation on A. The container only creates the singleton bean A once, and thus only gets one opportunity to set the properties. The container cannot provide bean A with a new instance of bean B every time one is needed.
最后两句:假定有单例bean A和原型bean B,当A初始化的时候只有一次机会初始化B,但是A中可能在不同方法中对B进行了调用,这时候可能B中的部分属性发生了变化,而在A中的不同方法可能希望B中的属性是刚初始化时的值,但是容器并不能提供新的B类的实体,因此才有了下面的解决办法

A solution is to forego some inversion of control. You can make bean A aware of the container by implementing the ApplicationContextAware interface, and by making a getBean(“B”) call to the container ask for (a typically new) bean B instance every time bean A needs it. The following is an example of this approach:

利用ApplicationContextAware接口中的getBean方法向容器请求一个新的bean
具体参考以下代码

package com.spring.util;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * @author chengjian
 * @date 2018/5/16
 **/
@Component
public class SpringBeanFactory implements ApplicationContextAware {
    private  ApplicationContext applicationContext;


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

    public <T> T getBean(Class<T> clazz){
        try{
            return applicationContext.getBean(clazz);
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

我们创建了一个SpringBeanFactory,这个类实现了ApplicationContextAware方法,我们在类中新定义了一个基于泛型的getBean方法,通过这样的方式我们就能通过方法的方式从spring容器中获取到我们想要的bean。参考下面的代码

package com.spring.javatest.io;

import com.github.javafaker.Faker;
import com.spring.config.SpringConfig;
import com.spring.javatest.entity.UserEntity;
import com.spring.util.CommonUtil;
import com.spring.util.SpringBeanFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.util.Locale;

/**
 * @author chengjian
 * @date 2018/5/15
 **/
@Component
public class OutPutStreamTest {
    @Autowired
    private SpringBeanFactory springBeanFactory;

    public void fileOutPutSerializable() {

        try {
            Faker faker=new Faker(new Locale("zh-CN"));
            UserEntity user=new UserEntity();
            user.setUserid(CommonUtil.getUuid());
            user.setUserpwd("123456");
            user.setUsername("a001");
            user.setRealname(faker.name().fullName());
            String fileName = springBeanFactory.getBean(SpringConfig.class).getLocation() + "output";
            FileOutputStream f = new FileOutputStream(fileName);
            ObjectOutput s = new ObjectOutputStream(f);
            s.writeObject(user);
            s.flush();
            s.close();
            f.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

我们并没有通过@Autowired注解注入SpringConfig,而是通过方法注入的方式注入的bean

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值