运行时的java解析实现

siotufzp  于 2021-07-12  发布在  Java
关注(0)|答案(2)|浏览(416)
// interface defined in Coffee.jar.
interface Coffee {
  void brew();

  void discard();
}

// implementation defined in BlackCoffee.jar
class BlackCoffee implements Coffee {
  @Override
  public void brew() {
    System.out.println("Brew BalckCoffee");
  }

  @Override
  public void discard() {
    System.out.println("Discard BlackCoffee");

  }
}

// implementation defined in FilterCoffee.jar
class FilterCoffee implements Coffee {

  @Override
  public void brew() {
    System.out.println("Brew FilterCoffee");

  }

  @Override
  public void discard() {
    System.out.println("Discard FilterCoffee");

  }
}

// Runtime class in Coffee.jar
class BrewCoffee {
  public static void main(String[] args) {
    Coffee coffee = //something here;
    coffee.brew();
    coffee.discard();
  }
}

然后,在不知道实现的情况下在运行时解析实现。该应用程序的依赖项是coffee.jar,依赖项来自blackcoffee.jar或filtercoffee.jar。

v6ylcynt

v6ylcynt1#

这是依赖注入框架(如spring)的优点之一。
您编写了接口代码,而您的客户机类不知道在运行时示例化了哪个实现。
您可以根据条件选择哪一个,例如在spring中可以使用@conditional属性

@ConditionalOnProperty("coffee.black")
class BlackCoffee implements Coffee 

@ConditionalOnProperty("coffee.filter")
class BlackCoffee implements Coffee

然后有

@Component
class ClassUsingCoffee {
    private Coffee coffee;

    @Inject
    public ClassUsingCoffee(Coffee coffee) {
        this.coffee = coffee;
    }

    //use coffee as normal
}

然后在spring的属性中,您可以定义属性“black”或“filter”来激活两个具体类实现中的一个。如果您同时定义了这两个属性,您将得到一个异常,说明存在两个coffee示例,并且它不知道将哪个(依赖注入)注入到您的应用程序中 ClassUsingCoffee
如果不深入了解spring的细节,很难解释。但你也可以用 ApplicationContext (把它想象成一个包含spring所知道的所有类的“东西”)

class BrewCoffee {
  public static void main(String[] args) {
        ApplicationContext ctx = //omitted for brevity
        Coffee coffee = ctx.getBean(Coffee.class);
        coffee.brew();
        coffee.discard();
  }

在这两个示例中,您都将类与 Coffee 接口而不是具体的实现。e、 如果你做了 Coffee coffee = new BlackCoffee() 然后您的代码被耦合到coffee的特定实现(在本例中) BlackCoffee )任何需要的更改都需要代码更改(与配置/属性更改相反)

qij5mzcb

qij5mzcb2#

如果您希望选择接口的实现,因为类路径上存在实现的jar文件,那么您应该使用服务加载器框架。
查看java™ 教程-创建可扩展的应用程序以获取更多信息。
在您的情况下,首先组织代码,即将类放入包中:

package com.example.api;

public interface Coffee {
    ...
}
package com.example.black;

import com.example.api.Coffee;

public class BlackCoffee implements Coffee {
    ...
}
package com.example.filter;

import com.example.api.Coffee;

public class FilterCoffee implements Coffee {
    ...
}
package com.example;

import com.example.api.Coffee;

public class BrewCoffee {
    public static void main(String[] args) {
        for (Coffee coffee : ServiceLoader.load(Coffee.class)) {
            coffee.brew();
            coffee.discard();
        }
    }
}

然后像这样 Package :
com/example/api/Coffee.class 在文件中 coffee.jarcom/example/black/BlackCoffee.class 在文件中 black.jar 与文件一起 META-INF/services/com.example.api.Coffee 有内容的 com.example.black.BlackCoffeecom/example/filter/FilterCoffee.class 在文件中 filter.jar 与文件一起 META-INF/services/com.example.api.Coffee 有内容的 com.example.filter.FilterCoffeecom/example/BrewCoffee.class 在文件中 brew.jar 现在可以使用以下命令之一运行程序:

java -cp brew.jar;coffee.jar;black.jar com.example.BrewCoffee
java -cp brew.jar;coffee.jar;filter.jar com.example.BrewCoffee
java -cp brew.jar;coffee.jar;black.jar;filter.jar com.example.BrewCoffee

注意:在linux上,替换 ;: 自从 main 方法在所有实现中循环,第三个命令将同时运行这两个实现 BlackCoffee 以及 FilterCoffee .

相关问题