Postanowiłem spróbować swoich sił i wdrożyć Spring Framework do projektu. Projekt jest już przy końcu cyklu wytwarzania i w zasadzie niedługo trafi do produkcji, a później utrzymania, jednakże sądzę, że zawsze jest czas na udoskonalenia (zapewne niejednego aż zmroziło przypominając sobie, jak ślęczał godzinami przed komputerem, w nocy, aby odszukać i poprawić błąd zgłoszony w środowisku produkcyjnym, właśnie po tym, jak chwilę przed oddaniem projektu i świętowaniem jego sukcesu, wdrożono jedno fascynujące rozwiązanie). Mimo takich doświadczeń i spędzenia niejednej nocy nad rozwiązywaniem problemów "na wczoraj", wierzę, że dobre rozwiązanie to takie, które da się przetestować bez zestawiania środowiska produkcyjnego, które po prostu da się przetestować. Wszystko zawsze i tak zależy w dużej mierze od doświadczenia zespołu, ale jego brak nie powinien powstrzymywać "wizjonerów" od działania. Nie potrafię jednoznacznie określić, czy zastosowanie Springa w danym kontekście będzie lepsze od innych kontenerów IoC (ang. Inversion of Control - inna nazwa wzorca Przekazywania Zależności), m.in. PicoContainer, ale jak na początek mojego zabiegu wstrzykiwania Springa (z nadzieją odrodzenia projektu z popiołów), brak jakiejkolwiek zależności od środowiska i brak koniecznych modyfikacji istniejącego kodu bardzo przypadł mi do gustu. Dodatkowo, zmiany, które będzie można łatwo wdrożyć w projekcie, podniosą jakość oprogramowania przez dokładniejsze jego testowanie. Jest to kolejna cecha kontenerów IoC (Spring Framework, PicoContainer), która upraszczaa testowanie aplikacji na nich opartych. Często spotykamy się z sytuacjami, w których środowisko produkcyjne będzie wymagało zaawansowanych konfiguracji, których próba uruchomienia na własnym komputerze byłaby (delikatnie mówiąc) nierozsądna. Dzięki Spring Framework, projekt zwiększy możliwości testowania przez dostarczenie zależności odpowiednich do środowiska. Zależności mogą być różnorakie: klasa obsługująca bazę danych, moduł bezpieczeństwa, moduł transakcyjny, czy moduł odpowiedzialny za wyrysowywanie grafiki. Zakładając, że owe zależności są już przetestowane - są oddzielnymi projektami żyjącymi własnym cyklem rozwojowym - nie ma potrzeby testować ich ponownie, a ich zastąpienie przez tzw. imitacje obiektów (ang. mock objects) znacząco przyspieszy i umożliwi testowanie w innych, skromniejszych, warunkach. Docelowo i tak czekają nas testy różnego rodzaju (wydajnościowe, funkcjonalne, regresyjne, etc.) w środowisku testowym, jednakże możliwość uruchomienia choćby ich wycinka pozwala na wprowadzanie modyfikacji w dowolnej chwili, nawet "za pięć dwunasta" z całą świadomością ich znaczenia i wpływu na cały projekt.
Pobieramy projekt Spring Framework ze strony domowej projektu - http://www.springframework.org/download. Instalacja sprowadza się do rozpakowania paczki do dowolnego katalogu.
Na początek naszej przygody ze Spring Framework, rozważmy bardzo uproszczoną klasę - pl.org.laskowski.WelcomeBean.
package pl.org.laskowski;Klasa nie wyróżnia się niczym specjalnym - jest po prostu klasą udostępniającą właściwość configFilename oraz bezparametrową metodę execute. Mimo swej prostoty jej działanie jest uzależnione od świata zewnętrznego - pliku konfiguracyjnego. Bez niej klasa nie będzie poprawnie funkcjonować (zakładamy, że wyświetlenie null nie należy do kategorii "aplikacje poprawnie działające").
public class WelcomeBean {
private String configFilename;
public String getConfigFilename() {
return configFilename;
}
public void setConfigFilename(String configFilename) {
this.configFilename = configFilename;
}
public void execute() {
System.out.println("Witaj!");
System.out.println("Korzystam z pliku konfiguracyjnego " + getConfigFilename());
}
}
Teraz przyjrzyjmy się plikowi XML - beans.xml.
<?xml version="1.0" encoding="UTF-8"?>Zrozumienie zawartości pliku jest trywialne - plik sam uzasadnia swoje istnienie. Poprzez znacznik property ustawiana jest zmienna instancji wskazana przez atrybut name na wartość wskazaną przez value. Skoro znacznik property jest zagnieżdżony w bean wskazuje to na jego przynależność - klasę wskazywana przez atrybut class znacznika bean.
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN"
"http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<bean id="welcomeBean" class="pl.org.laskowski.WelcomeBean">
<property name="configFilename" value="config.xml"/>
</bean>
</beans>
Jak można odczytać z (opcjonalnego) DOCTYPE jest to plik konfiguracyjny dla klasy org.springframework.beans.factory.xml.XmlBeanFactory należącej do Spring Framework. W naszym rozwiązaniu będzie to element kluczowy w naszym wdrażaniu Springa. Przyjrzyjmy się zatem jak uruchomić Spring Framework tak, aby on z kolei uruchomił naszą klasę - pl.org.laskowski.WelcomeBean. Stworzymy do tego celu klasę - pl.org.laskowski.Main.
package pl.org.laskowski;Do uruchomienia aplikacji będą nam potrzebne następujące biblioteki:
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.ClassPathResource;
public class Main {
public static void main(String[] args) {
XmlBeanFactory bf = new XmlBeanFactory(new ClassPathResource("beans.xml"));
WelcomeBean tb = (WelcomeBean) bf.getBean("welcomeBean");
tb.execute();
}
}
- spring-framework.jar
- commons-logging.jar
java pl.org.laskowski.MainBardzo istotnym elementem wdrażania Spring Framework jest fakt braku koniecznych modyfikacji. Jak można zauważyć w przykładowej klasie pl.org.laskowski.WelcomeBean, klasa nie posiada żadnych dodatkowych obciążeń, czego wynikiem mogłoby być wykorzystanie Spring Framework.
Daje to możliwość rozważnego wdrażania do projektu, bez niepotrzebnej rewolucji w sposobie wytwarzania aplikacji, szczególnie w ostatnich dniach projektu (które zwykle i tak nie są ostatnimi). Dalszy rozwój aplikacji odbywa się bez jakichkolwiek zmian, a jedynie finalna klasa uruchamiająca projekt ulegnie zmianie.
Oczywiście wykorzystanie Springa z jego dostarczaniem zależności zdejmuje konieczność inicjowania i konfiguracji usług zewnętrznych, co często obciąża niepotrzebnie wielu członków zespołu. W sytuacji, kiedy zależność jest dostarczana, korzystamy z założenia, że została ona zainicjowana i przekazana zanim klasa została uruchomiona. Znacząco wpływa to na zmniejszenie ilości kodu do utrzymania przez zespół programistów.
Komentarze, spostrzeżenia i uwagi (szczególnie krytyczne) mile widziane. Pomysły na następne artykuły również. Skorzystaj z możliwości komentowania artykułu, poniżej.
Bardzo przydatny artykuł dla początkujących. Pozwala bardzo szybko uruchomić pierwszą przykładowa aplikację, co wg mnie umozliwia szybkie wejscie w temat i zachęca do użycia Springa. Dobry pomysł.
OdpowiedzUsuńWielkie Dzięki.
Bardzo pożyteczny blog.
OdpowiedzUsuńKeep up the good work :)
Świetny artykuł, najlepszy jaki znalazłem o Springu na początek - po kolei wyjaśniasz jak działa IoC, po co to komu i dobry przykład wykorzystania Spring Framework.
OdpowiedzUsuńZ springframework zetknalem sie niedawno, a przeczytanie tego artkulu znacznie przyczynilo sie do zrozumienia ideii dzialania spring'a. Oby wiecej bylo takich artykulow..
OdpowiedzUsuńWitam serdecznie bardzo dobre artykuły, zauważyłem ze prosiłeś o ewentualne pomysły na następne. Mam pomysł powiązany z problemem, interesuje mnie rozwiązanie dotyczące springa i jego modułowości a dokładnie połączenia kilku plikow jar w jednej aplikacji i ciagniecie beanow przez @Autowired
OdpowiedzUsuń@kr, Odnotowane. Temat czeka na swoją kolej. Kiedy? Pewnie niebawem.
OdpowiedzUsuń