Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guice dependency injection for entity beans?

For a rich domain driven design I want to use Guice dependency injection on JPA/Hibernate entity beans. I am looking for a similar solution as the Spring @configurable annotation for non-Spring beans.

Does anybody know of a library? Any code examples?

like image 347
Kdeveloper Avatar asked Jul 17 '10 23:07

Kdeveloper


People also ask

How do you inject beans with dependency injection?

In Spring Boot, we can use Spring Framework to define our beans and their dependency injection. The @ComponentScan annotation is used to find beans and the corresponding injected with @Autowired annotation. If you followed the Spring Boot typical layout, no need to specify any arguments for @ComponentScan annotation.

How does Guice dependency injection work?

Guice figures out how to give you an Emailer based on the type. If it's a simple object, it'll instantiate it and pass it in. If it has dependencies, it will resolve those dependencies, pass them into it's constructor, then pass the resulting object into your object.

What is Guice dependency injection?

Guice is an open source, Java-based dependency injection framework. It is quiet lightweight and is actively developed/managed by Google. This tutorial covers most of the topics required for a basic understanding of Google Guice and to get a feel of how it works.

What is Bean in Guice?

Similar to Guice provider methods, bean definition methods are annotated (but with @Bean instead of @Provides), return the type you want to bind (often an interface), and can have arguments that are injected via Spring.


1 Answers

You can do this with AspectJ.

Create the @Configurable annotation:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Configurable {
}

Create an AspectJ @Aspect similar to this:

@Aspect
public class ConfigurableInjectionAspect {
    private Logger log = Logger.getLogger(getClass().getName());

    @Pointcut("@within(Configurable) && execution(*.new(..)) && target(instantiated)")
    public void classToBeInjectedOnInstantiation(Object instantiated) {}

    @After(value = "classToBeInjectedOnInstantiation(instantiated)", 
           argNames = "instantiated")
    public void onInstantiation(Object instantiated) {
        Injector injector = InjectorHolder.getInjector();
        if (injector == null) {
            log.log(Level.WARNING, "Injector not available at this time");
        } else {
            injector.injectMembers(instantiated);
        }
    } 
}

Create (and use) a holding class for your injector:

public final class InjectorHolder {

    private static Injector injector;

    static void setInjector(Injector injector) {
        InjectorHolder.injector = injector;
    }

    public static Injector getInjector() {
        return injector;
    }
}

Configure META-INF/aop.xml:

<aspectj>
    <weaver options="-verbose">
        <include within="baz.domain..*"/>
        <include within="foo.bar.*"/>
    </weaver>
    <aspects>
        <aspect name="foo.bar.ConfigurableInjectionAspect"/>
    </aspects>
</aspectj>

Start your VM with aspectjweaver:

-javaagent:lib/aspectjweaver.jar

Annotate your domain classes:

@Entity
@Table(name = "Users")
@Configurable 
public class User {
    private String username;
    private String nickname;
    private String emailAddress;
    @Inject
    private transient UserRepository userRepository

    public User() {}
}
like image 126
Craig Day Avatar answered Sep 23 '22 08:09

Craig Day