2013-05-24 8 views
0

Позвольте мне начать с примера. Предположим, что существует Factory inteface и клиентов класса:Как переключаются проекты maven?

public interface CustomerFactory(){ 
    Customer create(); 
} 

public class Customer(){ 
    private String name; 

    public String getName(){ 
     return name; 
    } 

    public void setName(String name){ 
     this.name = name; 
    } 
} 

Пусть у меня есть CustmerProject Maven проект, который нуждается в CustomerFactory. Я хотел создать несколько проектов maven с Реализация CustomerFactory (одна реализация для каждого проекта cource), но я не хочу, чтобы CustmerProject будет зависеть от всех этих проектов реализации. Я хочу создать один CustomerFactoryIntefaceProject, который CustmerProject будет зависеть от и поставить один из CustomerFactoryImplementationProject как CustomerFactoryIntefaceProject. Я знаю, что это возможно, но как я могу это сделать на практике?

P.S. Если вопрос непонятен, спросите меня.

ответ

1

я нашел решение, которое очень похоже на Сообщение Macias, но из реального кода.

Основная идея состоит в том, чтобы поместить класс-заглушку в проект «интерфейс», добавить плагин, который будет удалять классы-заглушки во время фазы технологических процессов, сделать проект реализации «зависит от» и создать класс с реальным кодом с помощью тот же пакет и имя класса как заглушка.

Давайте посмотрим SLF4J проект, как, например, вы можете загрузить исходные файлы из http://www.slf4j.org/download.html

Основным проектом является SLF4J-апи, который содержит интерфейсы: Logger, LocationAwareLogger (расширяет Logger), ILoggerFactory и др. Также он содержит LoggerFactory класс (и несколько классов полезности), который используется, например, при создании регистратора:

private static final Logger logger = LoggerFactory.getLogger(SomeClass.class); 

Это API-интерфейс «inteface».

Для "реализации" API SLF4J-апи проект содержит осущ пакет с 3 окурка классов: StaticLoggerBinder, StaticMarkerBinder и StaticMDCBinder, какие методы используются в LoggerFactory класса, но в SLF4J-апи проект они бросают UnsupportedException.

Теперь давайте посмотрим на SLF4J-jdk14 проекта, который зависит от SLF4J-апи и содержит только осущ пакет с 3 предыдущих упомянутых классов: StaticLoggerBinder, StaticMarkerBinder и StaticMDCBinder; и JDK14LoggerAdapter, JDK14LoggerFactory, который реализует LocationAwareLogger и ILoggerFactory из SLF4J-апи. Но они не являются заглушками, они имеют реальный код, например StaticLoggerBinder возвращает JDK14LoggerFactory, который производит JDK14LoggerAdapter.

Теперь давайте посмотрим, где волшебство Мавена. Напомним, что проекты «inteface» и «реализация» имеют одинаковые классы StaticLoggerBinder, StaticMarkerBinder и StaticMDCBinder. Посмотрите на SLF4J-апиpom.xml и найти построить тег:

<project> 
    ... 
    <groupId>org.slf4j</groupId> 
    <artifactId>slf4j-api</artifactId> 
    ... 
    <build> 
     <plugins> 
      <plugin> 
       <groupId>org.apache.maven.plugins</groupId> 
       <artifactId>maven-antrun-plugin</artifactId> 
       <executions> 
       <execution> 
        <phase>process-classes</phase> 
        <goals> 
         <goal>run</goal> 
        </goals> 
       </execution> 
       </executions> 
       <configuration> 
       <tasks> 
        <echo>Removing slf4j-api's dummy StaticLoggerBinder and StaticMarkerBinder</echo> 
        <delete dir="target/classes/org/slf4j/impl"/> 
       </tasks> 
       </configuration> 
      </plugin> 
     </plugins> 
    </build> 
    ... 
</project> 

Поскольку SLF4J-jdk14 зависит от SLF4J-апи, SLF4J-апи устроится первым, после чем плагин delete stubs и slf4j-jdk14 Продолжается строительство и помещает фактические классы «реализаций» вместо «заглушек».

+0

Решение SLF4J работает очень плохо в среде OSGi, и даже Ceki допускает, что он не очень модульный. Он застрял, сохраняя обратную совместимость, но для нового дизайна, вероятно, лучше рассмотреть альтернативное решение, такое как DI или поиск службы (например, java.util.ServiceLoader). –

+0

Может ли ссылка с подробной информацией о проблеме с OSGi? – Cherry

+0

Эта тема - лучшее, что я могу найти прямо сейчас. Я посмотрю, смогу ли я найти цитату из Цэки. http://mailman.qos.ch/pipermail/slf4j-dev/2012-October/003714.html –

1

Вы можете параметризовать artifactId или версию CustomerFactoryImplementationProject и использовать профили maven для выбора реализации во время сборки.

Скажем у вас есть следующие артефакты:

  • клиента
  • клиент-завод-1
  • клиент-завод-2

Так в pom.xml проекта клиента вы потребуется:

<dependency> 
    <groupId>base</groupId> 
    <artifactId>${customer.factory.artifact}</artifact> 
    <version>123</version> 
</dependency> 
.... 
<profiles> 
    <profile> 
     <id>customerFactory1</id> 
     <properties> 
      <customer.factory.artifact>customer-factory-1</customer.factory.artifact> 
     </properties> 
    </profile> 
    <profile> 
     <id>customerFactory2</id> 
     <properties> 
      <customer.factory.artifact>customer-factory-2</customer.factory.artifact> 
     </properties> 
    </profile> 
</profiles> 

А теперь просто выбрать профиль во время сборки, как это:

mvn -P customerFactory2 install 

... или на самом деле вы можете профилировать блок зависимостей непосредственно:

<profiles> 
    <profile> 
     <id>customerFactory1</id> 
     <dependencies> 
      <dependency> 
       <groupId>base</groupId> 
       <artifactId>customer-factory-1</artifact> 
       <version>123</version> 
      </dependency> 
     </dependencies> 
    </profile> 
    <profile> 
     <id>customerFactory2</id> 
     <dependencies> 
      <dependency> 
       <groupId>base</groupId> 
       <artifactId>customer-factory-2</artifact> 
       <version>123</version> 
      </dependency> 
     </dependencies> 
    </profile> 
</profiles> 
+0

ОК, но как насчет классов Java? В базовом проекте я должен написать что-то вроде этого «StaticClass.geFactory()», которое возвращает CustomerFactoryImpl из проектов customer-factory-1 или customer-factory-2, но как я могу написать этот код, если я не знаю, какая реализация будет используемый? – Cherry

+0

Проект не должен компилироваться с использованием любого класса реализации. Завод должен вернуть объект интерфейса, фактически являющийся неизвестным экземпляром класса реализации. Для этого добавьте в зависимость от maven ' время выполнения'. –

+0

Я предполагаю, что оба клиента-фабрики-1 и 2 предоставляют CustomerFactoryImpl в том же пакете. Вы также можете установить один из этих профилей по умолчанию, иначе IDE, возможно, немного запутается. – macias

Смежные вопросы