960 likes | 1.02k Views
Spring Framework strives to provide a simple, lightweight solution for building Java applications with a focus on Inversion of Control, AOP Framework, and Service Abstraction Layer. It enables the decoupling of software layers by injecting dependencies at runtime and supports declarative transactions, integration with J2EE services, ORM toolkits, and more. By promoting programming to interfaces and offering granular exception handling, Spring enhances testability and scalability, making it easier to track bugs and implement new features. Spring promotes clear architecture, easy wiring of components, and flexibility in views, facilitating team development and enabling both vertical and horizontal parallel development approaches.
E N D
The Spring Framework Mission Statement • J2EE should be easier to use • It's best to program to interfaces, rather than classes. Spring reduces the complexity cost of using interfaces to zero. • JavaBeans offer a great way of configuring applications. • OO design is more important than any implementation technology, such as J2EE. • Checked exceptions are overused in Java. A framework shouldn't force you to catch exceptions you're unlikely to be able to recover from. • Testability is essential, and a framework such as Spring should help make your code easier to test. • Spring should be a pleasure to use • Your application code should not depend on Spring APIs • Spring should not compete with good existing solutions, but should foster integration. (For example, JDO and Hibernate are great O/R mapping solutions. We don't need to develop another one.
Sun's Best Practices... • In 1998 Distributed Computing was the big buzz-word • Sun made EJBs to compete with technologies like CORBA • The specification was intrusive • And the result is Sun's famous PetStore application with quite difficult architecture
EJB Issues • Intrusive – Noisy • Must be an EJBObject • Must run within the container • Rapid iterative code/debug/test cycles difficult • If the Sun “Pet Store” is the best, we’re in trouble • Too many different patterns • Performs poorly • Reliance on Entity Beans • Too many different files needed to do simple things
What are Lightweight Frameworks? • Non-intrusive • No container requirements • Simplify Application Development • Remove re-occurring pattern code • Productivity friendly • Unit test friendly • Very Pluggable • Usually Open Source • Examples: • Spring, Pico, Hivemind • Hibernate, IBatis, Castor • WebWork • Quartz • Sitemesh
What is Spring? At it’s core, Spring provides: • An Inversion of Control Container • Also known as Dependency Injection (Fowler’s term) • An AOP Framework • Spring provides a proxy-based AOP framework • You can alternatively integrate with AspectJ or AspectWerkz • A Service Abstraction Layer • Consistent integration with various standard and 3rd party APIs These together enable you to write powerful, scalable applications using POJOs.
Spring Overview from springframework.org Note: Spring distribution comes as one big jar file and alternatively as a series of smaller jars broken out along the above lines (so you can include only what you need)
Spring introduction • Spring allows us to decouple our software layers by injecting a component’s dependencies at runtime rather than having them declared at compile time via importing and instantiating classes. It uses the JavaBeans framework to wire up dependencies. • Spring provides integration for J2EE services such as EJB, JDBC, JNDI, JMS, JTA. It also integrates several popular ORM toolkits such as Hibernate and JDO and assorted other services as well. Cosmo provides a similar Spring-based integration with JCR. • One of the highly touted features is declarative transactions, which allows the developer to write transaction-unaware code and configure transactions in Spring config files. • Spring is built on the principle of unchecked exception handling. This also reduces code dependencies between layers. Spring provides a granular exception hierarchy for data access operations and maps JDBC, EJB, and ORM exceptions to Spring exceptions so that applications can get better information about the error condition. • With highly decoupled software layers and programming to interfaces, each layer is easier to test. Mock objects is a testing pattern that is very useful in this regard.
Spring introduction • Layer Architecture • Clear Architecture • Easy to track down bugs and implement new features • Impact can’t be overstated • Wiring of components “collaborators” very easy to do and understand • Spring MVC Layer • Complete flexibility in Views (JSTL, PDF, MS Excel…) • Facilitates Team Development • Vertical (Parallel development – Use Cases) • Horizontal (leverage technical expertise)
Advantages of Spring Architecture Lifecycle – responsible for managing all your app components, particularly those in the middle tier container sees components through well-defined lifecycle: initialization(), destruction() Dependencies - Spring handles injecting dependent components without a component knowing where they came from (IoC) Config information - Spring provides one consistent way of configuring everything, separate configuration from application logic, varying configuration. In J2EE (e.g. EJB) it is easy to become dependent on container and deployment environment, proliferation of pointless classes (locators/delegates); Spring eliminates them. Cross-cutting behaivior (resource management is cross-cutting concern, easy to copy-and-paste everywhere) Portable (can use server-side in web/ejb app, client-side in swing app, business logic is completely portable)
Spring - Solutions • Solutions address major J2EE problem areas: • Web application development (MVC) • Enterprise Java Beans (EJB, JNDI) • Database access (JDBC, iBatis, ORM) • Transaction management (JTA, Hibernate, JDBC) • Remote access (Web Services, RMI) • Each solution builds on the core architecture • Solutions foster integration, they do not re-invent the wheel
Proprietary, buggy configuration code Proliferation of Singletons, Service Locators (glue code) Copy-and-paste code (boilerplate, not relevant to business object), ugly exception handling Tied by invasive infrastructure (EJB/JNDI), application server Testing? For some components only end-to-end tests are realistic. One elegant way of configuring everything Dependency Injection – components are handed only what they need Cohesive, reusable business logic (clear separation of concerns) No dependency on infrastructure APIs or container Easy, comprehensive testing Before Spring After Spring Sad Euphoric!
Spring MVC Source: http://www.manageability.org/polls/what_web_framework June 10, 2005
Spring Application Context • Container which controls components ApplicationContext ctx = new FileSystemXmlApplicationContext("config.xml"); ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext( new String[] {"applicationContext.xml", "applicationContext-part2.xml"} );
How to configure <?xml version="1.0" encoding="UTF-8"?> <beans> <bean id= "component1" class= "package.Class1"> ... </bean> <bean name= "component2,alias1" class= "package.Class2"> ... </bean> ... </beans>
Configuring Components • Singleton/prototype (non-singleton) • Setter/constructor dependency injection • Autowire: no, byName, byType, constructor, autodetect • Dependency-check: none, simple, object, all • Init-method, destroy-method • Lazy-init
Examples of configuration public class ExampleBean { private AnotherBean beanOne; private YetAnotherBean beanTwo; private int i; public ExampleBean(AnotherBean beanOne) { this.beanOne = beanOne; } public void setBeanTwo(YetAnotherBean beanTwo) {this.beanTwo = beanTwo; } public void setIntegerProperty(int i) { this.i = i; } } <bean id="exampleBean" class="examples.ExampleBean" singleton="false"> <constructor-arg><ref bean="anotherExampleBean"/></constructor-arg> <property name="beanTwo"><ref local="yetAnotherBean"/></property> <property name="integerProperty"><value>1</value></property> </bean> <bean id="anotherExampleBean" class="examples.AnotherBean"/> <bean id="yetAnotherBean" class="examples.YetAnotherBean” lazy-load=”true”/>
IoC Types • Three basic types • Type I • Interface Injection • Your service or component implement a specific interface • Much like EJBs • Type II • Method Injection • Dependent objects are provided to the object by methods • Based on JavaBeans constructs • Ordering of method calls may not be achievable • Type III • Constructor Injection • Dependent objects are provided to the object by constructors • Large constructor argument lists
Basic JavaBean Pattern • Include a “getter” and “setter” method for each field class MyBean { private int counter; public int getCounter() { return counter; } public void setCounter(int counter) { this.counter = counter; } }
BeanFactories • XML-based component deployment • Create object graphs and configure data • Inversion of Control (Dependency Injection) The bean’s fully- qualified classname The bean’s ID <beans> <bean id=“widgetService” class=“com.zabada.base.WidgetService”> <property name=“poolSize”> <!—-property value here--> </property> </bean> </beans> Maps to a setPoolSize() call
Property Values for BeanFactories (continued) The real magic comes in when you can set a property on a bean that refers to another bean in the configuration: <bean name=“widgetService” class=“com.zabada.base.WidgetServiceImpl”> <property name=“widgetDAO”> <ref bean=“myWidgetDAO”/> </property> </bean> calls setWidgetDAO(myWidgetDAO) where myWidgetDAO is another bean defined in the configuration This is the basic concept of Inversion of Control
Inversion of Control (IoC) • Rather than locating needed resources, application components provide setters through which resources are passed in during initialization • Example: our DataAccessObject class provides a setDataSource() method, which is called from the Init class. • In Spring Framework, this pattern is used extensively, and initialization is usually done through configuration file rather than application code.
Inversion of control • Design pattern (Wzorzec projektowy)on top of which components are functioning in a container • Components and classes supply certain functionality • Containers create concrete instances of the components, filling their fields and maintaining their life-cycle
IoC - Sample We would like that MovieLister knew only about the interface, but how to create a working instance of MovieListener?
IoC - Sample public interface MovieFinder { List findAll(); } class MovieLister... private MovieFinder finder; public MovieLister() {finder = new ColonDelimitedMovieFinder("movies1.txt"); } public Movie[ ] moviesDirectedBy(String arg) { List allMovies = finder.findAll(); for (Iterator it = allMovies.iterator(); it.hasNext();) { Movie movie = (Movie) it.next(); if (!movie.getDirector().equals(arg)) it.remove(); } return (Movie[ ]) allMovies.toArray(new Movie[allMovies.size()]); }
IoC - Sample class MovieLister... private MovieFinder finder; public void setFinder(MovieFinder finder) { this.finder = finder; } class ColonMovieFinder... public void setFilename(String filename) { this.filename = filename; }
IoC - Sample <beans> <bean id="MovieLister" class="package.MovieLister"> <property name="finder"> <ref local="MovieFinder"/> </property> </bean> <bean id="MovieFinder" class="package.ColonMovieFinder"> <property name="filename"> <value>movies1.txt</value> </property> </bean> </beans> public void testSpringContainer() { ApplicationContext ctx = new FileSystemXmlApplicationContext("config.xml"); MovieLister movieLister = (MovieLister) ctx.getBean("MovieLister"); Movie[ ] movies = movieLister.moviesDirectedBy("Sergio Leone"); }
Importance of Loose Coupling with Spring • Adopting Spring is easier when architecture is loosely coupled • Consistent transaction boundaries/entry points • Spring adds more value with testing. Control injection • No boundaries makes things a lot harder
High Level of Coupling • Very tight coupling across the entire application • Interaction complexity is extremely high. • Unit testing is hard to do, if not impossible. Impossible out of the container. • One code change could potentially affect multiple areas of the code. • The application is very brittle, and development takes much longer than in a layered architecture. • More than a few developers and they will start stepping on each other. Products Application Framework External Providers Data Access
Very Loose Coupling – layers talk only to those directly above and below them Spring Interceptors (AOP)/Interface Biz Services Interface Products Application Framework Interface Spring Interceptors (AOP)/Interface Workflow External Providers Spring Interceptors (AOP)/Interface Data Access Structuring a system into layers has a number of important benefits: • Understand a single layer as a coherent whole without knowing about the other layers • Substitute layers with alternative implementation of the same basic services • Significantly reduce complexity of code interactions • Simplify unit testing – test each layer separately • Much more rapid development
Looking at a Layer – Façade Pattern After Refactor Before Refactor Application Logic Spring Audit Interceptors Application Logic External Provider Layer Service1 Service2 Service3 Service4 Service1 Service2 Service3 Service4 Refactor Enabled Application Logic Mock External Provider Layer Mock Mock Mock Mock
Loose Coupling w/ Business Interface Pattern • Having code in EJBs makes unit testing extremely difficult since everything has to be run in an application server. • Moved all business logic out of Stateless and Message Driven EJBs into plain old java objects (POJO). EJB is solely used for transaction and thread management. This makes testing the business logic much easier since we can write all of our tests out of the container.
Practical Refactoring to Spring Framework • Start with bean wiring (Inversion of Control) • Beans that are Spring wired are very easy to apply AOP • The more injection, the more you can mock • Spring can be used for test data retrieval • One of Spring’s goal is to make existing technologies easier. Spring is not Hibernate, Hibernate is not Spring. • Ability to change behavior without changing code is an important point and benefit of Spring (i.e. datasource configuration, transaction manager, our entire web service layer) • Re-factor into layers first, then add Spring and Hibernate • Layering also creates boundaries • Tradeoff between run-time flexibility and run-time configuration validation • Changing one property in the database allows us to change entire layers
Practical Refactoring to Spring Framework • Entire code base can be tested out of container except for EJB EJB calls • Code is much more maintainable • Re-factoring is much easier with baseline of unit tests in place • Inversion of control helps immensely in mocking out external service layer calls • Testing becomes much easier meaning more likely to happen • Teams able to scale with less code contention
MVC for Web • Event – HTTP request from client • Controller – Custom Spring Controller Class • View – JSP script • Model – Java Beans Model is passed to the server-side View which is returned to the client
About Spring MVC • Comes with the Spring distribution • Well integrated with the rest of Spring • Very extensible
Quick Spring Refresher • Write dependencies as setters • Link up dependencies in XML file • The Spring Framework will instantiate and call setters to hook it all together <bean id=“dateFormat" class=“java.text.SimpleDateFormat"> <constructor-arg value=“dd MMM yyyy”/> </bean> <bean id=“myBean" class=“com.platinumSolutions.stuff.SomeClass"> <property name=“dateFormat” ref=“dateFormat”/> </bean>
Spring MVC Basics • All calls go through the DispatcherServlet • Config file is *-servlet.xml by default • MVC: instances of the following: • M – Model: a Java Map • V – View: org.springframework.web.servlet.View • C – Controller: org.springframework.web.servlet.mvc.Controller
Spring MVC Configuration The configurable pieces of Spring MVC: • org.springframework.web.servlet.HandlerMapping • what controller to call given a URL • org.springframework.web.servlet.ViewResolver • how to determine what view to show • org.springframework.web.servlet.LocaleResolver • how to determine internationalization • org.springframework.web.multipart.MultipartResolver • how to handle files • org.springframework.web.servlet.HandlerExceptionResolver • what to do with an Exception • org.springframework.web.servlet.ThemeResolver • where to get css, images, pages from • org.springframework.web.servlet.HandlerAdapter • wrapper around the controller (or servlet)
Spring MVC A (simplified) sequence diagram:
Handling the request with a HandlerMapping Given a URL, figures out what Controller to use: • SimpleUrlHandlerMapping • define mappings with Map or Properties • BeanNameUrlHandlerMapping • bean names have same names as URL • CommonsPathMapHandlerMapping • use Commons Attributes to determine mapping
Selecting a view with a ViewResolver Given a view name, figures out what View to use: • BeanNameViewResolver • Spring beans happen to have the same name • UrlBasedViewResolver • view name maps to a URL (like a filename) • ResourceBundleViewResolver • look up the View in a resource file • XmlViewResolver • uses XML file to determine mappings • FreeMarkerViewResolver • UrlResourceViewResolver preset for FreeMarkerView • InternalResourceViewResolver • UrlResourceViewResolver preset for InternalResourceView • VelocityViewResolver • UrlResourceViewResolver preset for VelocityView
Different Views Plenty of Views are packaged with Spring MVC: • JstlView • map to a JSP page • RedirectView • Perform an HTTP Redirect • TilesView, TilesJstlView • integration with tiles • VelocityLayoutView, VelocityToolboxView, VelocityView • Integration with the Velocity templating tool • FreeMarkerView • use the FreeMarker templating tool • JasperReportsView, JasperReportsMultiFormatView, JasperReportsMultiFormatView, JasperReportsPdfView, JasperReportsXlsView • Support for Jasper Reports