Announcement Announcement Module
No announcement yet.
A Spring Class Loader? Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • A Spring Class Loader?

    A quote from J2EE Design and Development without EJB:
    Spring AOP - Cons
    It's only possible to use configuration to advise objects obtained from a Spring IoC container, or to use the AOP framework programmatically; it's not possible to advise objects at the class loader level so that the new operator returns an advised object. As all business objects in Spring applications are obtained from the IoC container, it's possible to apply advice in a much broader range of cases than is supported by EJB. However, it would be harder to apply advice to all objects to be persisted with Hibernate, for example. Like lack of support for field interception, this partly reflects a conscious decision. Spring is not intended to encourage advising each and every object. (This may pose performance problems, for example.) Spring is designed to encourage obtaining business objects from a Spring container, which helps to structure applications. And this way there's never any doubt as to which objects are advised, and what advice applies.
    Some people now seem to want to inject dependencies into “each and every object” of not-very-spring-friendly frameworks (e.g. struts, hibernate, jdo). While this is sometimes possible, it sometimes seems to introduce complexity into Spring and the Spring users configuration.

    So here's the question: Wouldn't a Spring class loader make general purpose dependency injection much simpler than the complexity of the AOP interceptor/proxy approach?

    Simple Example: Struts integration.
    <action path="/EditItem" type="org.springframework.web.struts.DelegatingActionProxy"
    <bean name="/EditItem" class="" singleton="false">
            <property name="artBS"><ref bean="artBS"/></property>
    Sure, its not too bad, but I have to learn about DelegatingActionProxy. I'd rather have a “normal” struts-config.xml and a simple applicationContext.xml
    <action path="/EditItem" type=""
    <bean name="IMHOanyPlaceHolderNameWouldDo" class="" singleton="false">
            <property name="artBS"><ref bean="artBS"/></property>
    A Spring aware classloader could make this work. Big deal, you may say, but look at a more complex example of the same issue.

    A Complex Example: Full Hibernate object injection.
    This very popular thread called “How Common to Spring Manage Beans Created By Hibernate? comes to the conclusion that you can inject into hibernate created objects using cyInjectionInterceptorFactoryBean. It also requires some complex xml configuration that reminds me of EJB deployment descriptors (;->). Now I have to learn hibernate and some specialized Spring specific XML configuration. But aren't we just trying to a bit of simple dependency injection here?
    (Yes I know, this is an advanced use of Spring/Hibernate and its non-essential to get Spring and hibernate working nicely. However many people in the thread seem very happy to have this advanced feature and Rod/others seem keen to support it. )

    Couldn't a Spring aware classloader make this work without a DependencyInjectionInterceptorFactoryBean and the simplest of config in applicationContext.xml ?

    Other Examples?

    I expect that I am being naïve about a Spring class loader. I'm sure that there are some very big issues with a class loader especially in an EJB application server which generally want to control classloading. However I was surprised from 10,000 feet up not see some discussion about this. I did search the forums for “class loader” but I couldn't find anybody discussing this directly.

    So here's the question again with an addition in italics: Wouldn't a Spring class loader make general purpose dependency injection and its configuration much simpler than the complexity of the AOP interceptor/proxy approach from an end user perspective?

  • #2
    Interesting discussion. In general, application servers like to do class loader magic and we are wary of going there, as it may compromise portability.

    Rather than through class loading, I think AOP offers the most general way to do this. Adrian Colyer (AspectJ lead) has written an AspectJ aspect that can dependency inject any object that has a @SpringConfigured("beanName") annotation. I think this is the best way forward, and we'll ship this with Spring 1.3, assuming that the AspectJ 5.0 release schedule allows. While this would entail weaving your code with AspectJ, it would provide an elegant portable solution to all the problems you describe.




    • #3
      Originally posted by Rod Johnson
      Adrian Colyer (AspectJ lead) has written an AspectJ aspect that can dependency inject any object that has a @SpringConfigured("beanName") annotation.
      Rod, thanks for the heads-up. I have been trying to find a solution to the same issue and this could indeed be "it". I have one question though, that is, wouldn't this make the object being injected referencing Spring (and AspectJ) explicitly?


      • #4
        Rod, Thanks for the reply. This would do the trick.

        This blog by Adrian Colyer mentioning @SpringConfigured is compelling reading on a broader subject: “The New Holy Trinity”
        The key section is
        ... aspects can also be used to implement dependency injection scenarios. In general you're best leaving this job to an IoC container, but if you have DI requirements that go beyond the wiring of beans as they are instantiated by the container, aspects are a great solution. [....] A second example is the use of an annotation @SpringConfigured(beanName="XXX") on POJOs. It's easy to write an aspect (configured by DI to be BeanFactoryAware in Spring terms) that uses Spring to autowire any instance of an @SpringConfigured object when it is instantiated. This lets you separate instantiation and configuration (normally an IoC container like Spring does both for you) so that you can place instantiation under programmatic control, but still get configuration via DI.
        Couple of questions:
        Is there likely to be a variant that works with Java 1.4 or earlier?
        Can “normal” SpringAOP be mixed with AspectJ AOP? E.g. Could I use @SpringConfigured for hibernate objects and Spring AOP TransactionProxyFactoryBean for declarative transactions?


        • #5
          Some more information on this solution can be found at:

          Adrian, Rod and I did some work to decouple the @SpringConfigured annotation from Spring making it @Bean. There is a basic BeanConfigurator aspect which is extended to SpringBeanConfigurator. Your bean have no knowledge of Spring and only require the @Bean annotation. You don't even have to play about with configuration files - the SpringBeanConfigurator locates configuration files from across your classpath automatically.



          • #6
            Now it's perfect. Thanks!


            • #7
              Is there likely to be a variant that works with Java 1.4 or earlier?
              Sadly, no. This needs Java 5 and AspectJ 5 (not yet final).

              Can “normal” SpringAOP be mixed with AspectJ AOP? E.g. Could I use @SpringConfigured for hibernate objects and Spring AOP TransactionProxyFactoryBean for declarative transactions


              • #8
                A Spring Class Weaver?

                Thanks again Rod. My initial thoughts have evolved a bit. As you say, the problems that I described could certainly be solved using AspectJ 5 as elaborated in 'Hacking With Harrop'. Intriguing as it may be, it seems to be a very heavy weight solution, its not pure Java and it won't work in Java 1.4 or earlier.

                The usefulness of AspectJ in this context, basically hinges on the compile time weaving to advise classes. (To me, the advantages of the @Bean annotation vs. XML declaration are a matter of taste and less important). Compile time weaving means that is no need for a special classloader as per my original suggestion.

                So that got me thinking! Couldn't a much simpler solution be achieved with a Spring-Compile-Time-Class-Weaver?
                You'd run it on the application classes using the spring beans application configuration.
                It would byte-code-enhance some the spring beans classes. For each spring bean definition, it might
                (a) add code (weave advice?) into the constructors to do runtime Spring DI.
                (b) generate compile-time AOP proxies for Spring AOP advised classes.

                Although I think (a) is what would actually solve my original problems, it struck me that (b) could usefully be done at the same time and might even be essential if some of the DI spring beans needed advice too.

                Wouldn't this have the following advantages compared to AspectJ?
                -Pure Java.
                -Works in pre Java 5.
                -Solves all the problems that I mentioned, simplifying configuration for end users.
                - Once Spring gets a hook into instantiation of classes, anything is possible.

                Probably hellishly complicated to implement but it seemed like a good idea on the train!

                - Tim


                • #9
                  Hi Tim, Another AOP framework "ApectWerks" may be your choice. Checkout the previous edition. What u must do is to change your app server's classloader.