Search code examples
javaspringguice

Equivalency of Guice Provider in Spring


What is the equivalency of Guice's Provider in Spring?

Here is the Guice code I need to replace with Spring:

public class MyProxyProvider implements Provider<MyProxy> {

    @Inject
    Config config;

    @Override
    public MyProxy get() {
        return new MyProxy(httpsclient, config.server, config.user, config.password, config.version);
    }

}

and here the binding is defined:

public class MyModule implements Module {

    @Override
    public void configure(Binder g) {
        g.bind(MyProxy.class).toProvider(MyProxyProvider.class);
    }

}

Finally, my goal is use @Autowired for the proxy object as follows:

public class ConnectionTest {

    @Autowired
    MyProxy proxy;
}

Also note, that MyProxy class in in the external jar file that cannot be modified.


Solution

  • The equivalent to the Provider of guice is the FactoryBean in Spring.

    From the documentation:

    The FactoryBean interface is a point of pluggability into the Spring IoC container's instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean, write the complex initialization inside that class, and then plug your custom FactoryBean into the container.

    Sample

    public class MyFactoryBean implements FactoryBean<MyClassInterface> {
    
        @Override
        public MyClassInterface getObject() throws Exception {
            return new MyClassImplementation();
        }
    
        @Override
        public Class<?> getObjectType() {
            return MyClassInterface.class;
        }
    
        @Override
        public boolean isSingleton() {
            return true;
        }
    
    }
    

    This is a good approach when you have external libraries and complex object creation to avoid long XML configuration to setup your beans.

    In order to use it within your context, you could just provide it as a normal bean within your context XML like:

    ...
    <bean id="myClass" class="foo.bar.MyFactoryBean" />
    ...
    

    BUT, if your bean is quite simple to be instantiated (not lots of dependencies), you can setup it directly on the context XML like:

    <bean id="myClass" class="foo.bar.MyClassImplementation" />
    

    Alternative

    If you use Spring 3 you could write a configuration class (class annotated with @Configuration) as documented here. With this approach you could do something like:

    @Configuration
    public class MyConfiguration {
    
        @Bean
        public MyClassInterface getMyClass() {
            return new MyClassImplementation();
        }
    
    }
    

    This would add your instance to spring context and let autowire it within other classes. But some configuration is required, and its quite easy following the documentation provided.