简体   繁体   中英

Spring's Javaconfig and Prototyped Beans

I've moved my code from Spring's XML configuration to Java Configuration. I have everything working, but I have a question about how I implemented prototype beans - mainly, while what I'm doing works, is it the best way to do this? Somehow it just feels off!

I wrote the bean class this way:

@Component
@Scope("prototype")
public class ProtoBean {
    ...
}

Then to use the bean - this is the part that I'm just not sure about, although it does work:

@Component
public class BeanUser implements ApplicationContextAware {
    ApplicationContext context;

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

    public void getProtoBean() {
         ProtoBean protoBean = context.getBean(ProtoBean.class);
    }
}

This gets me a prototyped bean, and in unit tests I just mocked the context, called setApplicationContext with the mock, and had the getBean call of the mock return a mock ProtoBean. So all is well.

I did this in the XML by using a factory, but that didn't seem to work too well, so this is where I ended up. But is there a way to do this without the context? Or just a better way?

Thanks!

I don't think is so much an issue of Spring XML vs Java-base configuration, but one of matching dependency scopes. Since Spring can only do dependency injection on the singleton-scoped bean at creation time, you have to lookup the prototype-scoped bean on demand. Of course the current bean-lookup approach works, but creates a dependency on the ApplicationContext. I can suggest a few other possibilities but the root of the issue is really what is involved in producing a ProtoBean, and what trade-offs should you accept.

You could make BeanUser itself prototype-scoped, which would allow you to wire in the ProtoBean as a member. Of course the trade-off is you now have the same problem on the clients of BeanUser, but sometimes that would not be a problem.

Another path could be using something like a singleton-scoped ProtoBeanFactory to provide ProtoBean instances, and hiding dependency lookups within the ProtoBeanFactory.

Finally, you could use a scoped-proxy bean to effectively hide the factory. It uses AOP to do this, and isn't always clear to others what sort of voodoo you have going. With XML you'd use <aop:scoped-proxy/> on the bean declaration. For annotations you'd use:

@Scope(proxyMode = ScopedProxyMode.TARGET_CLASS, value = "prototype")

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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