is there an elegant way to inject a spring managed

2019-01-18 23:02发布

问题:

I have a bunch of java custom tags that use spring managed beans.. since i cant find a way to inject into a custom tag, i created a helper class that provides static methods to "getTheObjectINeedBean()" for all the spring bean objects i need.. I do not like this approach at all.

i really want to be able to inject a spring managed bean into the custom tag

Is there a way? As far as my research goes, I understand there is no way to do this, because the custom tag is container managed

Thanks,

Billy

回答1:

You are correct there isn't a simple way to use dependency-injection in jstl tags, because they are not managed by spring, and cannot be. However there are (at least) two workarounds:

  • @Configurable - aspectJ allows you to plug a weaver at load-time/compile-time, so that even objects that are not instantiated by spring can be spring aware. See here

  • You can create a base tag class for your project, and call an init(..) method from every doStartTag(..) method. There, you can get the ServletContext from the pageContext, and thus obtain the spring ApplicationContext (via ApplicationContextUtils). Then:

    AutowireCapableBeanFactory factory = appCtx.getAutowireCapableBeanFactory();
    factory.autowireBean(this);
    

Neither options are perfect as they require either some additional code, or some "black magic"



回答2:

To expand on @Bozho's post, I have gotten this to work like so: (in spring 3.0 there is no ApplicationContextUtils that I could find)

public class LocationTag extends RequestContextAwareTag {
    @Autowired
    PathComponent path;

...
    @Override
    protected int doStartTagInternal() throws Exception {
        if (path == null) {
            log.debug("Autowiring the bean");
            WebApplicationContext wac = getRequestContext().getWebApplicationContext();
            AutowireCapableBeanFactory acbf = wac.getAutowireCapableBeanFactory();
            acbf.autowireBean(this);
        }
        return SKIP_BODY;
    }
}


回答3:

The solution as described above works but some background and additional code snippets are, quite likely, useful.

1) The doStartTagInternal method is invoked from the doStartTag method. 2) I was forced to set the pageContext first before invoking the doStartTag 3) I did a lookup of the bean as opposed to the autowiring. To me this seems more straightforward: (YourBeanProxy) autowireCapableBeanFactory.getBean("yourBeanName")

Hopefully this additional info is useful.