# Dependency Injection mit Googles Guice bei mit new erzeugten Beans mt AspectJ



## Thomas Darimont (3. Mai 2007)

Hallo,

hier mal ein kleines Beispiel dazu wie man mit Googles neuem Dependency Injection Framework Guice
( http://code.google.com/p/google-guice/ ) auch Dependencies von Objekten verwalten kann die nicht über den Container sonder per 
new (...) erzeugt werden. Dazu bedienen wir uns ein klein wenig der Technik des Springframeworks ( http://springframework.org/ )
in Verbindung mit AspectJ in dem wir einen Configuration Aspect schreiben, der die Konstruktor-
aufrufe abfängt und die daraus resultierenden Instanzen entsprechend konfiguriert. 
Da Guice scheinbar an einigen Stellen noch nicht so gut mit generics klar kommt (oder ich sie falsch
Benutze hab ich diese aus meinem ursprünglichen Beispiel mal entfernt): Das Problem wird gerade hier:
http://groups.google.com/group/google-guice/browse_thread/thread/a48924f9434bfa6e diskutiert.

Hier das Beispiel:
Unser IService-Interface

```
/**
 * 
 */
package de.tutorials.services;

/**
 * @author Thomas.Darimont
 *
 */
public interface IService/*<TRequest extends IRequest, TResponse extends IResponse>*/{
    IResponse /*TResponse*/ process(IRequest /*TRequest*/ request);
}
```

Unser IRequest Interface:

```
/**
 * 
 */
package de.tutorials.services;

/**
 * @author Thomas.Darimont
 *
 */
public interface IRequest {
    String getData();
    void setData(String data);
}
```


Unser IResponse-Interface

```
package de.tutorials.services;

public interface IResponse {
    String getResult();
    void setResult(String result);
}
```

Unser MockService:

```
/**
 * 
 */
package de.tutorials.services.internal.mock;

import com.google.inject.Singleton;

import de.tutorials.services.IRequest;
import de.tutorials.services.IResponse;
import de.tutorials.services.IService;

/**
 * @author Thomas.Darimont
 * 
 */
@Singleton
public class MockService implements IService /*<MockRequest, MockResponse>*/{
    public IResponse /*MockRequest*/ process(IRequest /*MockResponse*/ request) {
        MockResponse response = new MockResponse();
        response.setResult(request.getData().toUpperCase());
        return response;
    }
}
```

Unser MockReuqest:

```
/**
 * 
 */
package de.tutorials.services.internal.mock;

import de.tutorials.services.IRequest;

/**
 * @author Thomas.Darimont
 *
 */
public class MockRequest implements IRequest {
    String data;

    /**
     * @return the data
     */
    public String getData() {
        return data;
    }

    /**
     * @param data the data to set
     */
    public void setData(String data) {
        this.data = data;
    }
    
}
```

Unsere MockResponse:

```
/**
 * 
 */
package de.tutorials.services.internal.mock;

import de.tutorials.services.IResponse;

/**
 * @author Thomas.Darimont
 *
 */
public class MockResponse implements IResponse {

    String result;

    /**
     * @return the result
     */
    public String getResult() {
        return result;
    }

    /**
     * @param result the result to set
     */
    public void setResult(String result) {
        this.result = result;
    }
}
```

unser Guice-Modle:

```
/**
 * 
 */
package de.tutorials;

import com.google.inject.Binder;
import com.google.inject.Module;

import de.tutorials.services.IService;
import de.tutorials.services.internal.mock.MockService;

/**
 * @author Thomas.Darimont
 * 
 */
public class MainModule implements Module {
    public void configure(Binder binder) {
        binder.bind(IService.class).to(MockService.class);
    }
}
```

unser Client der einen IService injected bekommen soll welcher die Configurable Annotation hat:

```
/**
 * 
 */
package de.tutorials;

import com.google.inject.Inject;

import de.tutorials.configuration.Configurable;
import de.tutorials.services.IRequest;
import de.tutorials.services.IResponse;
import de.tutorials.services.IService;
import de.tutorials.services.internal.mock.MockRequest;

/**
 * @author Thomas.Darimont
 * 
 */
@Configurable
public class Client {
    IService /*<IRequest, IResponse>*/ service;

    /**
     * @return the service
     */
    public IService/*<IRequest, IResponse>*/ getService() {
        return service;
    }

    /**
     * @param service
     *            the service to set
     */
    @Inject
    public void setService(IService/*<IRequest, IResponse>*/ service) {
        System.out.println("setService");
        this.service = service;
    }

    public void start() {
        IRequest request = new MockRequest();
        request.setData("bubu");
        IResponse response = getService().process(request);
        System.out.println(response.getResult());
    }
}
```

Unsere @Configurable-Annotation:

```
/**
 * 
 */
package de.tutorials.configuration;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author Thomas.Darimont
 *
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
@Inherited
public @interface Configurable{
}
```

Unser ConfigurationAspect:

```
/**
 * 
 */
package de.tutorials.configuration.aspects;

import de.tutorials.Main;
/**
 * @author Thomas.Darimont
 *
 */
public aspect Configuration {
    protected pointcut beanCreation(Object beanInstance) :
        initialization((@de.tutorials.configuration.Configurable *).new(..)) 
        && this(beanInstance) 
        && !cflow(call(* com.google.inject..*(..)));
    
    after(Object beanInstance) returning : beanCreation(beanInstance) {
      System.out.println("Configuring " + beanInstance.getClass() );
      Main.INJECTOR.injectMembers(beanInstance);
    }
}
```
die beanCreation Pointcutdefinition ist von Spring geklaut... außerdem ist es noch etwas unschön
den INJECTOR "global" als Klassenvariable verfügbar zu machen... na ja ist ja nur ein einfaches
Beispiel ;-)

Hier unsere Main:

```
/**
 * 
 */
package de.tutorials;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;

import de.tutorials.services.IService;

/**
 * @author Thomas.Darimont
 *
 */
public class Main {

  //Bootstrap Guice Runtime
  public final static Injector INJECTOR = Guice.createInjector(new MainModule()); 
  
    /**
     * @param args
     */
    public static void main(String[] args) {
        //Start Client
        INJECTOR.getInstance(Client.class).start();
        //new Client().start();
    }
}
```

Ausgabe:

```
setService
BUBU
```

Starten wir das ganze so:

```
/**
 * 
 */
package de.tutorials;

import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;

import de.tutorials.services.IService;

/**
 * @author Thomas.Darimont
 *
 */
public class Main {

  //Bootstrap Guice Runtime
  public final static Injector INJECTOR = Guice.createInjector(new MainModule()); 
  
    /**
     * @param args
     */
    public static void main(String[] args) {
        //Start Client
        //INJECTOR.getInstance(Client.class).start();
        new Client().start();
    }
}
```
So erhalten wir die Ausgabe:

```
Configuring class de.tutorials.Client
setService
BUBU
```

War ja richtig einfach 

Um das Beispiel ausführen zu können braucht ihr die neuste Version von Guice und von AspectJ bzw. das AJDT...
Für Eclipse gibts dazu zusätzlich noch eine komplette Entwicklungsumgebung (AJDT AspectJ Development Tools
dazu: http://www.eclipse.org/ajdt/)

Gruß Tom


----------

