JSR-330 依赖注入

前端之家收集整理的这篇文章主要介绍了JSR-330 依赖注入前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

这篇是承接《轻量级 Java 开发框架 设计》系列Blog文的后续文章。本文是最新 《Hasor 开发指南》中依赖注入章节的完整内容,开发指南目前仍然在努力编写中。

概念

“依赖注入(DI)”有时候也被称为“控制反转(IoC)”本质上它们是同一个概念。具体是指,当某个类调用另外一个类的时候通常需要调用者来创建被调用者。但在控制反转的情况下调用者不在主动创建被调用者,而是改为由容器注入,因此而得名。

这里的“创建”强调的是调用者的主动性。而依赖注入则不在需要调用者主动创建被调用者。

举个例子通常情况下调用者(ClassA),会先创建好被调用者(FunBean),然后在调用方法callFoo中调用调用者(FunBean)的foo方法

public class ClassA {
    private FunBean funBean = new FunBean();
    public void callFoo() {
        this.funBean.foo();
    }
}
public class FunBean {
    public void foo() {
        System.out.println("say ...");
    }
}

使用了依赖注入的情况恰恰相反,调用者(ClassA)事先并不知道要创建哪个被调用者(FunBean)。ClassA调用的是被注入进来的FunBean,通常我们会为需要依赖注入的对象留有set方法,在调用callFoo方法之前是需要先将funBean对象通过setFunBean方法设置进来的。例如:

public class ClassA {
    private FunBean funBean = null;
    public void setFunBean(FunBean funBean) {
        this.funBean = funBean;
    }
    public void callFoo() {
        this.funBean.foo();
    }
}
public class FunBean {
……

传统注入方式

严格意义上来说注入的形式分为两种,它们是“构造方法注入”和“set属性注入”。我们经常听到有第三种注入方式叫“接口注入”。其实它只是“set属性注入”的一种接口表现形式。

@H_301_24@
  • A.构造方法注入:是指被注入的对象通过构造方法传入,例如下面代码
  • public class ClassA {
        private FunBean funBean = null;
        public ClassA(FunBean funBean) {
            this.funBean = funBean;
        }
        public void callFoo() {
            this.funBean.foo();
        }
    }
    @H_301_24@
  • B.set属性注入:是指被注入的对象通过其get/set读写属性方法注入进来,例如:
  • public class ClassA {
        private FunBean funBean = null;
        public void setFunBean(FunBean funBean) {
            this.funBean = funBean;
        }
        public void callFoo() {
            this.funBean.foo();
        }
    }
    @H_301_24@
  • C.接口注入:是指通过某个接口的set属性方法来注入,大家可以看到其本质还是set属性注入。只不过调用者(ClassA),需要实现某个注入接口。
  • public interface IClassA {
        public void setFunBean(FunBean funBean);
    }
    public class ClassA implements IClassA{
        private FunBean funBean = null;
        public void setFunBean(FunBean funBean) {
            this.funBean = funBean;
        }
        public void callFoo() {
            this.funBean.foo();
        }
    }

    Guice与JSR-330

    JSR-330相关的API是由“javax.inject.*”软件包提供的一组标准API。通过注解作为其表现形式。Hasor使用Google旗下的开源DI容器Guice作为其JSR-330的标准支持组件。

    Guice是Google开发的一个轻量级,基于Java5(主要运用泛型与注释特性)的依赖注入框架(IoC)。Guice非常小而且快。Guice是类型安全的,它能够对构造函数属性方法(包含任意个参数的任意方法,而不仅仅是setter方法)进行注入。

    Guice还具有一些可选的特性比如:自定义scopes,传递依赖,静态属性注入,与Spring集成和AOP联盟方法注入等。对于DI框架来说,性能是很重要的,Guice比Spring快这是主流说法,在Guice的官方网站上您可以看到它宣称比Spring快1000倍!

    Hasor选用Guice是由于它的开发接口十分灵活,比起Spring而言Guice更适合作为一个内嵌DI工具来使用。

    由于Guice是JSR-330标准的实现,这也就使得Hasor也具备了支持JSR-330标准的能力。在下面几个小节会讲解如何使用JSR-330标准将其注入到需要的类上。

    我们先假定有一个被调用者(PojoBean),下面是PojoBean类的源代码

    public class PojoBean {
        private String uuid    = UUID.randomUUID().toString();
        private String name    = "马三";
        private String address = "北京马连洼街道办...";
        public String getUuid() {
            return uuid;
        }
        public void setUuid(String uuid) {
            this.uuid = uuid;
        }
        ……
    }

    构造方法注入

    public class ConstructorInject {
        private PojoBean userBean;
        @javax.inject.Inject/*依赖注入*/
        public ConstructorInject(PojoBean userBean) {
            this.userBean = userBean;
        }
        public String getUserName() {
            return this.userBean.getName();
        }
    }

    属性方式注入

    public class MethodInject {
        private PojoBean userBean;
        @javax.inject.Inject/*依赖注入*/
        public void setUserBean(PojoBean userBean) { 
            this.userBean = userBean;
        }
        public String getUserName() {
            return this.userBean.getName();
        }
    }

    字段方式注入

    字段注入是DI容器对“set属性注入”的一种改进.这种改进使得被注入的对象不在需要实现一个set方法,DI容器会主动的将要注入的对象赋值到给定的字段上。

    public class FieldInject {
        @javax.inject.Inject/*依赖注入*/
        private PojoBean userBean;
        public String getUserName() {
            return this.userBean.getName();
        }
    }

    单例Bean

    单例,通常是指整个应用程序范围内某个类型对象只有一个。Hasor使用AppContext接口表示一个应用程序,在一个AppContext内Hasor通过下面这样的代码可以保证单例:

    @javax.inject.Singleton/*声明单例*/
    public class SingletonBean {
        private long time = 0;
        public SingletonBean() {
            time = System.currentTimeMillis();
        }
        public void foo() {
            System.out.println("create at time:" + time);
        }
    }
    原文链接:https://www.f2er.com/javaschema/285815.html

    猜你在找的设计模式相关文章