Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

easier framework support for the creation & injection of a bean by its class [SPR-4594] #9271

Closed
spring-projects-issues opened this issue Mar 17, 2008 · 3 comments
Assignees
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Mar 17, 2008

James Strachan opened SPR-4594 and commented

Now that a bean can be annotated with @Service / @Component its no longer required to be inside an ApplicationContext for Spring to be able to instantiate and inject it. Yet from the public Spring context API the only choice you've got is to access beans by name. (Unless I've missed something :)

There are numerous frameworks out there that want to create an instance of some type easily (without it necessarily being in the spring.xml). Off the top of my head here's a few I've seen some icky code to integrate spring injection but am sure there's loads more...

  • struts
  • stripes
  • jersey
  • apache came

Now in Guice its super easy. You do things like

MyStartClass starter = injector.getInstance(MyStartClass.class);

You're done; all the nice IoC is done by the injector which is a framework developers dream.

When using Spring now we've got 2.5.x its kinda hacky.

e.g. here's some code from trying to use Spring nicely inside JAX-RS (Jersey). Notice its trying to find bean names; then if not it tries to use the BeanFactory in the appContext. This doesn't deal with things like the @Component / @Service use case though.


import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

import com.sun.ws.rest.spi.service.ComponentProvider;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.context.ConfigurableApplicationContext;

/**
 * @version $Revision: 1.1 $
 */
public class SpringComponentProvider implements ComponentProvider {
    private static final transient Log LOG = LogFactory.getLog(SpringComponentProvider.class);
    private final ConfigurableApplicationContext applicationContext;
    private int autowireMode = AutowireCapableBeanFactory.AUTOWIRE_AUTODETECT;
    private boolean dependencyCheck;

    public SpringComponentProvider(ConfigurableApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    public <T> T getInstance(Scope scope, Class<T> type) throws InstantiationException, IllegalAccessException {
        String name = getBeanName(type);
        Object value;
        if (name != null) {
            if (LOG.isDebugEnabled()) {
                LOG.debug("Found bean named: " + name);
            }
            value = applicationContext.getBean(name, type);
        }
        else {
            LOG.debug("No bean name so using BeanFactory.createBean");
            value = applicationContext.getBeanFactory().createBean(type, autowireMode, dependencyCheck);
        }
        return type.cast(value);
    }

    protected <T> String getBeanName(Class<T> type) {
        String[] names = applicationContext.getBeanNamesForType(type);
        String name = null;
        if (names.length == 1) {
            name = names[0];
        }
        return name;
    }

    public <T> T getInstance(Scope scope, Constructor<T> constructor, Object[] objects) throws InstantiationException, IllegalArgumentException, IllegalAccessException, InvocationTargetException {
        return constructor.newInstance(objects);
    }

    public void inject(Object object) {
        String beanName = getBeanName(object.getClass());
        if (beanName != null) {
            ConfigurableListableBeanFactory beanFactory = applicationContext.getBeanFactory();
            beanFactory.configureBean(object, beanName);
        }
    }

    // Properties
    //-------------------------------------------------------------------------
    public int getAutowireMode() {
        return autowireMode;
    }

    public void setAutowireMode(int autowireMode) {
        this.autowireMode = autowireMode;
    }

    public boolean isDependencyCheck() {
        return dependencyCheck;
    }

    public void setDependencyCheck(boolean dependencyCheck) {
        this.dependencyCheck = dependencyCheck;
    }
}

Now maybe SpringSource are now thinking, to hell with frameworks just use the Spring porfolio for everything bwaahahhahaha.

However one of the big factors for Spring's success has always been that it works nicely with loads of different frameworks (struts v stripes v tapestry et al). So I'm wondering would you consider writing some kind of SpringInjector helper class?

So a framework could do something like...

Injector injector = new Injector(applicationContext);
MyStartClass starter = injector.getInstance(MyStartClass.class);

This could then do things like; look for a single instance of MyStartClass in the bean names and use that if specified (fail if there's more than one); or if not treat it as a kinda @Component/@Service type and call its constructors and any other @Autowired / @Resource injection points etc.

i.e. now that there's the mixed model of stuff by name in the app context and stuff on the classpath which are types; could we have a simple unified injector API please for us poor hackers who sometimes dare to work with a framework which is not currently developed by SpringSource? :). Or - could Spring please catch up with Guice in the ease of use stakes as being an IoC framework? :)


Affects: 2.5.2

Issue Links:

4 votes, 3 watchers

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Apr 7, 2011

Stevo Slavić commented

Isn't this resolved in Spring 3.0 with #9905 et al.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Apr 7, 2011

Dave Syer commented

I'm not sure #9994 itself is directly relevant, but there are certainly a lot of features in Spring 3.0 that are relevant. E.g. it's pretty easy to write that injector now:

AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.setParent(applicationContext);
context.register(MyStartClass.class);
context.refresh();
MyStartClass starter = context.getBean(MyStartClass.class);

If it's a common enough use case we could make that into a one-liner, I suppose (one way would be to just add a constructor to AnnotationConfigApplicationContext which accepts the parent context directly).

There are other relevant features in Spring 3.0, e.g. support for @Inject.

@spring-projects-issues
Copy link
Collaborator Author

Rossen Stoyanchev commented

This issue has been resolved through a selective bulk update, as part of a larger effort to better manage unresolved issues. To qualify for the update, the issue was either created before Spring 3.0 or affects a version older than Spring 3.0 and is not a bug.

There is a good chance the request was made obsolete, or at least partly outdated, by changes in later versions of Spring including deprecations. It is also possible it didn't get enough traction or we didn't have enough time to address it. One way or another, we didn't get to it.

If you believe the issue, or some aspects of it, are still relevant and worth pursuing at present you may re-open this issue or create a new one with a more up-to-date description.

We thank you for your contributions and encourage you to become familiar with the current process of managing Spring Framework JIRA issues that has been in use for over a year.

@spring-projects-issues spring-projects-issues added status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement in: core Issues in core modules (aop, beans, core, context, expression) labels Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: core Issues in core modules (aop, beans, core, context, expression) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants