Micronaut seems to have a DI (Dependency Injection) mechanism.
As a feature,
There seems to be something like that.
Micronaut uses JSR-330 for annotation.
https://docs.oracle.com/javaee/6/api/javax/inject/package-summary.html
In addition to the @ Singleton
included in JSR-330, click here for the scope annotation used by Micronaut.
@Singleton
@Context
@Prototype
@Infrastructure
@ThreadLocal
@Refreshable
There are some strange things.
The @ Context
scope represents a bean that needs to be initialized and shut down when the BeanContext
starts and ends.
BeanContext
is usually ʻApplicationContext`, which is the entry point of DI.Micronaut seems to lazy initialize a Singleton bean, so you can use the @Context
annotation to initialize it when the BeanContext
starts. That said, Micronaut is designed to create a minimal number of beans at startup, so the @Context
spec seems to be conservative.
There are some strange things like @ThreadLocal
. @ Infrastructure
seems to be a stereotype of @ Singleton
.
There is also a refreshable scope called @Refreshable
, and it seems that you can refresh with the / refresh
endpoint or RefreshEvent
.
Click here for packages with annotations around here.
https://docs.micronaut.io/1.0.4/api/io/micronaut/context/annotation/package-summary.html
However, the @Controller
annotation that appears in Quick Start is also a kind of scope annotation. It seems that this is not the only thing in total ...
Click here for DI-enabled container types (such as ʻOptional and ʻIterable
).
There seems to be Qualifiers as well.
Let's touch it a little easier.
Click here for this environment.
$ mn -V
| Micronaut Version: 1.0.4
| JVM Version: 1.8.0_191
Create a template for your application.
$ mn create-app hello-di --build maven
$ cd hello-di
Let's write a simple sample using the @ Singleton
and @ Prototype
scopes.
@Singleton
Service.
src/main/java/hello/di/service/SingletonService.java
package hello.di.service;
import javax.inject.Singleton;
@Singleton
public class SingletonService {
public String message() {
return "Hello Singleton Bean";
}
}
Use this Service
, Controller
.
src/main/java/hello/di/controller/SingletonBeanController.java
package hello.di.controller;
import hello.di.service.SingletonService;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
@Controller("/singleton")
public class SingletonBeanController {
SingletonService singletonService;
public SingletonBeanController(SingletonService singletonService) {
this.singletonService = singletonService;
}
@Get(produces = MediaType.TEXT_PLAIN)
public String index() {
return singletonService.message() + " from " + singletonService.getClass().getName() + "@" + singletonService.hashCode();
}
}
It seems that constructor injection is possible.
SingletonService singletonService;
public SingletonBeanController(SingletonService singletonService) {
this.singletonService = singletonService;
}
Also, try issuing a hash code to confirm that the instances are the same.
@Get(produces = MediaType.TEXT_PLAIN)
public String index() {
return singletonService.message() + " from " + singletonService.getClass().getName() + "@" + singletonService.hashCode();
}
Next, a Service that is @ Prototype
.
src/main/java/hello/di/service/PrototypeService.java
package hello.di.service;
import io.micronaut.context.annotation.Prototype;
@Prototype
public class PrototypeService {
public String message() {
return "Hello Prototype Bean";
}
}
Use this Service
, Controller
.
src/main/java/hello/di/controller/PrototypeBeanController.java
package hello.di.controller;
import javax.inject.Inject;
import hello.di.service.PrototypeService;
import io.micronaut.context.ApplicationContext;
import io.micronaut.http.MediaType;
import io.micronaut.http.annotation.Controller;
import io.micronaut.http.annotation.Get;
@Controller("/prototype")
public class PrototypeBeanController {
@Inject
ApplicationContext applicationContext;
@Get(produces = MediaType.TEXT_PLAIN)
public String index() {
PrototypeService prototypeService = applicationContext.getBean(PrototypeService.class);
return prototypeService.message() + " from " + prototypeService.getClass().getName() + "@" + prototypeService.hashCode();
}
}
Controller
seems to be Singleton, and when I injected it as it is, it became the same instance even though it was @ Prototype
, so I decided to get it from ʻApplicatoinContext` ...
@Get(produces = MediaType.TEXT_PLAIN)
public String index() {
PrototypeService prototypeService = applicationContext.getBean(PrototypeService.class);
return prototypeService.message() + " from " + prototypeService.getClass().getName() + "@" + prototypeService.hashCode();
}
Is it because there is no client proxy?
Also, it seems that you can use the @Inject
annotation.
@Inject
ApplicationContext applicationContext;
ʻApplicationContext` constructor injection is also OK.
PrototypeService prototypeService;
public PrototypeBeanController(PrototypeService prototypeService) {
this.prototypeService = prototypeService;
}
The class with the main method is omitted because it is still automatically generated.
Access Controller
using @Singleton
Service
.
$ curl localhost:8080/singleton
Hello Singleton Bean from hello.di.service.SingletonService@56609473
$ curl localhost:8080/singleton
Hello Singleton Bean from hello.di.service.SingletonService@56609473
$ curl localhost:8080/singleton
Hello Singleton Bean from hello.di.service.SingletonService@56609473
I was able to confirm that the DI was working and the same Service
was returned.
Then, @ Prototype
.
$ curl localhost:8080/prototype
Hello Prototype Bean from hello.di.service.PrototypeService@1219715735
$ curl localhost:8080/prototype
Hello Prototype Bean from hello.di.service.PrototypeService@1284304729
$ curl localhost:8080/prototype
Hello Prototype Bean from hello.di.service.PrototypeService@1807347832
Here you can see that the Service
of a different instance is returned.
@ Prototype`` Service
, and he noticed that the same instance was returned ...By the way, what kind of file was generated by Annotation Processor?
$ tree target
target
├── classes
│ ├── META-INF
│ │ ├── hello-di.kotlin_module
│ │ └── services
│ │ └── io.micronaut.inject.BeanDefinitionReference
│ ├── application.yml
│ ├── hello
│ │ └── di
│ │ ├── Application.class
│ │ ├── controller
│ │ │ ├── $PrototypeBeanControllerDefinition$$exec1$$AnnotationMetadata.class
│ │ │ ├── $PrototypeBeanControllerDefinition$$exec1.class
│ │ │ ├── $PrototypeBeanControllerDefinition.class
│ │ │ ├── $PrototypeBeanControllerDefinitionClass$$AnnotationMetadata.class
│ │ │ ├── $PrototypeBeanControllerDefinitionClass.class
│ │ │ ├── $SingletonBeanControllerDefinition$$exec1$$AnnotationMetadata.class
│ │ │ ├── $SingletonBeanControllerDefinition$$exec1.class
│ │ │ ├── $SingletonBeanControllerDefinition.class
│ │ │ ├── $SingletonBeanControllerDefinitionClass$$AnnotationMetadata.class
│ │ │ ├── $SingletonBeanControllerDefinitionClass.class
│ │ │ ├── PrototypeBeanController.class
│ │ │ └── SingletonBeanController.class
│ │ └── service
│ │ ├── $PrototypeServiceDefinition.class
│ │ ├── $PrototypeServiceDefinitionClass$$AnnotationMetadata.class
│ │ ├── $PrototypeServiceDefinitionClass.class
│ │ ├── $SingletonServiceDefinition.class
│ │ ├── $SingletonServiceDefinitionClass$$AnnotationMetadata.class
│ │ ├── $SingletonServiceDefinitionClass.class
│ │ ├── PrototypeService.class
│ │ └── SingletonService.class
│ └── logback.xml
└── generated-sources
└── annotations
9 directories, 25 files
Somehow, various things are made.
It seems that a file for the service provider has been created, so the contents here as well.
target/classes/META-INF/services/io.micronaut.inject.BeanDefinitionReference
hello.di.service.$PrototypeServiceDefinitionClass
hello.di.service.$SingletonServiceDefinitionClass
hello.di.controller.$SingletonBeanControllerDefinitionClass
hello.di.controller.$PrototypeBeanControllerDefinitionClass
For the time being, I was able to confirm the atmosphere.
Recommended Posts