570 likes | 690 Views
Spring. Paul Jensen Principal, Object Computing Inc. Spring Overview. “Lightweight Container” Very loosely coupled Components widely reusable and separately packaged Created by Rod Johnson Based on “Expert one-on-one J2EE Design and Development” Currently on version 1.1.1.
E N D
Spring Paul Jensen Principal, Object Computing Inc.
Spring Overview • “Lightweight Container” • Very loosely coupled • Components widely reusable and separately packaged • Created by Rod Johnson • Based on “Expert one-on-one J2EE Design and Development” • Currently on version 1.1.1
Why Use Spring? • Wiring of components (Dependency Injection) • Promotes/simplifies decoupling, design to interfaces, TDD • Declarative programming without J2EE • Easily configured aspects, esp. transaction support • Simplify use of popular technologies • Abstractions insulate application from specifics, eliminate redundant code, and handle common error conditions • Underlying technology specifics still accessible (closures)
Why Use Spring? • Conversion of checked exceptions to unchecked • (Or is this a reason not to use it?) • Not an all-or-nothing solution • Extremely modular and flexible • Well designed • Easy to extend • Many reusable classes
Spring Dependency Injection • Inversion of Control (IoC) • “Hollywood Principle” • Don't call me, I'll call you • “Container” resolves (injects) dependencies of components by setting implementation object (push) • As opposed to component instantiating or Service Locator pattern where component locates implementation (pull) • Martin Fowler calls Dependency Injection
Dependency Injection Variants • Variations on dependency injection • Interface based (Avalon) • Constructor-based (PicoContainer, Spring) • Setter-based (Spring) • BeanFactory provides configuration framework to initialize and “wire” JavaBeans • org.springframework.beans and org.springframework.context • Typically use the XmlBeanFactory, employing XML configuration files
Dependency Injection (cont'd) • BeanFactory configured components need have no Spring dependencies • Simple JavaBeans • Beans are singletons by default • Properties may be simple values or references to other beans • Built-in support for defining Lists, Maps, Sets, and Properties collection types. • Custom PropertyEditors may be defined to convert string values to other, arbitrary types.
XmlBeanFactory Example • Property and constructor based IoC <bean id="exampleBean" class="examples.ExampleBean"> <property name="beanOne"><ref bean="anotherExampleBean"/></property> <property name="beanTwo"><ref bean="yetAnotherBean"/></property> <property name="integerProperty">1</property> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/> <bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg> <constructor-arg><ref bean="yetAnotherBean"/></constructor-arg> <constructor-arg><value>1</value></constructor-arg> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean"/>
Bean Creation • Direct instantiation • <bean id=“beanId” class=“className”> • BeanFactory instantiation • Same syntax but class is subclass of BeanFactory • getObject() called to obtain Bean • Static Factory • <bean id=“beanId” class=“className" factory-method=" staticCreationMethod“> • Instance Factory Method • <bean id=“beanId” factory-bean=“existingBeanId" factory-method=“nonStaticCreationMethod">
Bean Creation • Beans may be singletons or “prototypes” • Attribute singleton=“false” causes instantiation with each getBean() lookup • Singleton is default • XmlBeanFactory pre-instantiates singletons • May be overridden on per-instance basis by lazy-init=“true” • Beans may also be marked abstract, allowing reuse of attribute values through inheritance
Autowiring Properties • Beans may be auto-wired (rather than using <ref>) • Per-bean attribute autowire • Explicit settings override • autowire=“name” • Bean identifier matches property name • autowire=“type” • Type matches other defined bean • autowire=”constructor” • Match constructor argument types • autowire=”autodetect” • Attempt by constructor, otherwise “type”
Dependency Checking • Ensures properties are defined • Per-bean attribute dependency-check • None required by default • Verifies autowiring succeeded • “simple” • all but collaborators • “object” • collaborators only • “all” • Collaborators, primitive types, and collections
Lifecycle Customization • Can define init method called after properties set • init-method=”<method-name>” • Can define destroy method as shutdown hook • destroy-method=”<method-name>” • May alternatively implement InitializingBean and/or DisposableBean • At cost of Spring dependency
BeanFactory Miscellany • BeanFactoryAware interface provides BeanFactory for bean • setBeanFactory(BeanFactory) • BeanNameAware interface provides bean name • setBeanName(String) • FactoryBean for beans which are themselves factories • Object getObject() • Boolean isSingleton() • Class getObjectType()
BeanFactory Usage InputStream is = new FileInputStream("beans.xml"); XmlBeanFactory factory = new XmlBeanFactory(is); MyBeanClass bean = (MyBeanClass)factory.getBean(“myBean”); OR ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml"); MyBeanClass bean = (MyBeanClass)ctx.getBean(“myBean”);
ApplicationContext • Extends functionality of BeanFactory • Pre-instantiates singleton beans • Detects and registers BeanPostProcessors and BeanFactoryPostProcessors • Supports nesting of contexts • ApplicationListener and ApplicationEvents • Initialized and closed predefined • Custom may be created • MessageSource provides i18n messaging • <bean id=”messageSource” class=”...ResourceBundleMessageSource”/> • Contains list of bundle base names
Web Initialization • Web applications may use ContextLoaderListener to initialize Spring web.xml <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/daoContext.xml /WEB-INF/applicationContext.xml </param-value> </context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> Automatically done by Spring DispatcherServlet
Specialized Beans • MethodInvokingFactoryBean • Invokes method on registered beans or any static methods • Stores return value • SingletonBeanFactoryLocator and ContextSingletonBeanFactoryLocator • Useful for sharing BeanFactories • Eliminate duplication of beans in multiple similar factories or contexts
ApplicationContext customization • Defined beans inheriting from BeanFactoryPostProcessor are detected and invoked • CustomEditorConfigurer • Registers custom PropertyEditors for converting configuration string values to specific types • AutoProxyCreators • Wrap beans in proxies based on various criteria (name, metadata, etc) • PropertyResourceConfigurer • Sets from property file and/or system properties
ApplicationContext Example <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"><value>database.properties</value></property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>${database.connection.driver_class}</value> </property> <property name="url"> <value>${database.connection.url}</value> </property> </bean>
AOP Fundamentals • Aspect-oriented programming (AOP) provides for simplified application of cross-cutting concerns • Transaction management • Security • Logging • Auditing • Locking • AOP sometimes (partially) achieved via Decorators or Proxies • CORBA Portable Interceptors • Servlet Filters
AOP Fundamentals • Aspect - Implementation of a cross-cutting concern. • Spring Advisors or Interceptors • Joinpoint - Execution point to target • Typically, methods • Advice - Action taken at a particular joinpoint. • Pointcut - A set of joinpoints specifying where advice should be applied (e.g. Regular expression) • Introduction/Mixin - Adding methods or fields to an advised class. • Weaving - Assembling aspects into advised objects.
Spring AOP • Generally, applies aspects to beans using BeanFactory • Uses Dynamic Proxies if interface available otherwise CGLIB • CGLIB creates derived class which proxies requests • Bean class may not be final • Less capable than AspectJ • does not have field interception • only runtime weaving solution is available • Closer integration with AspectJ anticipated
Spring Pointcuts • Pointcut applicability to a class may be evaluated statically or dynamically • Spring only creates proxies where necessary public interface Pointcut { ClassFilter getClassFilter(); MethodMatcher getMethodMatcher(); } public interface ClassFilter { boolean matches(Class clazz); }
Pointcuts (cont'd) • Pointcut may be statically or dynamically evaluated based on isRuntime() • Abstract class StaticMethodMatcherPointcut requires override of 1st method only public interface MethodMatcher { boolean matches(Method m, Class targetClass); boolean isRuntime(); boolean matches(Method m, Class targetClass, Object[] args); } Only called if isRuntime() == true
Pointcuts (cont'd) • Spring predefined pointcuts • In org.springframework.aop.support package • RegexpMethodPointcut • Union of multiple regular expressions • Uses Jakarta ORO package • ControlFlowPointcut • Similar to AspectJ cflow • Applied if call stack includes specific class and, optionally, method • UnionPointcut • Merges pointcuts
Spring Advice • Can have per-class or per-instance Advice • Spring provides several Advice types • Around Advice • AOP Alliance compliant • Must call invocation.proceed() to call target public class MyAdvice implements AroundAdvice { Object invoke(MethodInvocation invocation) { // change arguments, start transaction, lock, etc. invocation.proceed(); // change return value, stop transaction, unlock,etc. } }
Spring Advice • MethodBeforeAdvice • void before(Method m, Object[] args, Object target) • Cannot alter return type • ThrowsAdvice • Marker interface • Implementors define methods of form: • afterThrowing([Method], [args], [target], subclassOfThrowable) • AfterReturningAdvice • void afterReturning(Object returnValue, Method, m, Object[] args, Object target) • Cannot modify return value
Spring Advice • IntroductionInterceptor provides ability to define mixins public class RollbackAdvice extends DelegatingIntroductionInterceptor implements RollbackSupport { Map map = new HashMap(); void rollback(Date date) { // rollback to state at given time } public Object invoke(MethodInvocation invocation) { // record change and time of change } }
Injecting Advice <bean id=“meetingTarget" class=“ex.DefaultMeeting“ singleton=“false”> <property name=“topic">Spring</property> </bean> <bean id="myAdvisor" class=“ex.RollbackAdvice" singleton=”false”> </bean> <bean id="debugInterceptor" class="org.springframework.aop.interceptor.DebugInterceptor"> </bean>
Injecting Advice (cont'd) <bean id=“meeting" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>ex.Meeting</value> </property> <property name="target"><ref local=“meetingTarget"/></property> <property name="interceptorNames"> <list> <value>myAdvisor</value> <value>debugInterceptor</value> </list> </property> </bean> All methods using CGLib if none defined Advisors applied in order
Autoproxying • Autoproxy bean definitions automatically proxy selected beans. • BeanNameAutoProxyCreator • Adds listed advisors/interceptors to beans with names matching regular expression • DefaultAdvisorAutoProxyCreator • Generic autoproxy infrastructure support • Applies all advisors defined in the context to all beans, proxying appropriately
Metadata support • Spring supports obtaining meta data Object attributes at class, method, and field level • Not yet argument level (as JSR-175) • Currently supports Jakarta Commons Attributes • Support for JSR-175 in work • Metadata support provided via Attributes interface • Amenable to mocking unlike JDK reflection and Commons static methods
Metadata autoproxying • Configuration of autoproxying based on metadata attributes simplifies configuration • Define custom attribute class • Define Advisor with pointcut based on custom attribute • Add Advisor in ApplicationContext with autoproxy • Examples • Transaction Attributes • Security Attributes • Pooling • Mapping of controllers to URLs
AOP Transactions • Spring provides AOP support for declarative transactions • Delegates to a PlatformTransactionManager instance • DataSourceTransactionManager • HibernateTransactionManager • JdoTransactionManager • JtaTransactionManager
Transaction Configuration <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="dataSource"><ref bean="dataSource"/></property> <property name="mappingResources"> <list> <value>com/../model/*.hbm.xml</value> </list> </property> </bean> <bean id="transactionManager” class="org.springframework.orm.hibernate.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory"/> </property> </bean>
Declarative Transactions • Declarative transactional support can be added to any bean by using TransactionProxyFactoryBean • Similar to EJB, transaction attributes may be defined on a per-method basis • Also allows definition of pre- and post- interceptors (e.g. for security)
Injecting Transaction Support Declarative transaction support for single bean <bean id=“reservationService" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"> <property name="transactionManager"> <ref bean="transactionManager"/> </property> <property name="target"><ref local=“reservationServiceTarget"/></property> <property name="transactionAttributes"> <props> <prop key=“reserveRoom*">PROPAGATION_REQUIRED</prop> <prop key="*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
Transaction Autoproxy <bean id="autoproxy" class="org...DefaultAdvisorAutoProxyCreator"> </bean> <bean id="transactionAdvisor" class="org...TransactionAttributeSourceAdvisor" autowire="constructor" > </bean> <bean id="transactionInterceptor" class="org...TransactionInterceptor" autowire="byType"> </bean> <bean id="transactionAttributeSource" class="org...AttributesTransactionAttributeSource" autowire="constructor"> </bean> <bean id="attributes" class="org...CommonsAttributes" /> Generic autoproxy support Invokes interceptor based on attributes Applies transaction using transactionManager Caches metadata from classes
Data Access • DAO support provides pluggable framework for persistence • Currently supports JDBC, Hibernate, JDO, and iBatis • Defines consistent exception hierarchy (based on RuntimeException) • Provides abstract “Support” classes for each technology • Template methods define specific queries
Hibernate DAO Example public class ReservationDaoImpl extends HibernateDaoSupport implements ReservationDao { public Reservation getReservation (Long orderId) { return (Reservation)getHibernateTemplate().load(Reservation .class, orderId); } public void saveReservation (Reservation r) { getHibernateTemplate().saveOrUpdate(r); } public void remove(Reservation Reservation) { getHibernateTemplate().delete(r); }
Hibernate DAO (cont’d) public Reservation[] findReservations(Room room) { List list = getHibernateTemplate().find( "from Reservation reservation “ + “ where reservation.resource =? “ + “ order by reservation.start", instrument); return (Reservation[]) list.toArray(new Reservation[list.size()]);
Hibernate DAO (cont’d) public Reservation[] findReservations(final DateRange range) { final HibernateTemplate template = getHibernateTemplate(); List list = (List) template.execute(new HibernateCallback() { public Object doInHibernate(Session session) { Query query = session.createQuery( "from Reservation r “ + “ where r.start > :rangeStart and r.start < :rangeEnd “); query.setDate("rangeStart", range.getStartDate() query.setDate("rangeEnd", range.getEndDate()) return query.list(); } }); return (Reservation[]) list.toArray(new Reservation[list.size()]); } }
Hibernate Example <bean id="sessionFactory" class="org.springframework.orm.hibernate.LocalSessionFactoryBean"> <property name="dataSource"><ref bean="dataSource"/></property> <property name="mappingResources"> <list> <value>com/jensenp/Reservation/Room.hbm.xml</value> <value>com/jensenp/Reservation/Reservation.hbm.xml</value> <value>com/jensenp/Reservation/Resource.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">${hibernate.dialect}</prop> <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto} </prop> <prop key="hibernate.show_sql">${hibernate.show_sql}</prop> </props> </property> </bean> <bean id=“reservationDao" class="com.jensenp.Reservation.ReservationDaoImpl"> <property name="sessionFactory"><ref bean="sessionFactory"/> </property> </bean>
JDBC Support • JDBCTemplate provides • Translation of SQLExceptions to more meaningful Spring Runtime exceptions • Integrates thread-specific transactions • MappingSQLQuery simplifies mapping of ResultSets to Java objects