Сибирские интеграционные системы
AngularSIS #1.18 - https://www.youtube.com/playlist?list=PLmEQRj1_Mt5fkeBYOw1o8k_o8-7POFZJN JavaSIS #2.19 - https://www.youtube.com/playlist?list=PLmEQRj1_Mt5f5MlXGlf5kzldb9Rl8Pwuo
Занятие № 6
Spring Core
Кернер
Денис
Нет, погодите. А что за Spring?
Шел 2002 год, господствовала технология JEE
Много инфраструктурного кода приводило к:
В 2002 вышла книга Рода Джонсона с попыткой пересмотреть подход JEE.
К книге прилагался репозиторий с первой версией фреймворка
JEE стал проще и легче, копируя Spring :)
Программист работает с POJO
POJO (plain old java object)
Объекты, с которыми вы работаете, должны как можно меньше знать о фреймворке
Ядро фреймворка отвечает за:
Зачем?
Ситуация:
Мы хотим рассчитать цену на товар.
private BigDecimal calculateProductPriceForClient(
Client client, Product product
) {
DataSource dataSource = new DataSource("url to db");
ProductRepository productRepository =
new ProductRepository(dataSource);
ProductPriceRepository productPriceRepository =
new ProductPriceRepository(dataSource);
ProductService productService =
new ProductServiceImpl();
return productService.calculatePrice(product,
productPriceRepository, productRepository);
}
Мы жестко контролируем создание нужных классов
Мы должны использовать уже готовый объект.
private final ProductService productService;
private BigDecimal calculateProductPriceForClient2(Client client,
Product product) {
return productService.calculatePrice(product,
productPriceRepository, productRepository);
}
Переворачиваем цепочку контроля.
Что же такое IoC?
IoC - инверсия управления
"Не звоните нам, мы сами позвоним вам!"
Основными способами являются:
private ProductService productService;
public void setProductService(ProductService productService) {
this.productService = productService;
}
public PriceCalculator(ProductService productService) {
this.productService = productService;
}
Как думаете, какой способ лучше?
APPLICATION FAILED TO START
Description:
The dependencies of some of the beans
in the application context form a cycle:
wsConfig defined in file
[C:\gitlab\citizenfeedback\server\build\classes\
java\main\pro\sisit\etalon\citizen\feedback\
config\WsConfig.class]
| syncServiceImpl defined in file
[C:\gitlab\citizenfeedback\server\build\classes
\java\main\pro\sisit\etalon\citizen\
feedback\sync\SyncServiceImpl.class]
Объект, отвечающий за хранение бинов и внедрение зависимостей (DI).
POJO, создаваемый и управляемый Spring IoC контейнером
Bean можно внедрять через DI
private final ProductService productService;
public PriceCalculator(ProductService productService) {
this.productService = productService;
}
Все это хранится в специальном интерфейсе BeanDefinition и грузится из конфигурации.
Основные
Только для веб:
А мне говорили, что singleton это плохо!
Работу singletone обеспечивает Spring.
Использовать можно, если помнить противопоказания
public class ServiceAntiPattern {
private BigDecimal debtSum;
private DebtService debtService;
private InterestService interestService;
public BigDecimal CalculateDebtOnToday(Client client) {
loadCurrentDebt(client);
calculateInterest();
return debtSum;
}
private void loadCurrentDebt(Client client) {
debtSum = debtService.loadDebt(client);
}
private void calculateInterest(Client client) {
debtSum = interestService.calculateInterest(client, debtSum);
}
}
private class ServiceAntiPatternState {
private CreateObjectDetails createObjectDetails;
public void initName(String name) {
createObjectDetails.name = name;
}
public void createObject(Long id) {
createObjectDetails.id = id;
return save(createObjectDetails);
}
}
В промежутке между вызовами initName и createObject - могут вызвать еще раз initName
Если нужно вставлять в класс бины и при этом хранить в классе состояние:
Небольшой пример - сервис, выдающий домашних питомцев.
PetService
Плюсы
Минусы
Объявляем бины в коде
Классы с конфигурацией помечаем @Configuration
@Configuration
public class DataConfiguration {
@Bean(name = "laborDataRep")
public LaborDataService laborDataService() {
return new LaborDataServiceImpl();
}
}
Плюсы
Минус
Аннотации служат для
Рассмотрим приложение для приветствий
Почему оно не работает?
Ранее мы явно определяли зависимости.
Этот код не говорит, что нужно инжектировать бин:
void setGreeterService(GreeterService greeterService) {
this.greeterService = greeterService;
}
Аннотация @Autowired на поле\сеттере\ конструкторе заставляет IoC искать подходящий бин.
На единственный конструктор в объекте спринг всегда вешает аннотацию @Autowired
Плюс
Минусы
Мы рассмотрели все существующие способы конфигурирования
На практике мы используем смесь аннотаций и JavaBased
Рекомендуемые способы:
Также см. InitializingBean и DisposableBean
Из полезного
Язык выражений Spring Framework
Может использовать методы и классы Spring и Java, может работать с контекстом
Demo
Вывод - мощно.
@PreAuthorize("hasPermission(#contact, 'admin')")
void deletePermission(Contact contact, Sid recipient,
Permission permission);
Мощно. Непонятно. Волшебно.
Есть уязвимости. Использовать с осторожностью
Позволяет использовать кросс функционал в вашем коде с помощью аннотаций
Примеры:
@Transactional
public void placeOrder(Order order) {
order.statusOrdered();
shipService.planShipping(order);
orderRepository.saveOrder(order);
}
Proxy
Spring создает класс-обертку вокруг вашего класса, с теми же методами.
При получении бина вы получаете прокси, который и делает сначала магию, а потом вызывает ваш код.
!!!method2 вызовет не прокси!!!
public class MyServiceImpl {
@Transactional
public void method1() {
//do something
method2();
}
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void method2() {
//do something
}
}
By Сибирские интеграционные системы
Работа со Spring Core