阅读 167

Quarkus依赖注入(3)🔥

我们在编写代码时,经常用到依赖注入。在Spring中经常看到@Bean@Service之类的注解,目的是将类转化为Bean进行有效的管理。 ​

而经过beanFactory管理的Bean可以通过注解注入到别的实现类中。从此,我们不用关心Bean从何处来要到何处去如何创建怎么销毁上下文怎么获取等等。

Bean

主流框架大多都有这个概念。 ​

比如我们业务实现类、拦截器、配置类、过滤器都基本都是基于Bean的概念。比如QuarkusBean,虽然有多个注解,用于区分不同的作用域,但是都不需要我们关心Bean的创建、注入等等细节,Quarkus简化了Bean的发现,但是Quarkus 鼓励用户不要在 bean 中使用私有成员。 ​

Bean依赖注入

Bean被有效的管理了,那么实现依赖注入将是一件非常简单的事情。

@ApplicationScoped
public class BrandInfoRepository extends ResourceRepository<BrandInfo> {
}
复制代码

@ApplicationScoped 是最常用的注解,将Bean交给容器管理。 ​

注入的方式比较多,但是在注入时,Quarkus不推荐使用private,一般可以用package-private修饰符。

@ApplicationScoped
public class BrandInfoResource extends BaseResource {
    @Inject
    BrandInfoRepository brandInfoRepository;
}
复制代码

这也是比较推荐的方式,通过@Inject进行注入。 ​

另外也可以通过构造函数进行注入,这时候就不需要@Inject注解了,但是这时候修饰符可以使用private

@ApplicationScoped
public class BrandInfoResource extends BaseResource {
    private BrandInfoRepository brandInfoRepository;
    
    public BrandInfoResource(BrandInfoRepository brandInfoRepository) {
        this.brandInfoRepository = brandInfoRepository;
    }
}
复制代码

Quarkus依赖注入的方式其实比较多的,但是一般常用的还是@Inject注解的方式。 ​

注解

@ApplicationScoped

javax.enterprise.context.ApplicationScoped是我们最经常用到的注解。被注解的Bean在应用系统中是单例的,同时是惰性创建的。

@Target({ TYPE, METHOD, FIELD })
@Retention(RUNTIME)
@Documented
@NormalScope
@Inherited
public @interface ApplicationScoped {

    /**
     * Supports inline instantiation of the {@link ApplicationScoped} annotation.
     *
     * @author Martin Kouba
     * @since 2.0
     */
    public final static class Literal extends AnnotationLiteral<ApplicationScoped> implements ApplicationScoped {

        public static final Literal INSTANCE = new Literal();

        private static final long serialVersionUID = 1L;

    }

}
复制代码

@Singleton

javax.inject.Singleton也是常用的注解,与ApplicationScoped的区别是立即创建了实例。

@Scope
@Documented
@Retention(RUNTIME)
public @interface Singleton {}
复制代码

@RequestScoped

javax.enterprise.context.RequestScoped的作用域限制在了当前请求。

@Target({ TYPE, METHOD, FIELD })
@Retention(RUNTIME)
@Documented
@NormalScope
@Inherited
public @interface RequestScoped {

    /**
     * Supports inline instantiation of the {@link RequestScoped} annotation.
     *
     * @author Martin Kouba
     * @since 2.0
     */
    public final static class Literal extends AnnotationLiteral<RequestScoped> implements RequestScoped {

        public static final Literal INSTANCE = new Literal();

        private static final long serialVersionUID = 1L;

    }

}
复制代码

@Dependent

javax.enterprise.context.Dependent这些实例不共享,并且每个注入点都会生成一个新的依赖Bean实例。 ​

bean的生命周期与注入它的bean绑定,将与注入它的bean一起创建和销毁它。

@Target({ METHOD, TYPE, FIELD })
@Retention(RUNTIME)
@Documented
@Scope
@Inherited
public @interface Dependent {

    /**
     * Supports inline instantiation of the {@link Dependent} annotation.
     *
     * @author Martin Kouba
     * @since 2.0
     */
    public final static class Literal extends AnnotationLiteral<Dependent> implements Dependent {

        public static final Literal INSTANCE = new Literal();

        private static final long serialVersionUID = 1L;

    }
}
复制代码

@SessionScoped

javax.enterprise.context.SessionScoped配合quarkus-undertow使用的,作用域是当前Session。 ​

选用合适的注解

主要是针对ApplicationScopedSingletonApplicationScoped是延迟创建的,而Singleton是立即创建实例。 ​

Singleton通常有更好的性能,因为是直接调用的,省去了Proxy,自然也不需要将上下文委托给当前实例的Proxy。 ​

但是Singleton不能通过QuarkusMock来模拟bean。 ​

一般来说,除非有充分的理由使用ApplicationScoped,否则我们建议默认情况下坚持使用Singleton,以获取更好的性能。 ​

文章分类
后端
文章标签