Spring
Links
Spring Eclipse Plugin
Hier findet man ein Spring Eclipse Plugin.
Spring beziehen
Hier gibt es die Spring Libs. In älteren Spring Versionen benötigte man
- dist/spring.jar<li>lib/jakarta-commons/commons-logging.jar</li>
In neueren Spring Versionen benötigt man den kompletten "dist" Ordner und das "commons-logging.jar".
Kleines Spring Tutorial
Eine Klasse für einen (Buch-) Leser. Erst ein Interface
public interface BookReader
{
public void setCreditStatus(String creditStatus);
@Override
public String toString();
}
dann die eigentliche Implementierung
public class BookReaderImpl implements BookReader
{
private BookStore buysBooksAt;
private String creditStatus;
public BookReaderImpl()
{
this.buysBooksAt = new BookStoreOnline();
}
public BookReaderImpl(BookStore pBookLibrary)
{
this.buysBooksAt = pBookLibrary;
}
public void setCreditStatus(String creditStatus)
{
this.creditStatus = creditStatus;
}
@Override
public String toString()
{
return "BookReader [buysBooksAt=" + buysBooksAt + ", creditStatus=" creditStatus + "]";
}
}
Und noch eine Buchverkäufer Klasse. Wieder erste eine Schnittstelle
public interface BookStore
{
public boolean buy(String pTitle);
}
dann die eigentliche Implementierung
public class BookStoreOnline implements BookStore
{
public BookStoreOnline()
{
}
public boolean buy(String pTitle)
{
// ...
}
@Override
public String toString()
{
return "Online Store";
}
}
Jetzt eine XML Datei, kann man z.B. "beans.xml" nennen, oder (vor allem für Webapplikationen) "applicationContext.xml" Den Ordner unbedingt in den Klassenpfad übernehmen.
<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-3.0.xsd">
<bean id="myBookStore" scope="singleton" class="invalid.mypackage.BookStoreOnline" />
<bean id="bookReader" scope="singleton" class="invalid.mypackage.BookReaderImpl">
<constructor-arg ref="myBookStore"/>
<property name="creditStatus" value="BBB" />
</bean>
</beans>
Das Ganze wird dann so benutzt
import org.springframework.beans.factory.*;
import org.springframework.context.support.*;
public class MyMainClass
{
public static void main(String[] args)
{
BeanFactory beanFactory =new ClassPathXmlApplicationContext("beans.xml");
BookReader lBookReader = (BookReader) beanFactory.getBean("bookReader");
System.out.println(lBookReader);
}
}
Autowire
Normalerweise setzt man mit Spring so eine Referenz von buch auf buchLaden:
<bean id="buch" class="Buch">
<property name="buchLaden" ref="buchLaden" />
</bean>
{
private BuchLaden buchLaden;
public BuchLaden getBuchLaden() {
return buchLaden;
}
public void setBuchLaden(BuchLaden buchLaden)
{
this.buchLaden = buchLaden;
}
//...
}
Mit Autowire kann man diese Referenz automatisch setzen lassen. Und das ohne entsprechend Einträge in der XML Datei und der Code benötigt nicht einmal einen entsprechenden Setter:
<bean id="buch" class="autowiredexample.Buch" />
<bean id="buchLaden" class="autowiredexample.BuchLaden" />
public class Buch
{
@Autowired
private BuchLaden buchLaden;
}
Der Einsatz von Autowire ist aber wohl nicht unumstritten.
scope
Spring Einführung, die auch den Scope behandelt
Wenn man von Spring eine Bean geliefert bekommt, ist es noch wichtig, zu wissen, wie lange diese Bean gültig ist, und unter welchen Bedingungen man eine neue Bean erhält.
singleton | (default) Man bekommt immer wieder genau die selbe Bean |
prototype | Man bekommt eine neue Bean |
request | web |
session | web |
globalSession | web |
Spring für Webanwendungen
Einführung: Spring für Webanwendungen
Ein normale Webapplikation starten. Per Contextmenü dem Projekt (mithilfe des Eclipse Spring Plugins) Spring Unterstützung hinzufügen.
Eine kleine Bean erstellen:
import java.io.Serializable;
public class MyHelloWorldBean implements Serializable
{
private String message;
public MyHelloWorldBean()
{
}
public MyHelloWorldBean(String pMessage)
{
setMessage(pMessage);
}
public String getMessage()
{
return message;
}
public void setMessage(String message)
{
this.message = message;
}
}
WEB-INF/applicationContext.xml:
<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-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
>
<bean id="sayHi" scope="singleton" class="foo.MyHelloWorldBean">
<constructor-arg value="Say hello World" />
</bean>
</beans>
WEB-INF/web.xml:
<web-app
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
version="2.5">
<!-- Get spring reference -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<servlet>
<servlet-name>MyServlet</servlet-name>
<servlet-class>foo.MyServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>MyServlet</servlet-name>
<url-pattern>/SayHiServlet</url-pattern>
</servlet-mapping>
</web-app>
Und kann das Servlet dann über Spring auf den Wert in der Bean zugreifen:
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.springframework.context.ApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;
public class MyServlet extends HttpServlet
{
private static final long serialVersionUID = 1L;
public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Hello World!</title>");
out.println("</head>");
out.println("<body>");
// get bean via Spring
ApplicationContext context = WebApplicationContextUtils.getRequiredWebApplicationContext((getServletContext()));
MyHelloWorldBean b=(MyHelloWorldBean) context.getBean("sayHi");
out.println("<h1>"+b.getMessage()+"</h1>");
out.println("</body>");
out.println("</html>");
}
}
JavaServerFaces und Spring
In der faces-config.xml konfigurieren, dass Beans auch über Spring aufgelöst werden
<faces-config xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<application>
<!-- For Spring -->
<variable-resolver>
org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>
<!-- For Spring -->
</application>
</faces-config>
In der web.xml muss, wie beim Servlet Beispiel, auch eine Referenz auf Spring vorhanden sein:
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
In der JSF kann man dann so die Inhalte der Bean ausgeben:
Ist ist dann unerheblich, ob die Bean jetzt über Spring aufgelöst wird, ober durch eine mit
annotierten Klasse.
Aspektorientierte Programmierung (AOP) mit Spring
Aspektorientierte Programmierung
Man hat eine Menge von Methoden. Als erstes schränkt man ein, welche dieser Methoden man beinflussen möchte. Diese Filterbedingung nennt man Pointcut. Eine Methode, die man dabei auswählt hat, nennen man Join-Point. Jetzt definiert man eine neue Methode, die z.B. beim Verlassen der Join-Point Methode aufgerufen werden soll. Diese neue Methode nenne man dann Advice.
Kleines Beispiel für aspektorientierte Programmierung mit Spring
Folgende jars werden benötigt (Spring 3.x)
Aus dem "dist" Order:
- org.springframework.aop-3*
- org.springframework.asm-3*
- org.springframework.beans-3*
- org.springframework.context-3*
- org.springframework.core-3*
- org.springframework.expression-3*
Plus diese hier aus dem großen Spring Paket (mit Dependencies)
- com.springsource.org.aopalliance-1*.jar
- com.springsource.org.aspectj.weaver-1*.jar
beans.xml:
<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-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop> http://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
>
<bean id="myBookStore" scope="singleton" class="invalid.mypackage.BookStoreOnline" />
<bean id="bookReader" scope="singleton" class="invalid.mypackage.BookReaderImpl">
<constructor-arg ref="myBookStore"/>
<property name="creditStatus" value="BBB" />
</bean>
<bean id="myBookStoreBuyAdvice" class="invalid.mypackage.BookStoreBuyAdvice" />
<aop:config>
<!-- <aop:pointcut id="myQueryPointcut" expression="target(invalid.mypackage.BookStore)" /> -->
<aop:pointcut id="myQueryPointcut" expression="execution(Integer buy(java.lang.String))" />
<aop:advisor advice-ref="myBookStoreBuyAdvice" pointcut-ref="myQueryPointcut" />
</aop:config>
</beans>
Neue Bean:
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
public class BookStoreBuyAdvice implements MethodInterceptor
{
public Object invoke(MethodInvocation invocation) throws Throwable
{
System.out.println("Advice started.");
return invocation.proceed();
}
}
Das in eine Main:
{
BeanFactory beanFactory =new ClassPathXmlApplicationContext("beans.xml");
BookReader lBookReader = (BookReader) beanFactory.getBean("bookReader");
System.out.println(lBookReader);
}
Siehe auch:
Spring & JDBC
Spring & Hibernate
Man braucht schon mal folgende jars (Version kann natürlich abweichen)
- com.springsource.antlr-2.7.7.jar
- com.springsource.javax.ejb-3.0.0.jar
- com.springsource.net.sf.cglib-2.2.0.jar
- com.springsource.org.apache.commons.pool-1.3.0.jar
- com.springsource.org.apache.openjpa-1.1.0.jar
- com.springsource.org.hibernate.annotations-3.4.0.GA.jar
- com.springsource.org.hibernate.annotations.common-3.3.0.ga.jar
- com.springsource.org.hibernate.ejb-3.4.0.GA.jar
- com.springsource.slf4j.api-1.5.3.jar
- commons-collections-3.2.jar
- commons-dbcp-1.2.1.jar
- dom4j-1.4.jar
- ejb3-persistence.jar
- hibernate-annotations.jar
- hibernate-commons-annotations.jar
- hibernate3.jar
- jta.jar
- log4j-1.2.14.jar
- ojdbc14.jar
- slf4j-api.jar
- slf4j-log4j12.jar
Das muss in die beans.xml
<bean id="myHibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<property name="properties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle9Dialect</prop>
<prop key="hibernate.cache.provider_class">org.hibernate.cache.NoCacheProvider</prop>
<prop key="hibernate.jdbc.fetch_size">50</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>
<bean id="myDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/>
<property name="url" value="jdbc:oracle:thin:@MyDBServerName:1521:MyDBName" />
<property name="username" value="yourDBAUserName" />
<property name="password" value="yourSuperSecretPasswort" />
</bean>
<bean id="mySessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="myDataSource" />
<property name="annotatedClasses">
<list>
<value>invalid.mypackage.MyDataObject</value>
</list>
</property>
<!--
<property name="mappingResources">
<list>
<value>invalid/mypackage/MyDataObject.hbm.xml</value>
</list>
</property>
-->
<property name="hibernateProperties" ref="myHibernateProperties" />
</bean>
<bean id="myUserDAO" class="invalid.mypackage.UserDAOImpl">
<property name="sessionFactory" ref="mySessionFactory"/>
</bean>
<!-- Hibernate -->
Eine kleine Klasse, die per Annotations gemappt wird:
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
@Entity(name="MyDataObject")
@Table(name="schemaFoo.TableBar")
public class MyDataObject
{
private Integer id;
private String name;
private Integer age;
@Id
public Integer getId()
{
return id;
}
public void setId(Integer id)
{
this.id = id;
}
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public Integer getAge()
{
return age;
}
public void setAge(Integer age)
{
this.age = age;
}
@Transient
@Override
public String toString()
{
return "MyDataObject [id=" + id + ", name=" + name + ", age=" + age + "]";
}
}
Eine Komponente, um auf die Datenbank zuzugreifen:
import java.util.List;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTemplate;
public class UserDAOImpl
{
private HibernateTemplate hibernateTemplate;
public void setSessionFactory(SessionFactory sessionFactory)
{
this.hibernateTemplate = new HibernateTemplate(sessionFactory);
}
@SuppressWarnings("unchecked")
public List<MyDataObject> listMyDataObjects()
{
return hibernateTemplate.find("from MyDataObject");
}
}
Und so greift man dann z.B. zu:
for(MyDataObject d : lDB.listMyDataObjects())
{
System.out.println(d.toString());
}