Spring 为什么AutowiredBean不创建新实例,而是从上下文加载?

Spring 为什么AutowiredBean不创建新实例,而是从上下文加载?,spring,spring-integration,spring-bean,Spring,Spring Integration,Spring Bean,我有一个简单的调度程序 public class MailSendScheduler { @Autowired MailCollector mailCollector; @Scheduled(cron = "0/10 * * * * *") public void call() throws Exception { log.info("Method executed " + new Date()); taskExecutor

我有一个简单的调度程序

public class MailSendScheduler {

    @Autowired 
    MailCollector mailCollector;

    @Scheduled(cron = "0/10 * * * * *")
    public void call() throws Exception {
        log.info("Method executed " + new Date());

        taskExecutor.initialize();

        for (int i = 0; i < 15; i++) {
                mailCollector.setText(Integer.toString(i));
            taskExecutor.execute(mailCollector);
        }
    }   
}
你认为会有什么结果?应该是从0到14,不是吗?但不是这样的:

<bean id="mailCollector" class="ge.ddrc.school.mails.MailCollector" scope="prototype" >
            <property name="mailSender" ref="mailSender" />
    </bean>
2,2,4,5,14,14,14,14,14,14,14,14,14,14,14.
似乎mailController是单例的。我认为这并不是在创造新的bean。但是等一下,如果我写这个:

ApplicationContext context = new ClassPathXmlApplicationContext("spring/mail-config.xml");

        for (int i = 0; i < 15; i++) {
            MailCollector  mailCollector=(MailCollector) context.getBean("mailCollector");
            mailCollector.setText(Integer.toString(i));
            taskExecutor.execute(mailCollector);
        }

输出是这样的:1,2,3,4,5,8,9,6,7,10,15,13,14,12,11!为什么会发生这种情况?

这就是Spring原型范围的工作原理

Prototype作用域意味着每个引用在每个@Autowired、每个context.getBean中都有自己的实例


您必须使用自定义作用域和作用域代理为循环的每个迭代获取一个新实例。这是相当先进的东西。创建自己的工厂来为每次迭代获取新实例可能更容易。

因为您不了解原型。一旦请求一个bean实例,该作用域就会创建一个新的bean实例。在第一个示例中,您基本上有一个单例;在第二个示例中,您为每个cal to getBean获得一个新实例。虽然您不应该自己创建上下文,但您可以通过实现ApplicationContextAware将其注入当前bean。或者您可以@Autowire应用上下文。理论上,作用域代理不也应该工作吗?尽管每个方法调用可能会以这种方式产生一个新实例。你想要一个线程和可见性之间的作用域或者其他什么。我是说作用域代理,对不起-但他需要一个自定义作用域,对吗?也许,不确定如果你放在一个原型作用域bean上会发生什么。我希望代理上的每个方法调用都有一个新的实例,但我不这么认为:在任何情况下,他在每次迭代中调用两个方法——setter和run。
ApplicationContext context = new ClassPathXmlApplicationContext("spring/mail-config.xml");

        for (int i = 0; i < 15; i++) {
            MailCollector  mailCollector=(MailCollector) context.getBean("mailCollector");
            mailCollector.setText(Integer.toString(i));
            taskExecutor.execute(mailCollector);
        }