简体   繁体   English

春季与豆列出

[英]List with Bean in spring

I having an user details class inside that i placed address class to store the multiple addressess for each user details class. 我在其中放置了一个用户详细信息类,在其中放置了地址类,以存储每个用户详细信息类的多个地址。 I am using Spring 4.0 for that. 我为此使用Spring 4.0。 Below given the code: 下面给出代码:

UserDetails class: UserDetails类:

@Component("userDetails")

public class UserDetails {

    @Resource(name="address")
    @Autowired
    private List<Address> address;
    public List<Address> getAddress() {
        return address;
    }
    @Autowired
    public void setAddress(List<Address> address) {
        this.address = address;
    }
}

Address Class: 地址类别:

@Component("address")

public class Address {

    private String area;

    public String getArea() {
        return area;
    }
    public void setArea(String area) {
        this.area = area;
    }
}

In this example, Address.area value need to pass in the run time and then i need to create an object for Address class. 在此示例中,Address.area值需要在运行时传递,然后我需要为Address类创建一个对象。 Then it need to add in the List address variable present inside UserDetails class. 然后,需要添加UserDetails类中存在的List地址变量。 Likewise i need to add n number object in the arrayList then i need to create an object for UserDetails class. 同样,我需要在arrayList中添加n个对象,然后为UserDetails类创建一个对象。

I tried the below code: 我尝试了以下代码:

public class AppMain {

    public static void main(String args[]){
        AbstractApplicationContext  context = new AnnotationConfigApplicationContext(AppConfig.class);

        Address address = (Address)context.getBean("address");
        //setting first value:
        address.setArea("XXX");

        Address address1 = (Address)context.getBean("address");
        //setting second value
        address1.setArea("YYY");

        UserDetails userDetails = (UserDetails)context.getBean("userDetails");
        System.out.println("User Size: "+application.getAddress().size());
        System.out.println("User Details : "+application.getAddress().get(0).getArea());
        System.out.println("User Details : "+application.getAddress().get(1).getArea()); // getting ArrayIndexOutOfBoundException in this line
    }
}

partial Output: User Size: 1 User Details : YYY 部分输出:用户大小:1用户详细信息:YYY

Expected Output: User Size: 2 User Details : XXX User Details : YYY 预期输出:用户大小:2用户详细信息:XXX用户详细信息:YYY

Could you please help with this. 您能帮忙吗?

It's not entirely clear to me why you would want to create what appear to be domain objects using Spring but it looks like that's what you're doing from your code. 对我来说,还不是很清楚,为什么要使用Spring创建看似域对象的对象,但这似乎正是您在代码中所做的。

Spring has the concept of Scope that controls what happens when you retrieve a bean from an ApplicationContext . Spring具有范围的概念,该范围控制从ApplicationContext检索bean时发生的情况。 The default Scope is singleton which means you only get a one instance of the bean within the ApplicationContext . 默认的Scopesingleton ,这意味着您在ApplicationContext仅获得一个bean实例。 This means that your calls context.getBean("address") always return the same object. 这意味着您的调用context.getBean("address")始终返回相同的对象。

As for the wiring that you've performed using the @Component annotation; 至于使用@Component注释执行的接线; this occurs when the classpath is scanned (normally when the application starts). 扫描类路径时会发生这种情况(通常是在应用程序启动时)。 At this time Spring instantiates a single instance of each class marked with @Component , that's one Address and one UserDetails . 此时,Spring实例化每个标记有@Component类的单个实例,即一个Address和一个UserDetails Spring is smart enough to add the single Address to a List before setting the address field but that's all it does. Spring足够聪明,可以在设置address字段之前将单个“ Address添加到“ List ,但是仅此而已。

Your code then retrieves this objects from the ApplicationContext setting the area on the same object twice, hence why the debug statements print as they do. 然后,您的代码从ApplicationContext设置相同对象上两次的区域中检索该对象两次,因此为什么调试语句会像它们那样打印。

This explains what's going on with your code, but leaves the question of how to fix it unanswered. 这解释了您的代码发生了什么,但未解决如何解决它的问题。

As I said, I can't understand why you would used Spring to build what appears to be a domain model. 就像我说的那样,我不明白您为什么要使用Spring来构建似乎是域模型的东西。 Domain models, in terms of the instances of each class, are not typically known ahead of time and therefore Spring is not the appropriate tool to use to create such a model (Spring is typically used to wire together the application itself). 就每个类的实例而言,领域模型通常不会提前知道,因此,Spring不是用于创建这种模型的合适工具(Spring通常用于将应用程序本身连接在一起)。

You should modify the domain classes' constructors like this: 您应该像这样修改域类的构造函数:

public Address
{
  private String area;

  public Address(String area)
  {
    this.area = area;
  }

  ...
}

public UserDetails
{
  private List<Address> addresses;

  public UserDetails(Address... addresses)
  {
    this.addresses = Arrays.asList(addresses);
  }

  ...
}

And then the main method can be re-written: 然后可以重写main方法:

public static void main(String[] args)
{
   UserDetails userDetails = new UserDetails(
     new Address("XXX"),         
     new Address("YYY"),        
   ); 

   System.out.println("User Size: " + application.getAddress().size());
   System.out.println("User Details: " + application.getAddress().get(0).getArea());
   System.out.println("User Details: " + application.getAddress().get(1).getArea());
}

Notice that you are getting the same bean twice, so it's impossible that you get two injections in the UserDetails List: 请注意,您两次获得同一个bean,因此不可能在UserDetails列表中获得两次注入:

Address address = (Address)context.getBean("address");
...
Address address1 = (Address)context.getBean("address");

Something like this should work: 这样的事情应该起作用:

@Configuration
public class AppConfig{

    @Bean
    public UserDetails userDetails(){
        return new UserDetails();
    }

    @Bean
    public Address addressXXX(){
        return new Address();
    }

    @Bean
    public Address addressYYY(){
        return new Address();
    }

}

Then your code: 然后你的代码:

Address address = (Address)context.getBean("addressXXX");
//setting first value:
address.setArea("XXX");

Address address1 = (Address)context.getBean("addressYYY");
//setting second value
address1.setArea("YYY");

UserDetails userDetails = (UserDetails)context.getBean("userDetails");
System.out.println("User Size: "+application.getAddress().size());
System.out.println("User Details : "+application.getAddress().get(0).getArea()); //--->XXX
System.out.println("User Details : "+application.getAddress().get(1).getArea()); //--->YYY

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

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