简体   繁体   English

弹簧注入,全局变量

[英]Spring injection, global variables

Probably my question is wrong and I can't do this way, but I can't find a good explanation. 我的问题可能是错误的,我不能这样做,但是找不到很好的解释。

Here are my classes and my injections with Spring: 这是我的课程和对Spring的投入:

public class A
{
    @Autowired
    protected B b;

    public void doSomething(Integer i)
    {
        b.doOtherStuff(i);
    }
}

And here is my B class: 这是我的B课:

public class B
{
    private Integer field;
    private List<SomeOtherClass> list = new ArrayList<>();

    @Autowired
    protected C c;

    public void doOtherStuff(Integer in)
    {
        field = in;
        list = c.getMyList(i);
    }
}

What if I'll have two concurrent calls to a.doSomething(..)? 如果我要同时对a.doSomething(..)进行两次调用怎么办? The second call will overwrite the private fields in B and probably the values will not be corret in one of the two executions? 第二次调用将覆盖B中的私有字段,并且可能不会在两个执行之一中将值正确化? Am I wrong? 我错了吗?

What if someone calls a.doSomething() and terminates, later B is used (via injection) in another class? 如果有人调用a.doSomething()并终止,后来在另一个类中使用B(通过注入)怎么办? Can this last class have an instance of B initialized precedently? 最后一个类是否可以预先初始化B的实例?

Let me know if my question are unclear, I'm not so good in Java and English too :D 如果我的问题不清楚,请告诉我,我的Java和英语也不太好:D

What if I'll have two concurrent calls to a.doSomething(..)? 如果我要同时对a.doSomething(..)进行两次调用怎么办? The second call will overwrite the private fields in B and probably the values will not be corret in one of the two executions? 第二次调用将覆盖B中的私有字段,并且可能不会在两个执行之一中将值正确化? Am I wrong? 我错了吗?

list property will be assigned twice. list属性将被分配两次。 And if B#doOtherStuff makes more than just assigning the value of list , then you'll most probably get ConcurrentModificationException or maybe unexpected results. 如果B#doOtherStuff不仅仅是分配list的值,那么您很可能会收到ConcurrentModificationException或意外的结果。

When you have this scenario when a bean needs to maintain mutable state that depends on execution, then your bean should not be in Singleton scope. 在这种情况下,当Bean需要维护依赖于执行的可变状态时,则Bean不应处于Singleton范围内。 The best option would be to have the bean declared as prototype , which is created every time by the Spring IoC container. 最好的选择是将bean声明为prototype ,它由Spring IoC容器每次创建。

It is important to know that if you have a prototype bean injected into a singleton bean, then the IoC container will only create a single instance of the prototype bean, thus making it virtually singleton. 重要的是要知道,如果将原型Bean注入到一个Singleton Bean中,那么IoC容器将仅创建该原型Bean的单个实例,从而使其实际上成为Singleton。 To avoid such behavior, you may ask for the ApplicationContext to retrieve a new instance per method execution: 为了避免这种行为,您可以要求ApplicationContext在每次方法执行时检索一个新实例:

@Component
public class A {
    @Autowired
    private ApplicationContext ctx;

    public void doSomething(Integer i) {
        //ApplicationContext will create the bean using the IoC container
        B b = ctx.getBean(B.class);
        b.doOtherStuff(i);
    } 
}

More info: 更多信息:

You are right in your assumption that the private variables are a problem in your beans. 您认为私有变量是bean中的问题是正确的。 You might want to read up a bit on bean scopes . 您可能需要阅读有关bean作用域的内容 The default bean scope is singleton, which means only one instance will life for all calls. 缺省的bean作用域是singleton,这意味着对于所有调用而言,只有一个实例可以使用。

This will also mean that your private variables are shared through all calls that you make to the bean. 这也意味着您的私有变量将通过对Bean的所有调用来共享。 So in class B the variable field would be overwritten by each call to the method doOtherStuff . 因此,在类B中,每次调用方法doOtherStuff都会覆盖变量field

In general practice it is bad to have private variables in Spring beans, unless you change the scope. 通常,除非更改范围,否则在Spring bean中拥有私有变量是很糟糕的。 There are some exceptions to this, for example some caching or any other shared and thread safe logic. 对此有一些例外,例如某些缓存或任何其他共享的和线程安全的逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM