xiaodududu / google-guice

Automatically exported from code.google.com/p/google-guice
Apache License 2.0
0 stars 0 forks source link

Original initialized instance values get lost after gucie injection #746

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
Description of the issue:

I use Gucie to intercept any methods that have my defined annotation 
@LogRequired. However for my application, some beans are initialized by Spring 
with injected fields values. After calling giuce injector.injectMembers(this), 
the beans gets proxied by guice but all original fields values are gone. Looks 
like Guice re-constucts the beans and throw away all old values. Is this 
expected behavior or how can I solve this issue?

Steps to reproduce:
1. Create a class extends AbstractModule
public class InterceptorModule extends AbstractModule{
    public void configure()
    {
            LogInterceptor tracing = new LogInterceptor();
            requestInjection(tracing);
            bindInterceptor(Matchers.any(), Matchers.annotatedWith(LogRequired.class), tracing);
        }
    }

2. Define the interceptor business logic
public class LogInterceptor
        implements MethodInterceptor
{
//business logic here 
}

3. Create LogService class
Public class LogService
{
 Injector injector = Guice.createInjector(new InterceptorModule());
}

4. I have one of the bean example below with the getName method wants to be 
intercepted:
public class UserImplTwo implements IUser
{

    private String name;

        @LogRequired
    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

}

which is initialized  by Spring context:
    <bean id="userTwo" class="com.consumer.impl.UserImplTwo">
        <property name="name" value="hello world"></property>
    </bean>

5. Finally I have a consumer to consume the bean:
public class Consumer
{
        @Inject
        private UserImplTwo instance;

        public void setInstance(UserImplTwo instance)
        {
            this.instance = instance;
        }

      public void init()
        {
           // the value of name is printed out as 'hello world'
             System.out.println(  this.instance.getName());

             LogService.injector.injectMembers(this);

            // the value of name is printed out as null, should be 'hello world'
             System.out.println(  this.instance.getName());

        }

Then use Spring to initialized the bean: 

     <bean id="consumer" class="com.demo.Consumer" init-method="init">
        <property name="instance" ref="userTwo"></property>
    </bean>

Please let me know if this the the right approach or if I did something wrong, 
because I have to use Spring to initialize some beans.

Original issue reported on code.google.com by dave.che...@gmail.com on 25 Apr 2013 at 8:50

GoogleCodeExporter commented 9 years ago
Calling injector.injectMembers(instance) asks Guice inject any fields or setter 
methods in the instance that are declared with @Inject. Guice has no way to 
know that these fields have already been injected, for example they could have 
default values that should be overwritten by the configured value.

The safest way to avoid this kind of re-injection, when you're using multiple 
injection frameworks to configure the same instance, is to use constructor 
injection for the primary properties. You can then use setter or field 
injection for any secondary properties supplied by the other framework.

If constructor injection is not an option then you could always use setter 
injection, and put a guard condition in your setter methods to ignore 
subsequent calls.

Original comment by mccu...@gmail.com on 12 May 2013 at 9:35