注解和依赖注入框架

时间:2019-08-19
本文章向大家介绍注解和依赖注入框架,主要包括注解和依赖注入框架使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

注解和依赖注入框架

在开始之前,带着几个问题去看:

  1. 什么是注解?
  2. 注解有什么作用?
  3. 如何使用注解?
  4. 注解的应用场景?
 
注解.png

一、注解及其作用

注解是在JDK 1.5之后引入的,是代码中的特殊标记(以“@注解名”)存在,这些标记可以在编译、类加载、运行时被读取,并执行相应的处理。引用Java编程思想里的描述:注解为我们在代码中添加信息提供了一种形式化的方法,使我们可以在稍后某个时刻非常方便的使用这些数据。


二、注解的分类

可以看上面导图,这里对几个元注解做一下简单说明

  • @Targe:注解所修饰的对象范围。该值是一个ElementType类型的数组,可取值有FILED METHOD等
  • @Retention:用于声明注解的保留策略,可取值有:RetentionPolicy.SOURCE CLASS和RUNTIME,分别表示源码级,编译时和运行时注解;运行时注解可以通过反射来获取该注解信息。

三、使用

3.1 定义注解
下面是一个自定义注解的例子

// 表示该注解为运行时注解,可根据需要设置其为其他两种类型
@Retention(RetentionPolicy.RUNTIME)
// 定义新的注解,使用@interface关键字
public @interface Student {

    // 注解中只有成员变量,没有方法
    // 定义成员变量,为下面这种无参方法的形式
    // 可以使用default关键字为其指定默认值
    String name() default "Joey";

    int age() default 20;
}

// 如果定义了成员变量,使用该注解时,就必须为其指定值
//(定义了default值的情况除外)
@Student(name = "K", age = "21")
public void test() {

}

关于@Retention值的选择:
如果只是做一些检查操作,则使用SOURCE;
如果编译时预处理,例如生成辅助代码,则选择CLASS;
如果运行时动态获取注解信息,则选择RUNTIME

3.2 注解处理器
注解必须配合注解处理器才能有作用,下面是注解处理器实现的一般方法:

  • 针对运行时注解,采用反射机制
  • 编译时注解,采用AbstractProcessor处理
    下面分别看一下:
  1. 运行时注解
    还是用上面的例子,
@Retention(RetentionPolicy.RUNTIME)
public @interface Student {
    String name() default "Joey";

    int age() default 20;
}

public class AnnotationTest {
    @Student(name = "K", age = "21")
    public void test() {

    }   
}

// 下面是一个简单的注解处理器
public class AnnotationProcessor {
    public static void main(String[] args) {
        Method[] methods = AnnotationTest.class.getDeclaredMethods();
        for (Method m: methods) {
            Student student = m.getAnnotion(Student.class);
            System.out.println(student.name() + " " + student.age());
        }
    }
}

getDeclaredMethods和getAnnotion方法都属于AnnotatedElement接口,Class,Method和Filed类都实现了该接口

  1. 编译时注解处理器

四、依赖注入

控制反转(Ioc):即Inversion of Control,用于实现对象间的解耦;指的是借助第三方实现具有依赖关系的对象之间的解耦;
举个例子,假设A和B对象相互依赖,那么当A在运行至某一点时,会主动去创建B的对象或者使用以及创建好的对象B,此时主动权在A手上;当加入IOC对象后,A与B之间失去了直接的联系,当A需要B时,IOC容器会主动创建一个B对象注入A需要的地方。可见,A创建B的过程由主动变为被动,就是控制反转的意思

依赖注入(DI):即Dependency Injection,值IoC容器运行期间,动态的将某种依赖关系注入到对象中。
依赖注入的实现方法:
这里举一个例子:
当代码中需要依赖其他类时,我们可能会这么写

public class Car {
    private Engine engine;

    public Car() {
        engine = new ConcreteEngine();
    }
}

这种方法存在的问题就是耦合度太高,car中需要知道具体的engine实现类,即ConcreteEngine类,一旦engine类型更改,car的构造方法也需要修改
将上面代码改为依赖注入的方法:

public class Car {
    private Engine engine;

    public Car(Engine engine) {
        this.engine = engine;
    }
}

这样一来,Car无需关心Engine的实现,即使后者类型变化了,Car也不需要做任何修改
一些简单的依赖注入方法有:

构造方法注入
Setter方法注入
接口注入

原文地址:https://www.cnblogs.com/isme-zjh/p/11378422.html