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:

<?xml version=“1.0″ encoding=“UTF-8″?>
<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:

package org.holewa;

public class FirstBean {
 
}

Klasa SecondBean zawiera akcesory dzięki którym zostanie wstrzyknięta zależność od FirstBean:

package org.holewa;

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:

<?xml version=“1.0″ encoding=“UTF-8″?>
<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?

July 27, 2008 | Leave a Comment