Spring i wstrzykiwanie zależności między bean’ami o różnych zasięgach.
Na pewno wszyscy z Was znają framework (rusztowanie aplikacyjne? LOL) Spring, więc nieobce jest wam hasło Dependency Injection. Wielu z Was codziennie korzysta z dobrodziejstw jakie daje DI, a niektórzy nie są w stanie się bez tego obejść.
Jak wiemy w Springu dostępnych jest kilka zasięgów które określają cykl życia bean’ów (ziaren), bean’y te mogą być od siebie wzajemnie zależne.
Uzależnienie jednego bean’a od drugiego jest w Springu dziecinnie proste i polega na napisaniu kawałka XML:
<beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=“http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd”>
<bean id=“firstBean” class=“org.holewa.FirstBean”/>
<bean id=“secondBean” class=“org.holewa.SecondBean”>
<property name=“firstBean” ref=“firstBean”/>
</bean>
</beans>
Gdzie postać klasy FirstBean jest następująca:
public class FirstBean {
}
Klasa SecondBean zawiera akcesory dzięki którym zostanie wstrzyknięta zależność od FirstBean:
public class SecondBean {
private FirstBean firstBean;
public FirstBean getFirstBean() {
return firstBean;
}
public void setFirstBean( FirstBean firstBean ) {
this.firstBean = firstBean;
}
}
To jest chyba najbardziej trywialny przykład zdefiniowania wzajemnych zależności jaki kiedykolwiek wymyślono ![]()
Obydwa zdefiniowane powyżej bean’y mają ten sam zasięg, który jest domyślnie zasięgiem singleton.
Sytuacja się jednak nieco komplikuje gdy chcemy stworzyć zależności między bean`ami o różnych zasięgach, tu przykładowo zasięg sesji (session) oraz singleton. O ile wykorzystanie singleton’a w bean’ie o zasięgu sesji jest bezproblemowe (dla wszystkich sesji będzie jeden singleton) o tyle sprawa jest bardziej zagmatwana w przeciwną stronę, bo skąd mamy wiedzieć o którą instancję bean’a chodzi, jest ich przecież wiele (jedna per sesja)? Otóż z pomocą przychodzi nam oczywiście Spring i programowanie aspektowe. Dzięki wykorzystaniu AOP Spring tworzy dynamic proxy które to pośredniczy podczas odwołania się do bean’a. Tak powstałe proxy automagicznie (uwielbiam to określenie :D) odnajduje bean’a znajdującego się w zasięgu sesji z której nastąpiło do niego odwołanie i zwraca do niego referencję. Niestety Spring nie jest aż tak automagiczny jakbyśmy chcieli (a może i dobrze :P), dlatego też trzeba w definicji wybranego bean’a (w tym przypadku tego o zasięgu sesji) zastosować specjalny tag który poinformuje Springa, że odwołania do tego bean’a będą odbywać się dzięki zastosowaniu dynamic proxy.
Robi się to następująco:
<beans xmlns=“http://www.springframework.org/schema/beans”
xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
xmlns:aop=“http://www.springframework.org/schema/aop”
xsi:schemaLocation=“http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.0.xsd”>
<bean id=“sessionData” scope=“session”
class=“org.holewa.SessionData”>
<aop:scoped-proxy/>
</bean>
<bean id=“singleton” class=“org.holewa.Singleton”>
<property name=“sessionData” ref=“sessionData”/>
</bean>
</beans>
Klasy Singleton i SessionData są tworzone analogicznie do klas FirstBean i SecondBean.
Taka definicja w zupełności wystarcza do tego aby z poziomu singletona odwoływać się do danych (bean’ów) znajdujących się w zasięgu aktualnej sesji.
Prawda, że proste?








