Просто вставьте его в класс, который вызывает правила (обычно Java), и передайте экземпляр в рабочую память при вызове правил.
Итак, если у вас есть, скажем, класс RuleInvoker, который вызывает правила ...
public class RuleInvoker {
@Inject
MyBean myBean;
public void invokeRules() {
KieSession kieSession = ...;
kieSession.insert( myBean ); // insert into working memory like any other fact
// insert other facts, etc here, then fire rules
kieSession.fireAllRules();
// ... etc
}
}
Я сделал инъекцию зависимостей, как это, используя Spring. Никаких дополнительных зависимостей, которые вы еще не используете, не требуется.
Для пояснения приведу небольшой пример с игрушкой.
Скажем, изначально у меня был класс Tax, который я Первоначально создавал новый экземпляр в правилах, а затем использовал в последующих правилах:
rule "Insert Tax"
when
not (Tax())
then
insert(new Tax())
end
rule "Apply Tax to Alcohol"
when
$tax: Tax()
$purchase: Purchase( includesAlcohol == true )
then
$purchase.apply(tax, TaxType.ALCOHOL);
end
// Other rules eg. apply tax to lottery tickets, apply tax to groceries, etc.
Теперь я должен изменить свой дизайн, чтобы поддерживать разные схемы налогообложения для двух разных регионов. Эти схемы налогообложения будут введены; в этом случае я буду использовать аннотацию Spring @Autowired
, но @Inject
аналогичен.
Для моего надуманного примера я бы преобразовал Tax
в интерфейс, а затем другие налоговые схемы просто реализовали бы этот интерфейс , Поскольку все правила написаны против налога, правила, таким образом, не нуждаются в изменении.
public interface Tax {
String getRegion();
// other methods previously on Tax class
}
public class RegionATax implements Tax { ... }
public class RegionBTax implements Tax { ... }
public class RegionCTax implements Tax { ... }
Поскольку я больше не могу обновлять свои налоговые отчеты, мне нужно вывести их в контекст, поместив их в рабочую память вручную.
public class RuleInvoker {
@Autowired
List<Tax> taxSchemes; // injects all tax schemes (implementors of Tax interface)
public void invokeRules(Purchase purchase) {
KieSession kieSession = ...;
for (Tax tax : taxSchemes) {
kieSession.insert( tax ); // insert into working memory like any other fact
}
// insert other facts, etc here, then fire rules
kieSesion.insert(purchase);
kieSession.fireAllRules();
// ... etc
}
}
И, наконец, правило «Включить налог» необходимо будет заменить правилом, которое определит, какую налоговую схему целесообразно использовать. В этом особенно надуманном примере, поскольку я не предоставлял себе никаких полезных методов, я просто собираюсь отозвать все несовместимые налоги, которые не соответствуют региону покупки.
rule "Filter incompatible tax regions"
salience 1
when
Purchase( $region: region )
$incompatibleTaxRegion: Tax( region != $region )
then
retract( $incompatibleTaxRegion )
end
// Other rules remain the same since they're referencing the Tax interface
Я решил использовать отличие, чтобы гарантировать, что правило фильтра вызывается до обычных правил. Для этого лучше создать отдельную группу повестки дня.
В конце концов, вы не можете внедрять напрямую в контекст правила, потому что какая бы библиотека CDI вы не использовали, не управлять жизненным циклом рабочей памяти / правилом контекста. Вместо этого решение состоит в том, чтобы передать объект в правила, жизненный цикл которых контролируется , управляемым вашей библиотекой CDI.
Самый простой способ сделать это - просто передать бины напрямую в рабочую память в виде фактов или глобальных переменных. Другими решениями, которые я видел, являются передаваемые классы «инжекторов». Мне когда-то приходилось управлять набором правил, в котором контекст приложения Spring полностью передавался в правила (что-то вроде кошмара для работы с tbh.)
Если вы не хотите передавать бины напрямую, вы можете создать своего рода класс «инжектор» в качестве держателя бина, вставить , что , в класс вызывающего правила, а затем разрешить правила разберитесь, что им нужно. Я совсем не знаком с Weld, но если он делает доступным контекст приложения, который вы можете внедрить, вы также можете передать это в правила. Но все эти решения требуют, чтобы вы как-то корректировали правила, как минимум, чтобы удалить или обновить исходное insert( new MyLibraryClass())
правило.