Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
Можно создавать бины через Spring Java Configuration, то есть напрямую, через параметры конструктора.
@A(queueType = LINKED_BLOCKING_QUEUE)
public class ServiceA {
}
@A(queueType=ARRAY_BLOCKING_QUEUE, queueSize=1000)
public class ServiceB extends ServiceA {
}
public class MyBeanParametersBuilder {
int x;
int y;
ThreadPoolExecutor executor;
public MyBeanParametersBuilder setX(int x) {
this.x = x;
return this;
}
public MyBeanParametersBuilder setY(int y) {
this.y = y;
return this;
}
public MyBeanParametersBuilder setExecutor(ThreadPoolExecutor) {
this.executor = executor;
return this;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
public ThreadPoolExecutor getExecutor() {
return executor;
}
}
@Configuration
public class MyConfiguration {
@Value("${myService.property1}")
int property1;
@Value("${myService.property2}")
String property2;
// very, very long list of properties
@Bean
public MyService myService() {
return new MyService(
property1,
property2,
property3,
property4,
property5,
property6,
property7,
...,
property24
);
}
}
Для сложных случаях давным-давно придумали наследование определений docs.spring.io/spring-framework/docs/current/spring-framework-reference/html/beans.html#beans-child-bean-definitions
Если XML принципиально не хотите, то вот stackoverflow.com/questions/23266175/bean-definition-inheritance-with-annotations
Речь здесь о том, как с помощью декларативного подхода с помощью аннотаций позволять задавать дефолты для контейнера свойств
соблюдать принцип «свойство сервиса — это не сложный объект».
там, где это должен увидеть программист: непосредственно в классе бина
финальных полях бина
Почему бы не использовать стандартные методы спринга? Вы же используете спринг в ваших примерах.
У вас этого как раз и нет. Ваши сервисы знают о выбранном способе параметризации (DemoService<P extends CommonServiceParams & DemoServiceParams> extends AbstractService).
Если прямо в классе нужно использовать ArrayBlockingQueue (например, это критично для конкретно этой реализации), то пусть оно и будет прямо в коде. Если же нет, то ему там делать нечего — конфигурация будет происходить вне кода класса, а сам класс должен использовать интерфейсы.
Я бы задался вопросом — а нужны ли финальные поля? Сервисы создаются 1 раз при старте контейнера.
Spring-way в данном случае — это сеттеры.
Я третий раз говорю одно и то же: статья не о том, как Spring позволяет инжектировать свойства в бины.
P — это не свойство, а тип контейнера свойств. Получив в конструкторе в качестве единственного параметра этот контейнер, класс просетывает финальные поля для свойств.
Зачем в коде задавать явно ArrayBlockingQueue? Речь идет о том, чтобы пользователь имел свободу выбора. В классе потомка задется свойство, которое (все еще) можно переопределить.
Если вы не видите разницы между финальным полем и не понимаете в чем преимущество использования финальных полей для хранения настроек сервиса, когда куча потоков обращается к их значениям очень и очень часто, то не вижу смысла вести бессмысленную дискуссию «финальное поле/не финальное поле».
Я так понимаю, вы уже делали тестирование производительности и точно знаете, что в вашем случае финальные поля дают выигрыш X% по сравнению с нефинальными?
Пользователь должен иметь возможность взять класс и создать нужный ему экземпляр множеством способов: через поля, через XML, через файл свойств.
@CommonServiceParameters(threadCount=8)
@HttpServerParameters(host = "0.0.0.0", port = 80)
class HttpServer extends EmbeddedHttpServer {
}
@CommonServiceParameters(threadCount = 4)
@DataStorageParameters(dir = "/ssd/data", ttl = 1, timeUnit = DAYS)
class DataStorage extends EmbeddedDataStorage {
}
def conf = new Configuration(
new HttpServer(),
new DataStorage()
).start();
сервис работает напрямую с environment, это нехорошо, это лишняя связанность, которая может неприятными моментами всплыть например в тестах
конфигурация «хранится» в аннотациях, на мой взгляд, это неудобно. Намного удобнее использовать для этого бины — они для этого как-то лучше предназначены
Для тестов можно сделать TestBeanConfig implements P1, P2,… P3
не дают конфигурировать бины сложными объектами
… все поля сервиса можно сделать финальными
можно задавать дефолты в том месте, где они должны появляться...
Конфигурирование бинов с помощью аннотаций: решение проблемы с отсутствием наследования для интерфейсов аннотаций