1 / 56

Веб-разработка на Java

Высшая школа ИТИС. Лекция 5 - Spring Framework Inversion of Control 16 октября 2013. Веб-разработка на Java. Алина Витальевна Васильева доцент факультета Компьютерных Наук Латвийский Университет инженер-разработчик, Одноклассники, Mail.ru Group alina.vasiljeva@gmail.com.

ndonaldson
Download Presentation

Веб-разработка на Java

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Высшая школа ИТИС Лекция 5 - Spring Framework Inversion of Control 16 октября 2013 Веб-разработка на Java Алина Витальевна Васильева доцент факультета Компьютерных Наук Латвийский Университет инженер-разработчик, Одноклассники, Mail.ru Group alina.vasiljeva@gmail.com

  2. Spring Overview • Spring is an open source layered Java/JavaEE application framework • Created by Rod Johnson • Based on book “Expert one-on-one J2EE Design and Development” (October, 2002) • Current version 3.2.4 (released on August 6, 2013)

  3. Initial Goal – Lightweight Framework • Non-intrusive • No container requirements • Simplify application development • Remove re-occurring pattern code • Productivity friendly • Unit test friendly • Very pluggable • Open source

  4. SpringMission Statement [1/3] • Java EE 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 (POJO) offer a great way of configuring applications • OO design is more important than any implementation technology, such as Java EE

  5. SpringMission Statement [2/3] • 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

  6. SpringMission Statement [3/3] • Spring should not compete with good existing solutions, but should foster integration. For example, Hibernate is a great object- relational mapping solution. Don't need to develop another one.

  7. Success Story SpringSource has been purchased for ~$400million by VMWare in August 2009

  8. Spring Products • Spring platform today provides A LOT of products for many different tasks • “from configuration to security, web apps to big data” • The central and core product is Spring Framework

  9. Some Advantages • Build applications from POJOs • Execute a database transaction without dealing with Transaction APIs • Make a local Java method: • a remote procedure without dealing with Remote APIs • a message handler without dealing with JMS APIs • a management operation without dealing with JMX APIs

  10. Modules of the Spring Framework The Spring Framework consists of features organized into about 20 modules http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/overview.html#overview-modules

  11. Modules of the Spring Framework • Core Container: • Core and Beans – Inversion of Control, Dependency Injection • Context • Expression Language • Data Access/Integration • JDBC, ORM, OXM, JMS and Transaction • Web MVC • Model-View-Controller implementation for web applications

  12. Modules of the Spring Framework • AOP • Remote Access • Authentication and Authorization • Remote Management • Messaging Framework • Web Services • Email • Testing • many more . . . Spring is very loosely coupled, components widely reusable and separately packaged

  13. How to start • Add Maven dependency to application’s pom.xml • Use the following command to download sources • spring-context provides core functionality <dependencies> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>3.2.4.RELEASE</version> </dependency> </dependencies> mvn eclipse:eclipse -DdownloadSources=true

  14. Let’s Start ! Simple demo example showing the basic concept of dependency injection: • Add Spring dependency to your Maven project http://projects.spring.io/spring-framework/#quick-start • <dependency> • <groupId>org.springframework</groupId> • <artifactId>spring-context</artifactId> • <version>3.2.4.RELEASE</version> • </dependency>

  15. Dependency Injection Demo • Create an interface for a message service • Create a component printing out a message received from a message service public interface MessageService { String getMessage(); } @Component public class MessagePrinter { @Autowired private MessageService service; public void printMessage() { System.out.println(service.getMessage()); } }

  16. Dependency Injection Demo • Create main application @Configuration @ComponentScan public class Application { @Bean MessageService mockMessageService() { return new MessageService() { public String getMessage() { return "Hello World!"; } }; } public static void main(String[] args) { ApplicationContext context = new AnnotationConfigApplicationContext(Application.class); MessagePrinter printer =context.getBean(MessagePrinter.class); printer.printMessage(); } }

  17. Dependency Injection Demo Result: • Spring Framework wired everything together • MessagePrinter is decoupled from the MessageService implementation Hello World!

  18. Inversion of Control (IoC) • Central in the Spring is its Inversion of Control container • Based on “Inversion of Control Containers and the Dependency Injection pattern” (by Martin Fowler) • Inversion of Control and Dependency Injection, in fact, are not the same thing • Inversion of Control is a much more general concept • Dependency Injection is merely one concrete example of IoC

  19. Inversion of Control • IoC covers a broad range of techniques that allow an object to become a passive participant in the system • IoC provides centralized, automated configuration, managing and wiring of application Java objects • Container responsibilities: • creating objects • configuring objects • calling initialization methods • etc Java objects that are managed by the Spring IoC containerare referred to as beans Object’s lifecycle

  20. Dependency Injection • Dependency Injection is a technique that frameworks use to wire together an application • In nearly all applications there are at least two participants, and these participants are required to somehow collaborate • The objects in an application have dependencieson each other • The trick is to connect objects without locking in the connection

  21. Dependency Injection • Java platform lacksthe means to organize the basic application building blocks into a coherent whole • Design patterns can help, such as Factory, Abstract Factory, Builder, Decorator, Service Locator … • But patterns are just formalized best practices that you must implement yourself in your application • Spring Framework IoCcomponent addresses this concern

  22. Example Let’s consider a simple Internet Shop example

  23. Example public interface CashRegister { public double calculateTotalPrice(ShoppingCart cart); } public interface PriceMatrix { public double lookupPrice(Item item); } public class CashRegisterImpl implements CashRegister { private PriceMatrix priceMatrix = new PriceMatrixImpl(); public double calculateTotalPrice(ShoppingCart cart) { double total = 0; for (Item item : cart.getItems()) { total += priceMatrix.lookupPrice(item)); } return total; } }

  24. Major issues • Every instance of CashRegisterImpl has a separate instance of PriceMatrixImpl • With heavy services it is preferable to share a single instance across multiple clients • CashRegisterImpl now has concrete knowledge of the implementation of PriceMatrix • Tight coupling • By explicitly creating its own dependent objects, the CashRegisterImpl creates a difficult test situation • Unit tests have to be divorced from any environment requirements

  25. Major issues • PriceMatrixImplmight need some specific and complex configuration after creation • initialization with business parameters • dependencies on other components PriceMatrix priceMatrix = new PriceMatrixImpl(); priceMatrix.setCoefficient(5); priceMatrix.setMaxValue(10000); priceMatrix.setRemoteProvider(new RemoteProviderImpl()); . . . Need to repeat it in any place where price matrix is needed . . .

  26. First attempt – Service Locator • The Service Locatorpattern encapsulates the actions taken to obtain a reference to the object required • Thisshields the client from knowing how, or even where, to obtain a reference to the object

  27. Updated code public class CashRegisterImpl implements CashRegister { private PriceMatrix priceMatrix; public CashRegisterImpl() { priceMatrix = ServiceLocator.getPriceMatrix(); } public double calculateTotalPrice(ShoppingCart cart) { double total = 0; for (Item item : cart.getItems()) { total += priceMatrix.lookupPrice(item)); } return total; } }

  28. Result • Using Service Locator the class no longer has to manage object creation • Next benefit - client has no knowledge of theconcrete implementation of PriceMatrix • The third problem, the lack of testability, is unfortunately still with us • Creating a unit test is extremely difficult, becausethe implementation relies on a functioning PriceMatrix object

  29. Testing with mock objects • The test should be written with amock PriceMatrix, but there is no way to insert the mock object during testing • The static ServiceLocator.getPriceMatrix is difficult to change during a test run • There is a need to swap different implementations of PriceMatrix without affecting the client

  30. How to achieve it ? • To effectively do this, the client must not actively participate in the construction or retrieval of the resource • The resource must be given to the client • Solution Dependency Injection

  31. Dependency Injection • Dependency Injection is a technique to wire an application together without any participationby the code that requires the dependency • The object provides a property that can hold a reference to a specific service • When the object is created a reference to an implementation of that type of service will automatically be injected into that property - by an external mechanism

  32. Non-IoC versus IoC Non Inversion of Control approach Inversion of Control approach

  33. Dependency Injection Basics • Basic JavaBean pattern: • include a “getter” and “setter” method for each private field: • Application components provide fields & setters through which resources are passed in during initialization • Spring extensively uses this pattern • Initialization is usually done through configuration file rather than application code class MyBean { private int counter; public int getCounter() { return counter; } public void setCounter(int counter) { this.counter = counter; } }

  34. Final Code public class CashRegisterImpl implements CashRegister { private PriceMatrix priceMatrix; public void setPriceMatrix(PriceMatrix priceMatrix) { this.priceMatrix = priceMatrix; } public double calculateTotalPrice(ShoppingCartcart) { double total = 0; for (Item item : cart.getItems()) { total += priceMatrix.lookupPrice(item)); } return total; } }

  35. Example (non-IoC) public class UsersDataImportProcessor implements DataImportProcessor { private XmlParser xmlParser; private CommonJpaDAO jpaDAO; . . . publicvoidimportData() { xmlParser = new DomXmlParser(. . .); jpaDAO = new CommonJpaDAOImpl (. . .); . . . List<User> users = xmlParser.parseUsers(usersXml); . . . jpaDAO.save(user); . . . } }

  36. Example (IoC) @Component public class UsersDataImportProcessor implements DataImportProcessor { @Autowired private XmlParser xmlParser; @Autowired private CommonJpaDAO jpaDAO; . . . publicvoidimportData() { . . . List<User> users = xmlParser.parseUsers(usersXml); . . . jpaDAO.save(user); . . . } }

  37. Spring’s Dependency Injection • Beans define their dependencies through constructor arguments or properties • Container resolves (injects) dependencies of components by setting implementation objectduring runtime • BeanFactoryinterface – the core that loads bean definitions and manages beans • Superset ApplicationContext - represents the Spring IoC container and is responsible for instantiating, configuring and assembling beans

  38. Creating ApplicationContext The ApplicationContext interface builds on top of the BeanFactory (it is a sub-interface) and adds other functionality In standalone applications it is common to create an instance ClassPathXmlApplicationContext ApplicationContext context = new ClassPathXmlApplicationContext( "applicationContext.xml"); File in a Maven project: \spring-app\src\main\resources\applicationContext.xml

  39. Configuration metadata Application classes are combined with configuration metadata so that after the ApplicationContextis created and initialized, you have a fully configured and executable system

  40. Configuration metadata • Configuration metadata defines how you as an application developer tell the Spring container to instantiate, configure, and assemble the objects in your application • There exists several forms of defining configuration metadata: • XML-based (traditional form) • Annotation-based configuration • Java-based configuration

  41. XML configuration metadata Configuration consists of at least one and typically more than one bean definition that the container must manage

  42. Internet Shop configuration <?xml version="1.0" encoding="UTF-8"?> <beans ...> <bean id="priceMatrix" class="beans.PriceMatrixImpl"/> <bean id="cashRegister" class="beans.CashRegisterImpl"> <property name="priceMatrix" ref="priceMatrix"/> </bean> </beans>

  43. XML configuration: example public class VenueDataImportProcessor implements DataImportProcessor { private boolean cleanDatabase; private Map<String, List<String>> request; private String count; . . . public void setCleanDatabase(boolean cleanDatabase) { this.cleanDatabase = cleanDatabase; } // setters for all properties } <bean id="venuesProcessor" class="lv.lu.meetings.impl.venues.VenueDataImportProcessor"> <property name="cleanDatabase" value="true"/> <property name="count" value="10"/> <property name="request"> <map> <entry> <key><value>Riga, LV</value></key> <list> <value>food</value> <value>coffee</value> </list> </entry> </map> </property> </bean>

  44. Using theContainer The BeanFactory interface has the following methods for client code to call: • boolean containsBean(String): returns true if the BeanFactory contains a bean definition or bean instance that matches the given name. • Object getBean(String): returns an instance of the bean registered under the given name. • Object getBean(String, Class<T>): returns a bean, registered under the given name. The bean returned will be cast to the given Class. • Class getType(String name): returns the Class of the bean with the given name. • boolean isSingleton(String): determines if the bean under the given name is a singleton. • String[] getAliases(String): Return the aliases for the given bean name, if any were defined in the bean definition.

  45. Main Application public class InternetShopApp { public static void main(String[] args){ ApplicationContext appCtxt = new ClassPathXmlApplicationContext( "/applicationContext.xml"); CashRegister cashRegister = (CashRegister)appCtxt.getBean("cashRegister"); System.out.println("Total price: " + cashRegister.calculateTotalPrice( getShorringCart())); System.exit(0); } }

  46. Annotation-based configuration • Instead of using XML, it is possible to move the configuration into the component class by using annotations on the relevant class, method, or field declaration • Enable annotation support by adding the following tag to XML configuration <beans ... > ... <context:annotation-config/> ... </beans>

  47. Annotations • Some of the most common annotations: • @Component • @Autowired • @PostConstruct • @PreDestroy • @Required • @Resource • @Repository • @Service • @Bean • @Configuration

  48. Classpath Scanning • There is a way to avoid registering each bean in XML file - using classpath scanning • Enable by adding the following tag to XML configuration: • Then, add @Component annotation to Java class definitions <context:component-scan base-package="<your_package>"/> http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/beans.html#beans-classpath-scanning

  49. @Component • To register a bean simply add annotation @Component to the class definition • Such classes are considered as candidates for auto-detection when using annotation-based configuration and classpath scanning @Component("cashRegister") public class CashRegisterImpl implements CashRegister { http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/beans.html#beans-classpath-scanning

  50. @Autowired • Marks a constructor, field, setter method or configuration method as to be autowired by Spring's dependency injection facilities • If there are multiple candidates for autowiring one option is to use • @Qualifier http://docs.spring.io/spring/docs/3.2.4.RELEASE/spring-framework-reference/html/beans.html#beans-autowired-annotation

More Related