spring framework ¿ª·¢²Î¿¼ÊÖ²á2. spring 2.0 2.5 2.1. 2.2. (ioc) 2.2.1. bean 2.2.2. xml...

Post on 06-Jun-2020

6 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

SpringFrameworkRodJohnson

JuergenHoeller

AlefArendsen

ColinSampaleanu

RobHarrop

ThomasRisberg

DarrenDavison

DmitriyKopylenko

MarkPollack

ThierryTemplier

ErwinVervaet

PortiaTung

BenHale

AdrianColyer

JohnLewis

CostinLeau

MarkFisher

SamBrannen

RamnivasLaddad

2.5.2Copiesof thisdocumentmaybemadeforyourownuseandfordistribution toothers,provided

thatyoudonotchargeanyfeeforsuchcopiesandfurtherprovidedthateachcopycontainsthisCopyrightNotice,whetherdistributedinprintorelectronically.

1.1.1.

1.1.1.

2.Spring2.02.52.1.2.2.(IoC)

2.2.1.bean2.2.2.XML2.2.3.XML2.2.4.Annotation()2.2.5.classpath

2.3.(AOP)2.3.1.AOPXML2.3.2.@AspectJ2.3.3.beanpointcut(beannamepointcutelement)2.3.4.AspectJAspectJload-timeweaving

2.4.2.4.1.XML2.4.2.Websphere2.4.3.JPA2.4.4.JMS2.4.5.JDBC

2.5.Web2.5.1.SpringMVC2.5.2.Portlet2.5.3.Annotation2.5.4.SpringMVC2.5.5.Tiles22.5.6.JSF1.22.5.7.JAX-WS

2.6.2.6.1.2.6.2.2.6.3.JMX2.6.4.SpringJCAadapter2.6.5.2.6.6.Java5(Tiger)

2.7.Spring2.52.7.1.

2.8.2.9.

I.

3.IoC()3.1.3.2.-bean

3.2.1.3.2.2.3.2.3.bean3.2.4.

3.3.3.3.1.3.3.2.3.3.3.depends-on3.3.4.bean3.3.5.autowire3.3.6.3.3.7.

3.4.Bean3.4.1.Singleton3.4.2.Prototype3.4.3.Singletonbeansprototype-bean3.4.4.3.4.5.

3.5.bean3.5.1.3.5.2.

3.6.bean3.7.

3.7.1. BeanPostProcessorbean3.7.2. BeanFactoryPostProcessor

3.7.3.FactoryBean3.8.TheApplicationContext

3.8.1.BeanFactory ApplicationContext?3.8.2.MessageSource3.8.3.3.8.4.3.8.5.ApplicationContextWEB

3.9.singleton3.10.J2EERARSpringApplicationContext3.11.Annotation-based

3.11.1.@Autowired3.11.2.3.11.3.CustomAutowireConfigurer3.11.4.@Resource

3.11.5.@PostConstruct @PreDestroy

3.12.Classpath3.12.1.@Component3.12.2.3.12.3.3.12.4.3.12.5.3.12.6.

3.13.LoadTimeWeaver

4.4.1.4.2.Resource4.3. Resource

4.3.1.UrlResource4.3.2.ClassPathResource4.3.3.FileSystemResource4.3.4.ServletContextResource4.3.5.InputStreamResource4.3.6.ByteArrayResource

4.4.ResourceLoader4.5.ResourceLoaderAware4.6. Resource

4.7.Applicationcontext Resource4.7.1.applicationcontext4.7.2.Applicationcontext4.7.3.FileSystemResource

5. BeanWrapper

5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper

5.4.1.5.4.2.PropertyEditor

6.SpringAOP6.1.

6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP

6.2.@AspectJ6.2.1.@AspectJ6.2.2.6.2.3.pointcut6.2.4.6.2.5.Introduction6.2.6.6.2.7.

6.3.SchemaAOP6.3.1.6.3.2.6.3.3.6.3.4.6.3.5.6.3.6.Advisor6.3.7.

6.4.AOP6.4.1.SpringAOPAspectJ6.4.2.SpringAOP@AspectJXML

6.5.6.6.

6.6.1.AOP6.7.@AspectJ6.8.SpringAspectJ

6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW

6.9.

7.SpringAOPAPIs7.1.7.2.SpringAPI

7.2.1.7.2.2.7.2.3.AspectJ7.2.4.7.2.5.7.2.6.

7.3.SpringAPI7.3.1.7.3.2.Spring

7.4.SpringAdvisorAPI7.5.ProxyFactoryBeanAOP

7.5.1.7.5.2.JavaBean7.5.3.JDKCGLIB7.5.4.7.5.5.7.5.6.“”

7.6.7.7.ProxyFactoryAOP7.8.7.9.“autoproxy”

7.9.1.bean7.9.2.

7.10.TargetSource7.10.1.7.10.2.7.10.3.7.10.4.ThreadLocal

7.11.Advice7.12.

8.8.1.8.2.

8.2.1.Mock8.2.2.

8.3.8.3.1.8.3.2.8.3.3.8.3.4.JDBC8.3.5.8.3.6.JUnit3.88.3.7.SpringTestContextFramework8.3.8.PetClinic

8.4.II.

9.9.1.9.2.9.3.9.4.

9.4.1.9.4.2.9.4.3.TransactionAwareDataSourceProxy

9.5.9.5.1.Spring9.5.2.9.5.3.9.5.4.bean9.5.5.<tx:advice/>9.5.6. @Transactional

9.5.7.9.5.8.9.5.9.AspectJ @Transactional

9.6.9.6.1.TransactionTemplate9.6.2.PlatformTransactionManager

9.7.9.8.

9.8.1.IBMWebSphere9.8.2.BEAWebLogic9.8.3.OracleOC4J

9.9.9.9.1. DataSource

9.10.

10.DAO10.1.10.2.10.3.DAO

11.JDBC11.1.

11.1.1.11.1.2.SpringJDBC

11.2.JDBCJDBC11.2.1.JdbcTemplate11.2.2.NamedParameterJdbcTemplate11.2.3.SimpleJdbcTemplate11.2.4.DataSource11.2.5.SQLExceptionTranslator11.2.6.SQL11.2.7.11.2.8.11.2.9.

11.3.11.3.1.DataSourceUtils11.3.2.SmartDataSource11.3.3.AbstractDataSource11.3.4.SingleConnectionDataSource11.3.5.DriverManagerDataSource11.3.6.TransactionAwareDataSourceProxy11.3.7.DataSourceTransactionManager11.3.8.NativeJdbcExtractor

11.4.JDBC11.4.1.JdbcTemplate11.4.2.SimpleJdbcTemplate

11.5.SimpleJdbcJDBC11.5.1.SimpleJdbcInsert11.5.2.SimpleJdbcInsert11.5.3.SimpleJdbcInsert11.5.4.SqlParameterSource11.5.5.SimpleJdbcCall11.5.6.SimpleJdbcCall11.5.7.SqlParameters11.5.8.SimpleJdbcCall11.5.9.SimpleJdbcCallResultSet/REFCursor

11.6.JavaJDBC11.6.1.SqlQuery11.6.2.MappingSqlQuery11.6.3.SqlUpdate11.6.4.StoredProcedure11.6.5.SqlFunction

11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.

12.ORM12.1.12.2.Hibernate

12.2.1.12.2.2.Spring SessionFactory

12.2.3.TheHibernateTemplate12.2.4.SpringDAO12.2.5.Hibernate3APIDAO12.2.6.12.2.7.12.2.8.12.2.9.vs12.2.10.Hibernate

12.3.JDO12.3.1.PersistenceManagerFactory12.3.2.JdoTemplateJdoDaoSupport12.3.3.JDOAPIDAO12.3.4.12.3.5.JdoDialect

12.4.OracleTopLink12.4.1.SessionFactory12.4.2.TopLinkTemplateandTopLinkDaoSupport12.4.3.TopLinkAPIDAO12.4.4.

12.5.iBATISSQLMaps12.5.1.SqlMapClient12.5.2. SqlMapClientTemplate SqlMapClientDaoSupport

12.5.3.iBATISAPIDAO12.6.JPA

12.6.1.SpringJPA12.6.2.JpaTemplate JpaDaoSupport

12.6.3.JPADAO12.6.4.

12.7.12.8.JpaDialect

III.TheWeb

13.WebMVCframeworkWeb13.1.

13.1.1.MVC13.1.2.SpringWebMVC

13.2.DispatcherServlet13.3.

13.3.1.AbstractController WebContentGenerator

13.3.2.13.3.3.MultiActionController13.3.4.

13.4.handlermapping13.4.1.BeanNameUrlHandlerMapping13.4.2.SimpleUrlHandlerMapping13.4.3.HandlerInterceptor

13.5.13.5.1.ViewResolver13.5.2.13.5.3.Rediret

13.6.13.6.1.AcceptHeaderLocaleResolver13.6.2.CookieLocaleResolver13.6.3.SessionLocaleResolver13.6.4.LocaleChangeInterceptor

13.7.13.7.1.13.7.2.13.7.3.

13.8.Springmultipartfileupload13.8.1.13.8.2.MultipartResolver13.8.3.

13.9.Spring13.9.1.13.9.2.form13.9.3.input13.9.4.checkbox13.9.5.checkboxes13.9.6.radiobutton13.9.7.radiobuttons13.9.8.password13.9.9.select

13.9.10.option13.9.11.options13.9.12.textarea13.9.13.hidden13.9.14.errors

13.10.13.11.conventionoverconfiguration

13.11.1. ControllerClassNameHandlerMapping

13.11.2. ModelMapModelAndView

13.11.3. RequestToViewNameTranslator

13.12.13.12.1.dispatcher13.12.2.@Controller13.12.3.@RequestMapping13.12.4.@RequestParam13.12.5.@ModelAttribute13.12.6.@SessionAttributes13.12.7.WebDataBinder

13.13.

14.14.1.14.2.JSPJSTL

14.2.1.14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTL14.2.3.

14.3.Tiles14.3.1.14.3.2.Tiles

14.4.VelocityFreeMarker14.4.1.14.4.2.Context14.4.3.14.4.4.14.4.5.

14.5.XSLT14.5.1.14.5.2.

14.6.PDF/Excel14.6.1.14.6.2.

14.7.JasperReports14.7.1.14.7.2.14.7.3. ModelAndView

14.7.4.14.7.5.Exporter

15.Web15.1.15.2.15.3.JavaServerFaces

15.3.1.DelegatingVariableResolver15.3.2.FacesContextUtils

15.4.Struts15.4.1.ContextLoaderPlugin15.4.2.ActionSupportClasses

15.5.Tapestry15.5.1.Springbeans

15.6.WebWork15.7.

16.PortletMVC16.1.

16.1.1.-MVCC16.1.2.-MVCV16.1.3.WebBean

16.2.DispatcherPortlet16.3.ViewRendererServlet16.4.

16.4.1.AbstractController PortletContentGenerator

16.4.2.16.4.3.Command16.4.4.PortletWrappingController

16.5.16.5.1.PortletModeHandlerMapping16.5.2.ParameterHandlerMapping16.5.3.PortletModeParameterHandlerMapping16.5.4. HandlerInterceptors16.5.5.HandlerInterceptorAdapter16.5.6.ParameterMappingInterceptor

16.6.16.7.Multipart

16.7.1. PortletMultipartResolver

16.7.2.16.8.16.9.Portlet

IV.

17.SpringWeb17.1.17.2.RMI

17.2.1.RmiServiceExporter17.2.2.

17.3.HessianBurlapHTTP17.3.1.Hessianco.DispatcherServlet17.3.2.HessianServiceExporterbean17.3.3.17.3.4.Burlap17.3.5.HessianBurlapHTTPBasic

17.4.HTTP17.4.1.Exposingtheserviceobject17.4.2.

17.5.WebServices17.5.1.JAX-RPCservletweb17.5.2.JAX-RPCweb17.5.3.JAX-RPCBean17.5.4.JAX-RPC17.5.5.JAX-WSservletweb17.5.6.JAX-WSweb17.5.7.SpringJAX-WSRI17.5.8.JAX-WSweb17.5.9.XFireWeb

17.6.JMS17.6.1.17.6.2.

17.7.17.8.

18.EnterpriseJavaBeans(EJB)18.1.18.2.EJB

18.2.1.18.2.2.SessionBean(SLSB)18.2.3.SLSB18.2.4.AccessingEJB2.xSLSBsversusEJB3SLSBs

18.3.SpringEJB18.3.1.EJB2.xbaseclasses18.3.2.EJB3

19.JMS(JavaMessageService)19.1.19.2.SpringJMS

19.2.1.JmsTemplate19.2.2.19.2.3.19.2.4.19.2.5.

19.3.19.3.1.19.3.2.SessionCallback ProducerCallback

19.4.19.4.1.19.4.2.-POJO19.4.3.SessionAwareMessageListener19.4.4.MessageListenerAdapter19.4.5.

19.5.JCA19.6.JMS

20.JMX20.1.20.2.BeanJMX

20.2.1.MBeanServer20.2.2.MBeanServer20.2.3.MBean20.2.4.MBean20.2.5.

20.3.Bean20.3.1.MBeanInfoAssembler20.3.2.20.3.3.JDK5.020.3.4.20.3.5.AutodetectCapableMBeanInfoAssembler20.3.6.Java20.3.7.MethodNameBasedMBeanInfoAssembler

20.4.BeanObjectName20.4.1. PropertiesProperties

20.4.2.MetadataNamingStrategy20.4.3.<context:mbean-export/>

20.5.JSR-16020.5.1.20.5.2.20.5.3.Burlap/Hessian/SOAPJMX

20.6.MBean20.7.

20.7.1.20.7.2.

20.8.

21.JCACCI21.1.21.2.CCI

21.2.1.21.2.2.SpringConnectionFactory21.2.3.CCI21.2.4.CCI

21.3.SpringCCI21.3.1.21.3.2.CciTemplate21.3.3.DAO21.3.4.21.3.5.21.3.6.CCIConnectionInteraction21.3.7.CciTemplate

21.4.CCI21.4.1.MappingRecordOperation21.4.2.MappingCommAreaOperation21.4.3.21.4.4.21.4.5.MappingRecordOperation21.4.6.MappingCommAreaOperation

21.5.

22.Spring22.1.22.2.Spring

22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator

22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.

23.Spring(Scheduling)(ThreadPooling)23.1.23.2.OpenSymphonyQuartz

23.2.1.JobDetailBean23.2.2. MethodInvokingJobDetailFactoryBean

23.2.3.triggersSchedulerFactoryBean23.3.JDKTimer

23.3.1.timers23.3.2. MethodInvokingTimerTaskFactoryBean

23.3.3. TimerFactoryBean

23.4.SpringTaskExecutor23.4.1.TaskExecutor23.4.2.TaskExecutor23.4.3.TaskExecutor

24.24.1.24.2.24.3.bean

24.3.1.24.3.2.JRubybeans24.3.3.Groovybeans24.3.4.BeanShellbeans

24.4.24.4.1.SpringMVC24.4.2.Validator

24.5.Bitsandbobs24.5.1.AOP-bean24.5.2.

24.6.

25.25.1.25.2.Spring25.3.

25.3.1.@Required

25.3.2.Spring@Annotations25.4.JakartaCommonsAttributes25.5.SpringAOP

25.5.1.25.5.2.

V.

26.26.1.26.2.SpringMVC

26.2.1.26.3.SimpleJdbcTemplate@RepositoryDAO

26.3.1.26.3.2.DataAccessObject26.3.3.

A.XMLSchema-basedconfigurationA.1.IntroductionA.2.XMLSchema-basedconfiguration

A.2.1.ReferencingtheschemasA.2.2.TheutilschemaA.2.3.ThejeeschemaA.2.4.ThelangschemaA.2.5.ThejmsschemaA.2.6.Thetx(transaction)schemaA.2.7.TheaopschemaA.2.8.ThecontextschemaA.2.9.ThetoolschemaA.2.10.Thebeansschema

A.3.SettingupyourIDEA.3.1.SettingupEclipseA.3.2.SettingupIntelliJIDEAA.3.3.Integrationissues

B.ExtensibleXMLauthoringB.1.IntroductionB.2.AuthoringtheschemaB.3.CodingaNamespaceHandlerB.4.CodingaBeanDefinitionParserB.5.Registeringthehandlerandtheschema

B.5.1.'META-INF/spring.handlers'B.5.2.'META-INF/spring.schemas'

B.6.UsingacustomextensioninyourSpringXMLconfigurationB.7.Meatierexamples

B.7.1.NestingcustomtagswithincustomtagsB.7.2.Customattributeson'normal'elements

B.8.FurtherResourcesC.spring-beans-2.0.dtdD.spring.tld

D.1.IntroductionD.2.Thebindtag

D.3.TheescapeBodytagD.4.ThehasBindErrorstagD.5.ThehtmlEscapetagD.6.ThemessagetagD.7.ThenestedPathtagD.8.ThethemetagD.9.Thetransformtag

E.spring-form.tldE.1.IntroductionE.2.ThecheckboxtagE.3.ThecheckboxestagE.4.TheerrorstagE.5.TheformtagE.6.ThehiddentagE.7.TheinputtagE.8.ThelabeltagE.9.TheoptiontagE.10.TheoptionstagE.11.ThepasswordtagE.12.TheradiobuttontagE.13.TheradiobuttonstagE.14.TheselecttagE.15.Thetextareatag

F.Spring2.5F.1.F.2.F.3.F.4.

3.1.bean3.2.Autowiringmodes3.3.3.4.Bean3.5.FeatureMatrix3.6.3.7.4.1.Resourcestrings5.1.5.2.PropertyEditors6.1. DefaultContextLoadTimeWeaver

LoadTimeWeaversDefaultContextLoadTimeWeaverLoadTimeWeavers

6.2.aspectj-weaving9.1.<tx:method/>9.2.<tx:annotation-driven/>9.3.@Transactional13.1.WebApplicationContextbean13.2.DispatcherServlet13.3.AbstractController13.4.13.5.CookieLocaleResolver13.6.ThemeResolver14.1.14.2.JasperReportsViewClasses14.3.JasperReportsMultiFormatViewMappingKey16.1.WebApplicationContextBean16.2.DispatcherPortlet16.3.AbstractController19.1.JMSlistener19.2.JMS<listener-container/>19.3.JMS<jca-listener-container/>20.1.20.2.20.3.21.1.UsageofInteractionexecutemethods21.2.UsageofInteractionexecutemethodsA.1.EclipseXMLeditorsD.1.AttributesD.2.AttributesD.3.AttributesD.4.AttributesD.5.AttributesD.6.AttributesD.7.AttributesD.8.AttributesE.1.AttributesE.2.AttributesE.3.AttributesE.4.AttributesE.5.AttributesE.6.AttributesE.7.AttributesE.8.AttributesE.9.Attributes

E.10.AttributesE.11.AttributesE.12.AttributesE.13.AttributesE.14.AttributesF.1.

MVCframework AOP

Spring SpringSpringChristianBauer( Hibernate) DocBook-XSLHibernateHealy

2004MartinFowler” Fowler

IoC

http://martinfowler.com/articles/injection.html

1

1.1.1.1.1.

JavaappletsnJavajavaClasswebClasses

FactoryAbstractFactoryBuilderDecorator ServiceLocator “ ......” wikisSpringIoCclassesSpringSpringFrameworkspringSpring

1.1.Spring

Spring

CoreIoC BeanFactoryFactoryContext() Core:JNDIContextbeansI18Nresourcebundle,servletDAOJDBCJDBCobjectsORM“/”APIs JPAJDOHibernate iBatisORMSpring“/”

Spring AOP AOPAllianceaspect-orientedprogrammingmethod-interceptorspointcutssource-level.NetattributeSpring WebWebServletlistenersIoCWebapplicationcontextWebWorkStrutsSpringSpringSpring MVCWebModel-View-ControllerMVCSpringMVC webformSpring

1.1.1.SpringAppletSpringWeb

SpringWeb

Spring WebEJB POJOSpringIoCemailwebSpringORMJPAHibernateJDOiBatisHibernateHibernateSessionFactoryweb ActionFormsclassHTTP

Spring

Spring Spring WebWorkStrutsTapestryUISpring ApplicationContext WebApplicationContext

WebServiceSpring Hessian-Burlap-Rmi- JaxRpcProxyFactory

EJBs-POJOs

SpringEJB POJOSessionBeanEJBWeb

2Spring2.02.5

2.1.2.2.(IoC)

2.2.1.bean2.2.2.XML2.2.3.XML2.2.4.Annotation()2.2.5.classpath

2.3.(AOP)2.3.1.AOPXML2.3.2.@AspectJ2.3.3.beanpointcut(beannamepointcutelement)2.3.4.AspectJAspectJload-timeweaving

2.4.2.4.1.XML2.4.2.Websphere2.4.3.JPA2.4.4.JMS2.4.5.JDBC

2.5.Web2.5.1.SpringMVC2.5.2.Portlet2.5.3.Annotation2.5.4.SpringMVC2.5.5.Tiles22.5.6.JSF1.22.5.7.JAX-WS

2.6.2.6.1.2.6.2.2.6.3.JMX2.6.4.SpringJCAadapter2.6.5.2.6.6.Java5(Tiger)

2.7.Spring2.52.7.1.

2.8.2.9.

JavaSEJavaEESpringFrameworkJava-Java1.4.2(1.4.2)springJava1.4.2,Java5Java6SpringFramework1.4.2Spring2.5,SpringJava6Spring2.0Java5SpringJ2EE1.3JavaEE5SpringBEAWebLogic 8.1, 9.0, 9.2 10,IBMWebSphere5.1,6.06.1,Oracle OC4J 10.1.3 11,JBoss 3.2, 4.0 4.2,Tomcat4.1,5.0,5.56.0,Jetty4.2,5.16.1,Resin2.1,3.03.1GlassFishV1V2.

2.1.SpringFrameworkSpring:200610Spring2.0,200711Spring2.5

Spring2.02.5SpringSpring2.x

2.2.(IoC)Spring2.0SpringIoC

2.2.1.beanSpringIoCbeanSpring2.0Springwebrequestsessionbean,'''hooks'Springbeans... 3.4“Bean”

2.2.2.XMLXML SchemaXMLSpringXMLSpringSpring A, XMLSchema-basedconfigurationSpring2.0DTDSchemaXMLDOCTYPESpring2.0'dist/resources''spring-beans-2.0.dtd'DTD

<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"

"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

2.2.3.XMLXML''SpringDSLdomainspecificlanguage

SpringSpringSpring B,ExtensibleXMLauthoring

2.2.4.Annotation()Spring 2.0 annotation, @Transactional, @Required and@PersistenceContext/@PersistenceUnit.Spring 2.5 Annotation: @AutowiredJSR-250@Resource, @PostConstructand@PreDestroyAnnotationbean 3.11 “Annotation-based” Spring MVCannotation2.5.3“Annotation”

2.2.5.classpathSpring2.5 classpathannotationstereotype: @Component,@Repository,@Service,@Controller.SpringbeanAnnotation-drivenbeanconfigurationisdiscussedin3.12.1“ @Component” .Annotationbean3.12.1“ @Component”

2.3.(AOP)Spring2.0AOPSpringAOPXMLSpring2.0AspectJpointcut@AspectJaspect 6 SpringAOP

2.3.1.AOPXMLSpring2.0Java AspectJadvice“SchemaAOP”

2.3.2.@AspectJSpring2.0@AspectJAspectJSpringAOP!“@AspectJ” @AspectJ

2.3.3.beanpointcut(beannamepointcutelement)Spring 2.5 bean(...)pointcut springbean 6.2.3.1 “PCD”

2.3.4.AspectJAspectJload-timeweavingSpring 2.5AspectJproxyAOP context:load-time-weaverAspectJMETA-INF/aop.xmlAspectJClassLoader(classtransformation)

6.8.4“SpringAspectJLTW”

2.4.

2.4.1.XMLSpring2.01.2.xIoCSpring2.5 context:load-time-weaver

mode="aspectj"

9

2.4.2.WebsphereSpring2.5IBMWebSphereApplicationServer,WebSphere'stransactionmanager.Transactionsuspension(WebSphere UOWManager

APIonWAS6.0.2.19+and6.0.1.9+WebSphere Application ServerSpringSpring 2.5WebSphereUowTransactionManagerPlatformTransactionManagerIBMJTASpring2.5 tx:jta-transaction-manager

IBMWebSphere, PlatformTransactionManager

2.4.3.JPASpring2.0JPASpringJDBCJPA 12.6“JPA” SpringSpring2.5OpenJPAOpenJPA1.0savepoint

2.4.4.JMSSpring2.0SpringJMS JmsTemplateSpring2.0 19.4.2“-POJO” Spring2.5JCA GenericMessageEndpointManagerJMSActionMQJORAMbroker 19.5“JCA”

Spring2.5XMLnamespaceJMSJMSJCAsetup 19.6“JMS”

2.4.5.JDBCSpringJDBC() NamedParameterJdbcTemplateJDBCJDBC

'?'

SimpleJdbcTemplateJava5+(Tiger) JdbcTemplate

Spring2.5 SimpleJdbcTemplate SimpleJdbcCallSimpleJdbcInsert

2.5.WebSpring2.0web Spring2.5controller

2.5.1.SpringMVC... SpringMVCconvention-over-configurationXML ModelAndView 13.11“conventionoverconfiguration” SpringMVC

2.5.2.PortletSpring2.0SpringMVCPorlet 16 PortletMVC

2.5.3.AnnotationSpring 2.5 MVC Annotation(, @RequestMapping,@RequestParam,@ModelAttribute SevletMVCPortletMVCControllerServletPortletAPIServletPortlet

2.5.4.SpringMVCSpringMVCJSP JIRASpringSpring2.0JSPSpringMVCJSPSpringJIRA 13.9“Spring” E,spring-form.tld

2.5.5.Tiles2Spring 2.5 tiles 2,Tiles SpringTiles 1Strutcs 1.xTiles 1 14.3“Tiles”

2.5.6.JSF1.2Spring 2.5 JSF 1.2 DelegatingVariableResolver

SpringBeanFacesELResolver

2.5.7.JAX-WSSpring2.5JAX-WS2.0/2.1Java6JavaEE5JAX-WSJAX-RPCWSDL/SOAPwebserviceJAX-WSwebservice

2.6.Spring2.0/2.5

2.6.1.Spring2.0JavabeanJRubyGroovyBeanShell 24 Spring2.5autowiringJRuby1.0

2.6.2.Spring2.5SpringTestContextFramework,(annotation)JUnit3.8JUnit4.4TestNG

SpringTestContextFrameworkSpring contextmanagementandcaching() ,dependencyinjectionoftestfixturesDI , transactionaltestmanagementrollback

8.3.7“SpringTestContextFramework”

2.6.3.JMXSpringFramework(Notification)MBean MBeanServer

20.7“”

20.2.5“”

Spring2.5 context:mbean-exportbeanSpring @ManagedResource

2.6.4.SpringJCAadapterSpring2.5SpringJCA(JCAresourceadapter)JCARARJ2EE

2.6.5.Spring2.0 23.4“Spring TaskExecutor” TaskExecutorSpringJMSSpring2.5JCA

2.6.6.Java5(Tiger)Spring2.02.5Java5

3.11“Annotation-based”

25.3.1“@ Required”

9.5.6“ @Transactional”

11.2.3“ SimpleJdbcTemplate”

12.6“JPA”

6.2“@AspectJ”

6.8.1“SpringAspectJdomainobject”

2.7.Spring2.5Spring1.2/2.0Spring2.5Spring2.0.xSpring2.5Spring2.5jarJDK1.4.2Spring2.0Spring2.5Java5Spring2.5Spring1.2.xSpringAPISpring2.0Spring1.2.x“deprecated”

Spring 1.2.xXML100%Spring 2.5Spring 1.2.x DTDSpring 2.0(scopes easierAOP transactionconfiguration)Spring2.5jarbugSpring2.5Spring2aspects90%Spring1.2.x1.2.xDTD,10%Spring22.0/2.5DTDXSDSpring2.5XML

2.7.1.SpringFramework2.0 'changelog.txt'

2.7.1.1.JDKSpring2.5JDK1.3Sun2006JDK1.3JDK1.4.2JDK1.3WebSphere4.05.0SpringFramework2.0.7/2.0.8JDK1.3

2.7.1.2.Spring2.5JarSpring2.5SpringWebMVC 'spring.jar'.SpringMVC'spring-webmvc.jar''spring-webmvc-portlet.jar' lib/modulesStruts1.x 'spring-webmvc-struts.jar'

:Spring DispatcherServletSpringWebMVC HessianHTTP DispatcherServlet,'spring-webmvc.jar'( 'spring-webmvc-

portlet/struts.jar')'spring.jar'Spring2.0 'spring-jmx.jar' 'spring-remoting.jar'Spring2.5'spring-context.jar'(JMXHTTP) 'spring-web.jar'

)Spring2.0 'spring-support.jar' 'spring-context-support.jar','spring-portlet.jar' 'spring-webmvc-portlet.jar',SpringWebMVCframework , 'spring-struts.jar' 'spring-webmvc-struts.jar'

Spring2.0'spring-jdo.jar','spring-jpa.jar','spring-hibernate3.jar',

'spring-toplink.jar' 'spring-ibatis.jar'Spring2.5 'spring-

orm.jar'

Spring 2.5 'spring-test.jar' 'spring-mock.jar',test contextframework 'spring-test.jar' 'spring-mock.jar'

Spring2.5 'spring-tx.jar' 'spring-dao.jar''spring-jca.jar'transactionframeworkSpring2.5jarOSGibundleOSGiSpring

2.7.1.3.XMLSpring2.0XSDSpringXMLDTD DTDbeanXSDbeanSpring1.2DTD 'singleton' Spring2.0DTD'singleton'

'scope'bean

2.7.1.4.Deprecated@deprecatedSpring2.0 Spring2.0deprecatedSpringFramework2.0 'changelog.txt'

/Spring2.0ResultReader:RowMapper

BeanFactoryBootstrap:BeanFactoryLocator

2.7.1.5.ApacheOJBSpring2.0SpringApacheOJB SpringModulesApacheOJB

2.7.1.6.iBATISiBATISSQLMaps1.3iBATISSQLMaps1.32.0/2.1

2.7.1.7.HibernateSpring2.5Hibernate2.1Hibernate3.0 Hibernate3.1Hibernate2.13.0Spring2.0.7/2.0.8Hibernate

2.7.1.8.JDOSpring2.5JDO1.0JDO2.0

JDO1.0spring2.0.7/2.0.8JDO1.0

2.7.1.9.UrlFilenameViewControllerSpring2.0 UrlFilenameViewControllerviewrequestUrlFilenameViewControllerSpring1.xSpring2.x SpringWebMVC

UrlFilenameViewControllerJavadocviewnamedetermination

2.8.Spring2.0 Spring[zip|tar.gz]' 26

Spring2.5PetClinicPetPortalSpring2.5Java5autoboxing,varargsJava56SDKPetClinicPetPortalSpring2.5

2.9.SpringSpring2.02.5ArthurLoderSpringFrameworkJavadocs

I.SpringFrameworkSpringFrameworkIoCSpringFrameworkIoCSpringAOPSpringFrameworkAOPJavaAOP80%SpringAspectJ ,AspectJJavaAOPSpringTDDSpring""

3 IoC()

4

5 BeanWrapper

6 SpringAOP

7 SpringAOPAPIs

8

3.IoC()3.1.3.2.-bean

3.2.1.3.2.2.3.2.3.bean3.2.4.

3.3.3.3.1.3.3.2.3.3.3.depends-on3.3.4.bean3.3.5.autowire3.3.6.3.3.7.

3.4.Bean3.4.1.Singleton3.4.2.Prototype3.4.3.Singletonbeansprototype-bean3.4.4.3.4.5.

3.5.bean3.5.1.3.5.2.

3.6.bean3.7.

3.7.1. BeanPostProcessorbean3.7.2. BeanFactoryPostProcessor

3.7.3.FactoryBean3.8.TheApplicationContext

3.8.1.BeanFactory ApplicationContext?3.8.2.MessageSource3.8.3.3.8.4.3.8.5.ApplicationContextWEB

3.9.singleton3.10.J2EERARSpringApplicationContext3.11.Annotation-based

3.11.1.@Autowired3.11.2.3.11.3.CustomAutowireConfigurer3.11.4.@Resource

3.11.5.@PostConstruct @PreDestroy

3.12.Classpath3.12.1.@Component3.12.2.3.12.3.3.12.4.3.12.5.3.12.6.

3.13.LoadTimeWeaver

4.4.1.4.2.Resource4.3. Resource

4.3.1.UrlResource4.3.2.ClassPathResource4.3.3.FileSystemResource4.3.4.ServletContextResource4.3.5.InputStreamResource4.3.6.ByteArrayResource

4.4.ResourceLoader4.5.ResourceLoaderAware4.6. Resource

4.7.Applicationcontext Resource4.7.1.applicationcontext4.7.2.Applicationcontext4.7.3.FileSystemResource

5. BeanWrapper

5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper

5.4.1.5.4.2.PropertyEditor

6.SpringAOP6.1.

6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP

6.2.@AspectJ6.2.1.@AspectJ6.2.2.6.2.3.pointcut6.2.4.6.2.5.Introduction6.2.6.6.2.7.

6.3.SchemaAOP6.3.1.6.3.2.6.3.3.6.3.4.6.3.5.6.3.6.Advisor6.3.7.

6.4.AOP6.4.1.SpringAOPAspectJ6.4.2.SpringAOP@AspectJXML

6.5.6.6.

6.6.1.AOP6.7.@AspectJ6.8.SpringAspectJ

6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW

6.9.

7.SpringAOPAPIs7.1.7.2.SpringAPI

7.2.1.7.2.2.7.2.3.AspectJ7.2.4.7.2.5.7.2.6.

7.3.SpringAPI7.3.1.7.3.2.Spring

7.4.SpringAdvisorAPI7.5.ProxyFactoryBeanAOP

7.5.1.7.5.2.JavaBean7.5.3.JDKCGLIB7.5.4.7.5.5.7.5.6.“”

7.6.7.7.ProxyFactoryAOP7.8.7.9.“autoproxy”

7.9.1.bean7.9.2.

7.10.TargetSource7.10.1.7.10.2.7.10.3.7.10.4.ThreadLocal

7.11.Advice7.12.

8.8.1.8.2.

8.2.1.Mock8.2.2.

8.3.8.3.1.8.3.2.8.3.3.8.3.4.JDBC8.3.5.8.3.6.JUnit3.88.3.7.SpringTestContextFramework8.3.8.PetClinic

8.4.

3IoC()

3.1.3.2.-bean

3.2.1.3.2.2.3.2.3.bean3.2.4.

3.3.3.3.1.3.3.2.3.3.3.depends-on3.3.4.bean3.3.5.autowire3.3.6.3.3.7.

3.4.Bean3.4.1.Singleton3.4.2.Prototype3.4.3.Singletonbeansprototype-bean3.4.4.3.4.5.

3.5.bean3.5.1.3.5.2.

3.6.bean3.7.

3.7.1. BeanPostProcessorbean3.7.2. BeanFactoryPostProcessor

3.7.3.FactoryBean3.8.TheApplicationContext

3.8.1.BeanFactory ApplicationContext?3.8.2.MessageSource3.8.3.3.8.4.3.8.5.ApplicationContextWEB

3.9.singleton3.10.J2EERARSpringApplicationContext3.11.Annotation-based

3.11.1.@Autowired

3.11.2.3.11.3.CustomAutowireConfigurer3.11.4.@Resource3.11.5.@PostConstruct @PreDestroy

3.12.Classpath3.12.1.@Component3.12.2.3.12.3.3.12.4.3.12.5.3.12.6.

3.13.LoadTimeWeaver

BeanFactoryApplicationContext?

BeanFactoryApplicationContext

BeanFactorybeanApplicationContext AOP

ApplicationContext

3.1.Spring(InversionofControlIoC) [1]

org.springframework.beans

org.springframework.contextSpringIoCBeanFactory ApplicationContext

BeanFactory SpringAOP()context (webWebApplicationContext)

BeanFactory ApplicationContext ApplicationContextBeanFactoryBeanFactoryApplicationContext

BeanFactoryApplicationContextApplicationContext

[1]

bean?'bean'''(component) ''(object) Spring(EnterpriseJavaBeans)

3.2.-beanSpring(backbone)SpringIoC beanbeanSpring bean beanbean

3.2.1.

org.springframework.beans.factory.BeanFactorySpringIoC IoCbeanbeanSpring BeanFactoryIoCSpringBeanFactory XmlBeanFactoryXML

SpringIoC

3.2.1.1.SpringIoC

SpringIoCCLASSPATH

IoC4 Resource

XML SpringIoC3.11“Annotation-based” Spring

SpringIoC web)8XML( 3.8.5“ ApplicationContext

WEB” )SpringIoCbeanbean XML<beans/> <bean/>

beanbean DAOStrutsActionHibernate SessionFactoryJMS QueuebeanXML

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<beanid="..."class="...">

<!--collaboratorsandconfigurationforthisbeangohere-->

</bean>

<beanid="..."class="...">

<!--collaboratorsandconfigurationforthisbeangohere-->

</bean>

<!--morebeandefinitionsgohere-->

</beans>

3.2.2.SpringIoC

ApplicationContextcontext=newClassPathXmlApplicationContext(

newString[]{"services.xml","daos.xml"});

//anApplicationContextisalsoaBeanFactory(viainheritance)

BeanFactoryfactory=context;

3.2.2.1.XMLXMLXML ApplicationContextApplicationContextdefintionreaderbeanSpring

<beans>

<importresource="services.xml"/>

<importresource="resources/messageSource.xml"/>

<importresource="/resources/themeSource.xml"/>

<beanid="bean1"class="..."/>

<beanid="bean2"class="..."/>

</beans>

3 services.xmlmessageSource.xmlthemeSource.xmlbeanservices.xml messageSource.xmlthemeSource.xml‘/’‘/’SpringXML Schema(DTD)XMLbean

3.2.3.beanSpringIoCbeanbean bean(XML <bean/>

bean BeanDefinition

bean

beanbean

beanbean beancollaborators beandependencies .

beanbeanbeanproperties

3.1.bean

class 3.2.3.2“bean”

beanbeanJavaaccountManager

accountService userDao

loginController

beanSpringAOPbean

name 3.2.3.1“bean”

scope 3.4“Bean”

constructorarguments 3.3.1“”

properties 3.3.1“”

autowiringmode 3.3.5“autowire”

dependencycheckingmode 3.3.6“”

lazy-initializationmode 3.3.4“bean”

initializationmethod 3.5.1.1“”

destructionmethod 3.5.1.2“”

beanbean BeanFactoryBeanFactoryDefaultListableBeanFactoryregisterSingleton(..)

3.2.3.1.beanbeanid( ) idIoC

XML idnamebean id XMLIDxmlidXML beanidXMLXMLIDbeanXMLid bean

beanname namename(bean)

3.2.3.1.1.bean

bean id name beanbean beanXML

<aliasname="fromName"alias="toName"/>

beancom.exampleFoo Foo Bar

bean class

com.example.Foo$Bar

$

fromNamebean toName

AXML componentA-dataSourceDataSourcebeanBXMLcomponentB-dataSourcebeanMyAppXML myApp-dataSourcebeanXMLApplicationContextMyAppXML alias

<aliasname="componentA-dataSource"alias="componentB-dataSource"/>

<aliasname="componentA-dataSource"alias="myApp-dataSource"/>

3.2.3.2.beanbean beanbeanbean

XML <bean/> class class(BeanDefinitionClass)( 3.2.3.2.3

“” 3.6“bean” )class bean(new) beanclass)

3.2.3.2.1.

beanSpringclass classIoCJavaBean SpringJavaBean(()beanstyle) JavaBeanSpringXMLbean

<beanid="exampleBean"class="examples.ExampleBean"/>

<beanname="anotherExample"class="examples.ExampleBeanTwo"/>

bean

3.2.3.2.2.

bean class factory-methodbean Spring()

beanbean

<beanid="exampleBean"

class="examples.ExampleBean2"

factory-method="createInstance"/>

bean

3.2.3.2.3.

beanbeanbeanfactory-method

<!--thefactorybean,whichcontainsamethodcalledcreateInstance()

<beanid="serviceLocator"class="com.foo.DefaultServiceLocator">

<!--injectanydependenciesrequiredbythislocatorbean-->

</bean>

<!--thebeantobecreatedviathefactorybean-->

<beanid="exampleBean"

factory-bean="serviceLocator"

factory-method="createInstance"/>

bean bean (DI)

SpringfactorybeanSpring bean FactoryBean

FactoryBean

3.2.4.BeanFactory bean BeanFactory

Resourceres=newFileSystemResource("beans.xml");

BeanFactoryfactory=newXmlBeanFactory(res);

getBean(String)bean BeanFactorygetBean(String) SpringAPI

3.3.Springbean)beanbean

3.3.1.DIbean bean ServiceLocator 3InversionofControlIoC DIbeanDI Setter

3.3.1.1.DI statticbean

publicclassSimpleMovieLister{

//theSimpleMovieListerhasadependencyonaMovieFinder

privateMovieFindermovieFinder;

//aconstructorsothattheSpringcontainercan'inject'a

publicSimpleMovieLister(MovieFindermovieFinder){

this.movieFinder=movieFinder;

}

//businesslogicthatactually'uses'theinjectedMovieFinder

}

3.3.1.1.1.

beanbeanbean

packagex.y;

publicclassFoo{

publicFoo(Barbar,Bazbaz){

//...

}

}

Bar Baz

<beans>

<beanname="foo"class="x.y.Foo">

<constructor-arg>

<beanclass="x.y.Bar"/>

</constructor-arg>

<constructor-arg>

<beanclass="x.y.Baz"/>

</constructor-arg>

</bean>

</beans>

beanbean() <value>true<value>Spring

packageexamples;

publicclassExampleBean{

//No.ofyearstothecalculatetheUltimateAnswer

privateintyears;

//TheAnswertoLife,theUniverse,andEverything

privateStringultimateAnswer;

publicExampleBean(intyears,StringultimateAnswer){

this.years=years;

this.ultimateAnswer=ultimateAnswer;

}

}

3.3.1.1.1.1.'type'

<beanid="exampleBean"class="examples.ExampleBean">

<constructor-argtype="int"value="7500000"/>

<constructor-argtype="java.lang.String"value="42"/>

</bean>

Setter?SpringsettersetterDI

DIsetter

3.3.1.1.1.2.index

<beanid="exampleBean"class="examples.ExampleBean">

<constructor-argindex="0"value="7500000"/>

<constructor-argindex="1"value="42"/>

</bean>

2 index0

3.3.1.2.Setterstaticbeanbeansetter setterDIsetter Java

publicclassSimpleMovieLister{

//theSimpleMovieListerhasadependencyontheMovieFinder

privateMovieFindermovieFinder;

//asettermethodsothattheSpringcontainercan'inject'a

publicvoidsetMovieFinder(MovieFindermovieFinder){

this.movieFinder=movieFinder;

}

//businesslogicthatactually'uses'theinjectedMovieFinder

}

BeanFactorybeanSetterBeanDefinition PropertyEditor

SpringXMLSpringIoCbean

bean BeanFactorySpringXML BeanFactoryApplicationContext

bean beanbean

bean

beanABBAABbeanSpringIoCBeanCurrentlyInCreationException

settersettersetterbeanbeanbean

SpringString intlongStringboolean

Springbeanbeanbeanbeanbean beansingletonbean ApplicationContextsingletonbeanbeanbeanbeanbeanbeanbeanbeanSpringbeanSpringbeanSpringbeanbean

ApplicationContextbeansingletonbean ApplicationContext

singletonbeanbeanbeanbean beanAbeanBSpringIoCbeanAsetterbeanB beansingletonlifecycle IntializingBeaninitcallback

3.3.1.3.XMLSetterDIXML

<beanid="exampleBean"class="examples.ExampleBean">

<!--setterinjectionusingthenested<ref/>element-->

<propertyname="beanOne"><refbean="anotherExampleBean"/></property>

<!--setterinjectionusingtheneater'ref'attribute-->

<propertyname="beanTwo"ref="yetAnotherBean"/>

<propertyname="integerProperty"value="1"/>

</bean>

<beanid="anotherExampleBean"class="examples.AnotherBean"/>

<beanid="yetAnotherBean"class="examples.YetAnotherBean"/>

publicclassExampleBean{

privateAnotherBeanbeanOne;

privateYetAnotherBeanbeanTwo;

privateinti;

publicvoidsetBeanOne(AnotherBeanbeanOne){

this.beanOne=beanOne;

}

publicvoidsetBeanTwo(YetAnotherBeanbeanTwo){

this.beanTwo=beanTwo;

}

publicvoidsetIntegerProperty(inti){

this.i=i;

}

}

beansetterxml

<beanid="exampleBean"class="examples.ExampleBean">

<!--constructorinjectionusingthenested<ref/>element-->

<constructor-arg>

<refbean="anotherExampleBean"/>

</constructor-arg>

<!--constructorinjectionusingtheneater'ref'attribute-->

<constructor-argref="yetAnotherBean"/>

<constructor-argtype="int"value="1"/>

</bean>

<beanid="anotherExampleBean"class="examples.AnotherBean"/>

<beanid="yetAnotherBean"class="examples.YetAnotherBean"/>

publicclassExampleBean{

privateAnotherBeanbeanOne;

privateYetAnotherBeanbeanTwo;

privateinti;

publicExampleBean(

AnotherBeananotherBean,YetAnotherBeanyetAnotherBean,inti){

this.beanOne=anotherBean;

this.beanTwo=yetAnotherBean;

this.i=i;

}

}

xmlbean ExampleBean

static

<beanid="exampleBean"class="examples.ExampleBean"

factory-method="createInstance">

<constructor-argref="anotherExampleBean"/>

<constructor-argref="yetAnotherBean"/>

<constructor-argvalue="1"/>

</bean>

<beanid="anotherExampleBean"class="examples.AnotherBean"/>

<beanid="yetAnotherBean"class="examples.YetAnotherBean"/>

publicclassExampleBean{

//aprivateconstructor

privateExampleBean(...){

...

}

//astaticfactorymethod;theargumentstothismethodcanbe

//consideredthedependenciesofthebeanthatisreturned,

//regardlessofhowthoseargumentsareactuallyused.

publicstaticExampleBeancreateInstance(

AnotherBeananotherBean,YetAnotherBeanyetAnotherBean,inti){

ExampleBeaneb=newExampleBean(...);

//someotheroperations...

returneb;

}

}

staticconstructor-arg static factory-bean

class

3.3.2.beanbeaninlinebeanspringXML <property/><constructor-arg/>

3.3.2.1.( Strings)<value/> JavaBean PropertyEditorjava.lang.String

<beanid="myDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<!--resultsinasetDriverClassName(String)call-->

<propertyname="driverClassName">

<value>com.mysql.jdbc.Driver</value>

</property>

<propertyname="url">

<value>jdbc:mysql://localhost:3306/mydb</value>

</property>

<propertyname="username">

<value>root</value>

</property>

<propertyname="password">

<value>masterkaoli</value>

</property>

</bean>

<property/><constructor-arg/>'value'

<beanid="myDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<!--resultsinasetDriverClassName(String)call-->

<propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>

<propertyname="url"value="jdbc:mysql://localhost:3306/mydb"/>

<propertyname="username"value="root"/>

<propertyname="password"value="masterkaoli"/>

</bean>

Spring <value/>value java.util.Properties

<beanid="mappings"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<!--typedasajava.util.Properties-->

<propertyname="properties">

<value>

jdbc.driver.className=com.mysql.jdbc.Driver

jdbc.url=jdbc:mysql://localhost:3306/mydb

</value>

</property>

</bean>

SpringJavaBean PropertyEditor<value/>java.util.Properties

Spring <value/>value

3.3.2.1.1.idref

idrefbeanid<constructor-arg/> <property/>

<beanid="theTargetBean"class="..."/>

<beanid="theClientBean"class="...">

<propertyname="targetName">

<idrefbean="theTargetBean"/>

</property>

</bean>

bean

<beanid="theTargetBean"class="..."/>

<beanid="client"class="...">

<propertyname="targetName"value="theTargetBean"/>

</bean>

idrefbean clientbeantargetName clientbeanclientbean prototypebeanbeanXMLbeanbean idlocalXMLXMLbean

<propertyname="targetName">

<!--abeanwithanidof'theTargetBean'mustexist;otherwiseanXMLexceptionwillbethrown-->

<idreflocal="theTargetBean"/>

</property>

ProxyFactoryBeanbean<idref/>AOPinterceptor<idref/>ID

3.3.2.2.bean<constructor-arg/><property/>refbeanbeanbeansingletonbeanid/name<ref/>beanbeanbeanXMLXML' bean'bean idname

<refbean="someBean"/>

reflocalbeanXMLbean localbeanidbeanXMLbeanlocal

<reflocal="someBean"/>

refparentbean parentbeanid namebeanparentbeanbean(beanbean)

<!--intheparentcontext-->

<beanid="accountService"class="com.foo.SimpleAccountService">

<!--insertdependenciesasrequiredashere-->

</bean>

<!--inthechild(descendant)context-->

<beanid="accountService"<--noticethatthenameofthisbeanisthe

class="org.springframework.aop.framework.ProxyFactoryBean">

<propertyname="target">

<refparent="accountService"/><--noticehowwerefertothe

</property>

<!--insertotherconfigurationanddependenciesasrequiredashere-->

</bean>

3.3.2.3.beanbeaninnerbeanbean <property/> <constructor-arg/><bean/>beanbeanidnameidname

<beanid="outer"class="...">

<!--insteadofusingareferencetoatargetbean,simplydefinethetargetbeaninline-->

<propertyname="target">

<beanclass="com.example.Person"><!--thisistheinnerbean-->

<propertyname="name"value="FionaApple"/>

<propertyname="age"value="25"/>

</bean>

</property>

</bean>

bean scopeidnamebean prototypebeanbeanbean

3.3.2.4.<list/><set/><map/><props/>JavaCollectionListSetMapProperties

<beanid="moreComplexObject"class="example.ComplexObject">

<!--resultsinasetAdminEmails(java.util.Properties)call-->

<propertyname="adminEmails">

<props>

<propkey="administrator">administrator@example.org</prop>

<propkey="support">support@example.org</prop>

<propkey="development">development@example.org</prop>

</props>

</property>

<!--resultsinasetSomeList(java.util.List)call-->

<propertyname="someList">

<list>

<value>alistelementfollowedbyareference</value>

<refbean="myDataSource"/>

</list>

</property>

<!--resultsinasetSomeMap(java.util.Map)call-->

<propertyname="someMap">

<map>

<entry>

<key>

<value>anentry</value>

</key>

<value>justsomestring</value>

</entry>

<entry>

<key>

<value>aref</value>

</key>

<refbean="myDataSource"/>

</entry>

</map>

</property>

<!--resultsinasetSomeSet(java.util.Set)call-->

<propertyname="someSet">

<set>

<value>justsomestring</value>

<refbean="myDataSource"/>

</set>

</property>

</bean>

mapkeyvaluesetvalue

bean|ref|idref|list|set|map|props|value|null

3.3.2.4.1.

2.0SpringIoC parent-stylechild-style<list/><map/><set/><props/>

parent-childbeanbean 3.6“bean”

Findbelowanexampleofthecollectionmergingfeature:

<beans>

<beanid="parent"abstract="true"class="example.ComplexObject">

<propertyname="adminEmails">

<props>

<propkey="administrator">administrator@example.com</prop>

<propkey="support">support@example.com</prop>

</props>

</property>

</bean>

<beanid="child"parent="parent">

<propertyname="adminEmails">

<!--themergeisspecifiedonthe*child*collectiondefinition-->

<propsmerge="true">

<propkey="sales">sales@example.com</prop>

<propkey="support">support@example.co.uk</prop>

</props>

</property>

</bean>

<beans>

childbeanadminEmails<props/>merge=true childbeanadminEmailsadminEmails

administrator=administrator@example.com

sales=sales@example.com

support=support@example.co.uk

beanProperties<props/>bean support

<list/><map/><set/> <list/> List beanbean MapSet

Properties MapSetProperties

Spring 2.0 map list Exceptionmergebeanbeanmerge

3.3.2.4.2.(Java5+)

Java5Java6() StringCollectionSpringbeanCollectionSpringCollection

publicclassFoo{

privateMap<String,Float>accounts;

publicvoidsetAccounts(Map<String,Float>accounts){

this.accounts=accounts;

}

}

<beans>

<beanid="foo"class="x.y.Foo">

<propertyname="accounts">

<map>

<entrykey="one"value="9.99"/>

<entrykey="two"value="2.75"/>

<entrykey="six"value="3.99"/>

</map>

</property>

</bean>

</beans>

foobeanaccounts Map<String, Float>Springvalue Float 9.99

2.753.99Float

3.3.2.5.Nulls<null/>nullSpring xmlemail

<beanclass="ExampleBean">

<propertyname="email"><value/></property>

</bean>

Java exampleBean.setEmail("")null<null>

<beanclass="ExampleBean">

<propertyname="email"><null/></property>

</bean>

Java exampleBean.setEmail(null)

3.3.2.6.XML“” <property/>bean

3.3.2.6.1.XML-basedconfigurationmetadatashortcuts

<property/><constructor-arg/><entry/>valueattribute <value/>

<propertyname="myProperty">

<value>hello</value>

</property>

<constructor-arg>

<value>hello</value>

</constructor-arg>

<entrykey="myKey">

<value>hello</value>

</entry>

<propertyname="myProperty"value="hello"/>

<constructor-argvalue="hello"/>

<entrykey="myKey"value="hello"/>

The <property/> and <constructor-arg/> elements support a similarshortcut'ref'attributewhichmaybeusedinsteadofafullnested<ref/>element.Therefore,thefollowing:<property/><constructor-arg/>ref <ref/>

<propertyname="myProperty">

<refbean="myBean">

</property>

<constructor-arg>

<refbean="myBean">

</constructor-arg>

<propertyname="myProperty"ref="myBean"/>

<constructor-argref="myBean"/>

<refbean="xxx"> <reflocal="xxx">xmlbeanmapentry key/key-ref value/value-ref

<entry>

<key>

<refbean="myKeyBean"/>

</key>

<refbean="myValueBean"/>

</entry>

<entrykey-ref="myKeyBean"value-ref="myValueBean"/>

<refbean="xxx"> <reflocal="xxx">

3.3.2.6.2.p

XML""p2.0Spring XMLSchema beanXMLSchemaXSDSpringpschema <property/>beanp bean

attributebeanpropertyXMLbeanXMLp

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<beanname="classic"class="com.example.ExampleBean">

<propertyname="email"value="foo@bar.com/>

</bean>

<beanname="p-namespace"class="com.example.ExampleBean"

p:email="foo@bar.com"/>

</beans>

beanpemailSpringbeanpropertypschemaattributebeanpropertyThisnextexample includes twomorebeandefinitions thatbothhavea

referencetoanotherbean:beanbean

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<beanname="john-classic"class="com.example.Person">

<propertyname="name"value="JohnDoe"/>

<propertyname="spouse"ref="jane"/>

</bean>

<beanname="john-modern"

class="com.example.Person"

p:name="JohnDoe"

p:spouse-ref="jane"/>

<beanname="jane"class="com.example.Person">

<propertyname="name"value="JaneDoe"/>

</bean>

</beans>

Asyoucansee,thisexampledoesn'tonlyincludeapropertyvalueusingthe p-namespace, but also uses a special format to declare propertyreferences. Whereas the first bean definition uses <property

name="spouse" ref="jane"/> to create a reference from bean john tobean jane, the second bean definition uses p:spouse-ref="jane" as anattributetodotheexactsamething.Inthiscase'spouse' isthepropertynamewhereasthe'-ref'partindicatesthatthisisnotastraightvaluebutratherareferencetoanotherbean.ppropertybean <propertyname="spouse"ref="jane"/>beanjohnbeanjanebean p:spouse-ref="jane"attribute" spouse"property" -ref“bean

pXMLbean RefpXML

3.3.2.7.bean nullbean

<beanid="foo"class="foo.Bar">

<propertyname="fred.bob.sammy"value="123"/>

</bean>

foo beanfred bob bobsammy sammy123 foofredfredbobbeanNullPointerException

3.3.3. depends-on

beanbeanbeanbeanxml <ref/>bean depends-on

beanbean depends-onbean

<beanid="beanOne"class="ExampleBean"depends-on="manager"/>

<beanid="manager"class="ManagerBean"/>

bean 'depends-on'bean 'depends-on'bean

<beanid="beanOne"class="ExampleBean"depends-on="manager,accountDao">

<propertyname="manager"ref="manager"/>

</bean>

<beanid="manager"class="ManagerBean"/>

<beanid="accountDao"class="x.y.jdbc.JdbcAccountDao"/>

“depends-on” singletonbean depends-onbeanbean

3.3.4.beanApplicationContextsingleton bean ApplicationContextsingleton

beansingletonbean ApplicationContextbeanbeanIoC

XML <bean/>lazy-init

<beanid="lazy"class="com.foo.ExpensiveToCreateBean"lazy-init="true"

<beanname="not.lazy"class="com.foo.AnotherBean"/>

ApplicationContext lazybeanApplicationContext not.lazy

beansingletonbean ApplicationContextsingletonbeansingletonbeanbeanIocbeanbeansingletonbean<beans/>'default-lazy-init'

<beansdefault-lazy-init="true">

<!--nobeanswillbepre-instantiated...-->

</beans>

3.3.5.autowireSpringIoCautowire beanSpring BeanFactorybeanbeanautowireautowirebeanbeanautowirebeanautowire

[2]xml <bean/>autowire:

3.2.Autowiringmodes

no

byName beanbeanautowirebynamebean master setMaster(..)Springmasterbeanmaster

byType beanbean byTypebean dependency-check="objects"

Spring

constructor byTypebean

autodetect beanintrospection constructorbyType byType

propertyconstructor-arg StringClass byTypeconstructor key StringMapMapvaluebeanMapkeybean

bean

javajava

SpringSpring

SpringbeansetterMapbeanbean'autowire-candidate''false'beanbean 'primary''true'beanbeanJava5bean2bean

3.3.5.1.beanbeanXMLbean <bean/> autowire-candidatefalsebeanbean <beans/>'default-autowire-candidates' 'Repository'bean"*Repository“bean'false'

beanbeanbeanbeanbean

3.3.6.Springbeanbeanbeanbeanbean notxmlbeandependency-check

3.3.

none bean

simple

object

all

Java5annotations 25.3.1“@ Required”

3.3.7.bean singletonsingletonbeansingletonbeansingletonbeansingletonbeanbeanbeanpropertybeansingletonbeanAsingletonprototypebeanBbeanAbeanAbeanB

BeanFactoryAware beanAbean getBean("B") beanB

//aclassthatusesastatefulCommand-styleclasstoperformsomeprocessing

packagefiona.apple;

//lotsofSpring-APIimports

importorg.springframework.beans.BeansException;

importorg.springframework.beans.factory.BeanFactory;

importorg.springframework.beans.factory.BeanFactoryAware;

publicclassCommandManagerimplementsBeanFactoryAware{

privateBeanFactorybeanFactory;

publicObjectprocess(MapcommandState){

//grabanewinstanceoftheappropriateCommand

Commandcommand=createCommand();

//setthestateonthe(hopefullybrandnew)Commandinstance

command.setState(commandState);

returncommand.execute();

}

//theCommandreturnedherecouldbeanimplementationthatexecutesasynchronously,orwhatever

protectedCommandcreateCommand(){

return(Command)this.beanFactory.getBean("command");

}

publicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{

this.beanFactory=beanFactory;

……Tapestry 4.0 abstract

TapestryBlog

}

}

SpringFrameworkSpringIoC

3.3.7.1.LookupLookupbeanbeanLookupbeanLookupSpringCGLIBLookupbeanLookup(CommandManager)SpringcreateCommand() CommandManager

Spring

packagefiona.apple;

//nomoreSpringimports!

publicabstractclassCommandManager{

publicObjectprocess(ObjectcommandState){

//grabanewinstanceoftheappropriateCommandinterface

Commandcommand=createCommand();

//setthestateonthe(hopefullybrandnew)Commandinstance

command.setState(commandState);

returncommand.execute();

}

//okay...butwhereistheimplementationofthismethod?

protectedabstractCommandcreateCommand();

}

( CommandManager)

<public|protected>[abstract]<return-type>theMethodName(no-arguments

<!--astatefulbeandeployedasaprototype(non-singleton)-->

<beanid="command"class="fiona.apple.AsyncCommand"scope="prototype">

<!--injectdependencieshereasrequired-->

</bean>

<!--commandProcessorusesstatefulCommandHelper-->

<beanid="commandManager"class="fiona.apple.CommandManager">

<lookup-methodname="createCommand"bean="command"/>

</bean>

commandManagerbeancommandbean createCommand

commandprototype singleton commandbeanCGLIBjarclasspathSpring final final

bean(serialized)

S

erviceLocatorFactoryBean( org.springframework.beans.factory.config

) ObjectFactoryCreatingFactoryBeanlookupSpringlookup ObjectFactoryServiceLocatorFactoryBean

Javadocs( Spring)

3.3.7.2.LookupbeanXMLbean replaced-methodcomputeValue

publicclassMyValueCalculator{

publicStringcomputeValue(Stringinput){

//somerealcode...

}

//someothermethods...

}

org.springframework.beans.factory.support.MethodReplacer

/**meanttobeusedtooverridetheexistingcomputeValue(String)

implementationinMyValueCalculator

*/

publicclassReplacementComputeValueimplementsMethodReplacer{

publicObjectreimplement(Objecto,Methodm,Object[]args)throwsThrowable{

//gettheinputvalue,workwithit,andreturnacomputedresult

Stringinput=(String)args[0];

...

return...;

}

}

bean

<beanid="myValueCalculatorclass="x.y.z.MyValueCalculator">

<!--arbitrarymethodreplacement-->

<replaced-methodname="computeValue"replacer="replacementComputeValue">

<arg-type>String</arg-type>

</replaced-method>

</bean>

<beanid="replacementComputeValue"class="a.b.c.ReplacementComputeValue"/>

<replaced-method/><arg-type/>overrideoverloadjava.lang.String

java.lang.String

String

Str

[2]3.3.1“”

3.4.Beanbeanbean “(recipe)” beanclass“”JavaClassSpringFrameworkwebSpringApplicationContext

3.4.Bean

singleton SpringIoCbean

prototype bean

request HTTPbeanHTTPbean beanwebSpring

session HTTPSessionbeanwebSpring ApplicationContext

globalsession

HTTPSessionbeanportletcontextwebSpring ApplicationContext

3.4.1.Singletonbeansingleton,SpringIoCbeanbeanidbeanbeanbeansingltonSpringIoCbean singletoncache bean

Springsingleton bean“”GoFSingletonGoF SingletonClassLoaderclassSpringsingletoncontainerbeanSpringclassbeanSpring bean SingletonSpringXMLbeansingleton

<beanid="accountService"class="com.foo.DefaultAccountService"/>

<!--thefollowingisequivalent,thoughredundant(singletonscopeisthedefault);using

<beanid="accountService"class="com.foo.DefaultAccountService"scope="singleton"/>

<!--thefollowingisequivalentandpreservedforbackwardcompatibilityin

<beanid="accountService"class="com.foo.DefaultAccountService"singleton="true"/>

3.4.2.PrototypePrototypebeanbeanbean getBean() beanbeanprototypebeansingletonSpringprototype DAOprototypeDAOsingleton

XMLbeanprototype

<!--usingspring-beans-2.0.dtd

<beanid="accountService"class="com.foo.DefaultAccountService"scope="prototype"/>

<!--thefollowingisequivalentandpreservedforbackwardcompatibilityin

<beanid="accountService"class="com.foo.DefaultAccountService"singleton="false"/>

prototypebeanSpringprototypebeanprototypeprototypeprototypeSpringprototypebean beanbeanprototypebeanSpringJava new 3.5.1“” Springbean

3.4.3.Singletonbeansprototype-beanprototypebeansingleton-scopedbean prototype-scopedbeansingleton-scopedbeanprototypebeansingletonbean...scopedbeanprototypesingleton-scopedbeanprototype-scopedbeanprototype-scopedbeansingletonbeanSpringsingletonbean(prototype)bean

3.3.7“”

XMLbean'spring-beans.dtd'DTD bean") 'spring-beans-2.0.dtd'DTDSpring2.0XSDschema" scope"(" singleton" DTDXSD" scope")" singleton" 'spring-beans.dtd'DTD " scope"'spring-beans-2.0.dtd'DTD 'spring-beans-2.0.xsd'XSD

3.4.4.requestsessionglobalsessionwebweb

webSpringApplicationContext XmlWebApplicationContext

Spring IoC XmlBeanFactory

ClassPathXmlApplicationContext IllegalStateException

bean

3.4.4.1.webrequestsessionglobalsessionbeanwebbean bean“”singletonprototypeservlet...SpringWebMVCSpring DispatcherServletDispatcherPortlet

DispatcherServlet DispatcherPortlet

Spring'sDispatcherServletServlet2.4WebJSFStrutsWeb 'web.xml'

javax.servlet.ServletRequestListener

<web-app>

...

<listener>

<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>

</listener>

...

</web-app>

webServlet2.4 javax.servlet.Filterweb.xml

<web-app>

..

<filter>

<filter-name>requestContextFilter</filter-name>

<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>requestContextFilter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

...

</web-app>

RequestContextListenerRequestContextFilter HTTPrequestrequestsessionbean

3.4.4.2.Requestbean

<beanid="loginAction"class="com.foo.LoginAction"scope="request"/>

HTTPSpring loginActionbeanLoginActionbean loginActionbeanHTTPrequest loginAction

3.4.4.3.Sessionbean

<beanid="userPreferences"class="com.foo.UserPreferences"scope="session"/>

HTTP SessionSpringuserPreferences beanuserPreferences beanuserPreferencesbeanHTTPSession requestHTTP Session

userPreferences HTTP Session HTTPbean

3.4.4.4.globalsessionbean

<beanid="userPreferences"class="com.foo.UserPreferences"scope="globalSession"/>

globalsessionHTTPSessionportletwebPortlet Sessionportletwebportlet globalsessionbeanportletSessionServletweb globalsessionbeanHTTP Session

3.4.4.5.beanHTTPrequestSession beanSpringIoCbeanHttprequestbeanbeanAOPbeanHTTPrequest

<aop:scoped-proxy/>singletonprototypebeansingletonbeanscopedproxy BeanCreationException

bean“ ”“ ”

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<!--aHTTPSession-scopedbeanexposedasaproxy-->

<beanid="userPreferences"class="com.foo.UserPreferences"

<!--thisnextelementeffectstheproxyingofthesurroundingbean-->

<aop:scoped-proxy/>

</bean>

<!--asingleton-scopedbeaninjectedwithaproxytotheabovebean

<beanid="userService"class="com.foo.SimpleUserService">

<!--areferencetotheproxied

'userPreferences'

<propertyname="userPreferences"ref="userPreferences"/>

</bean>

</beans>

Bean <aop:scoped-proxy/>(classpathCGLIB

Schema-based configuration) request,session, globalSession ' '<aop:scoped-proxy/>( 'userPreferences'Bean):

<beanid="userPreferences"class="com.foo.UserPreferences"scope="session"/>

<beanid="userManager"class="com.foo.UserManager">

<propertyname="userPreferences"ref="userPreferences"/>

</bean>

singleton bean userManagerHTTP Sessionbean userPreferencessingletonuserManagerbean userPreferencesbean userManager

userPreferencesbeanHTTP Sessionbean userManagerHTTPSessionHTTP SessionuserPreferences

UserPreferences UserPreferencesHTTP request Session

UserPreferences userManagerbean, userManager

UserPreferences UserManagerUserPreferencesHTTP Session

UserPreferences UserPreferences

request-,session-, globalSession-scopedbeans

<beanid="userPreferences"class="com.foo.UserPreferences"scope="session">

<aop:scoped-proxy/>

</bean>

<beanid="userManager"class="com.foo.UserManager">

<propertyname="userPreferences"ref="userPreferences"/>

</bean>

3.4.4.5.1.

bean <aop:scoped-proxy/>SpringCGLIBCGLIBpublic public<aop:scoped-proxy/>' proxy-target-class'' false'JDKclasspath

bean

<!--DefaultUserPreferences

<beanid="userPreferences"class="com.foo.DefaultUserPreferences"scope="session">

<aop:scoped-proxyproxy-target-class="false"

/>

</bean>

<beanid="userManager"class="com.foo.UserManager">

<propertyname="userPreferences"ref="userPreferences"/>

</bean>

6.6“”

3.4.5.Spring 2.0SpringbeanSpringbean singleton

prototype

3.4.5.1.org.springframework.beans.factory.config.ScopeSpringSpringScope ScopeJavadoc

Scope''Sessionsession-scopedbean(Session)

Objectget(Stringname,ObjectFactoryobjectFactory)

sessionsessionsession-scopedbean(null)

Objectremove(Stringname)

JavadocSpringScope

voidregisterDestructionCallback(Stringname,RunnabledestructionCallback)

The lastmethod dealswith obtaining the conversation identifier for theunderlyingscope.Thisidentifierisdifferentforeachscope.Forasessionforexample,thiscanbethesessionidentifier.sessionsession

StringgetConversationId()

3.4.5.2.ScopeSpring ScopeSpring ConfigurableBeanFactory

voidregisterScope(StringscopeName,Scopescope);

registerScope(..) Spring'singleton''prototype'registerScope(..)ScopeScope

//note:theThreadScope

ScopecustomScope=newThreadScope();

beanFactory.registerScope("thread",scope);

<beanid="..."class="..."scope="thread"/>

CustomScopeConfigurer

CustomScopeConfigurer

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<beanclass="org.springframework.beans.factory.config.CustomScopeConfigurer">

<propertyname="scopes">

<map>

<entrykey="thread">

<beanclass="com.foo.ThreadScope"/>

</entry>

</map>

</property>

</bean>

<beanid="bar"class="x.y.Bar"scope="thread">

<propertyname="name"value="Rick"/>

<aop:scoped-proxy/>

</bean>

<beanid="foo"class="x.y.Foo">

<propertyname="bar"ref="bar"/>

</bean>

</beans>

3.5.bean

3.5.1.Springmarkerinterfacebean InitializingBeanDisposableBean

bean afterPropertiesSet() destroy()

SpringBeanPostProcessor BeanPostProcessor3.7“”

Springbeanbean

3.5.1.1.org.springframework.beans.factory.InitializingBeanbean

InitializingBean

voidafterPropertiesSet()throwsException;

InitializingBeanSpringBeanXML init-method

<beanid="exampleInitBean"class="examples.ExampleBean"init-method="init"/>

publicclassExampleBean{

publicvoidinit(){

//dosomeinitializationwork

}

}

......

<beanid="exampleInitBean"class="examples.AnotherExampleBean"/>

publicclassAnotherExampleBeanimplementsInitializingBean{

publicvoidafterPropertiesSet(){

//dosomeinitializationwork

}

}

...Spring

3.5.1.2.org.springframework.beans.factory.DisposableBeanbeanbean

DisposableBean

voiddestroy()throwsException;

DisposableBeanSpringbeanXML destroy-method

<beanid="exampleInitBean"class="examples.ExampleBean"destroy-method="cleanup"/>

publicclassExampleBean{

publicvoidcleanup(){

//dosomedestructionwork(likereleasingpooledconnections)

}

}

......

<beanid="exampleInitBean"class="examples.AnotherExampleBean"/>

publicclassAnotherExampleBeanimplementsDisposableBean{

publicvoiddestroy(){

//dosomedestructionwork(likereleasingpooledconnections)

}

}

...Spring

3.5.1.3.SpringInitializingBeanDisposableBean init()

initialize()dispose()

Spring bean init() XMLbean 'init-method="init"'

SpringIoCbean

publicclassDefaultBlogServiceimplementsBlogService{

privateBlogDaoblogDao;

publicvoidsetBlogDao(BlogDaoblogDao){

this.blogDao=blogDao;

}

//thisis(unsurprisingly)theinitializationcallbackmethod

publicvoidinit(){

if(this.blogDao==null){

thrownewIllegalStateException("The[blogDao]propertymustbeset.");

}

}

}

<beansdefault-init-method="init">

<beanid="blogService"class="com.foo.DefaultBlogService">

<propertyname="blogDao"ref="blogDao"/>

</bean>

</beans>

<beans/>'default-init-method'SpringIoCbean 'init'

(XML) <beans/> 'default-destroy-method'bean

<bean/>'init-method''destroy-method'(XML)SpringbeanbeanAOPbean AOPbeanbeanbean/bean

3.5.1.4.As of Spring 2.5, there are three options for controlling bean lifecyclebehavior: the InitializingBean and DisposableBean callback interfaces;custom init() and destroy() methods; and the @PostConstruct and

@PreDestroyannotations.Spring2.5bean InitializingBeanDisposableBean; init() destroy()

; @PostConstruct@PreDestroyannotations.

--@PostConstruct

InitializingBeanafterPropertiesSet()

init()

:@PreDestroy

DisposableBeandestroy()

destroy()

bean -

3.5.1.5.webSpringIoC

webApplicationContextwebSpringIoCwebSpringIoCsingletonbeanJVM“”shutdownhookSpringIoC“” AbstractApplicationContextregisterShutdownHook()

importorg.springframework.context.support.AbstractApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

publicfinalclassBoot{

publicstaticvoidmain(finalString[]args)throwsException{

AbstractApplicationContextctx

=newClassPathXmlApplicationContext(newString[]{"beans.xml"});

//addashutdownhookfortheabovecontext...

ctx.registerShutdownHook();

//apprunshere...

//mainmethodexits,hookiscalledpriortotheappshuttingdown...

}

}

3.5.2.3.5.2.1.BeanFactoryAwareorg.springframework.beans.factory.BeanFactoryAwareBeanFactoryBeanFactory

publicinterfaceBeanFactoryAware{

voidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException;

}

beanBeanFactoryBeanFactorycastBeanFactorybeanSpringbeanBeanFactoryAware

org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean

Spring BeanFactoryAwareIoCObjectFactoryCreatingFactoryBeanFactoryBeanbean

ObjectFactoryCreatingFactoryBeanBeanFactoryAwarebeanObjectFactorySpringSpring ObjectFactorygetObject()bean

ObjectFactoryBeanFactorybeanObjectFactoryCreatingFactoryBeanbean

packagex.y;

publicclassNewsFeed{

privateStringnews;

publicvoidsetNews(Stringnews){

this.news=news;

}

publicStringgetNews(){

returnthis.toString()+":'"+news+"'";

}

}

packagex.y;

importorg.springframework.beans.factory.ObjectFactory;

publicclassNewsFeedManager{

privateObjectFactoryfactory;

publicvoidsetFactory(ObjectFactoryfactory){

this.factory=factory;

}

publicvoidprintNews(){

//hereiswherethelookupisperformed;notethatthereisno

//needtohardcodethenameofthebeanthatisbeinglookedup...

NewsFeednews=(NewsFeed)factory.getObject();

System.out.println(news.getNews());

}

}

XML

<beans>

<beanid="newsFeedManager"class="x.y.NewsFeedManager">

<propertyname="factory">

<bean

class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">

<propertyname="targetBeanName">

<idreflocal="newsFeed"/>

</property>

</bean>

</property>

</bean>

<beanid="newsFeed"class="x.y.NewsFeed"scope="prototype">

<propertyname="news"value="...that'sfittoprint!"/>

</bean>

</beans>

NewsFeedManagerprintNews() ObjectFactory

prototype newsFeedbean

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

importx.y.NewsFeedManager;

publicclassMain{

publicstaticvoidmain(String[]args)throwsException{

ApplicationContextctx=newClassPathXmlApplicationContext("beans.xml");

NewsFeedManagermanager=(NewsFeedManager)ctx.getBean("newsFeedManager");

manager.printNews();

manager.printNews();

}

}

x.y.NewsFeed@1292d26:'...that'sfittoprint!'

x.y.NewsFeed@5329c5:'...that'sfittoprint!'

Spring2.5 BeanFactory BeanFactoryAware "" constructor

byType 3.3.5“autowire” setter BeanFactory @Autowired BeanFactory 3.11.1“ @Autowired

3.5.2.2.BeanNameAwarebeanorg.springframework.beans.factory.BeanNameAware BeanFactory

BeanFactoryBeanNameAwarebeanbeanbeanbeanInitializingBeanafterPropertiesSet

3.6.beanbeanbeanbeanbeanbean/beanBeanFactorybean ChildBeanDefinition XmlBeanFactorybeanXML 'parent'bean

<beanid="inheritedTestBean"abstract="true"

class="org.springframework.beans.TestBean">

<propertyname="name"value="parent"/>

<propertyname="age"value="1"/>

</bean>

<beanid="inheritsWithDifferentClass"

class="org.springframework.beans.DerivedTestBean"

parent="inheritedTestBean"init-method="initialize">

<propertyname="name"value="override"/>

<!--theagepropertyvalueof1willbeinheritedfromparent-->

</bean>

beanclassbeanclassbeanclassbeanbeanbeanbeanbeaninit-methoddestroy-method/ factory-methodbeanbean singleton

abstractbeanbeanclassbean abstract

<beanid="inheritedTestBeanWithoutClass"abstract="true">

<propertyname="name"value="parent"/>

<propertyname="age"value="1"/>

</bean>

<beanid="inheritsWithClass"class="org.springframework.beans.DerivedTestBean"

parent="inheritedTestBeanWithoutClass"init-method="initialize">

<propertyname="name"value="override"/>

<!--agewillinheritthevalueof1fromtheparentbeandefinition-->

</bean>

bean beanbeanbeanbeanrefbeanid getBean()

preInstantiateSingletons()abstractbean

ApplicationContextBeanFactorysingletonbeanbeanclass 'abstract''true'

3.7.SpringIoC BeanFactoryApplicationContextplugin

3.7.1. BeanPostProcessorbeanBeanPostProcessor Springbean BeanPostProcessor

BeanPostProcessor'order'BeanPostProcessor BeanPostProcessor

Ordered BeanPostProcessor Ordered BeanPostProcessor

OrderedJavaDoc

BeanPostProcessorbean SpringIoCbeanBeanPostProcessor

bean BeanFactoryPostProcessor 3.7.2

“ BeanFactoryPostProcessor”

BeanPostProcessor BeanPostProcessorbeanBeanPostProcessorbean

org.springframework.beans.factory.config.BeanPostProcessor

(post-processor)bean afterPropertiesSetbeanbeanproxySpringAOPbean

BeanFactoryApplicationContextbean ApplicationContext

BeanPostProcessorbeanbeanbean BeanFactorybean

ConfigurableBeanFactoryfactory=newXmlBeanFactory(...);

//nowregisteranyneededBeanPostProcessorinstances

MyBeanPostProcessorpostProcessor=newMyBeanPostProcessor();

factory.addBeanPostProcessor(postProcessor);

//nowstartusingthefactory

Spring ApplicationContext BeanPostProcessor

BeanPostProcessorsAOP(auto-proxying)

BeanPostProcessor , . BeanPostProcessorsbeanApplicationContext, BeanPostProcessorsbeanAOPBeanPostProcessorBeanPostProcessorsbean(aspects"")bean “Bean 'foo' isnoteligibleforgettingprocessedbyallBeanPostProcessors(auto_proxying) ”

ApplicationContext BeanPostProcessor

3.7.1.1. BeanPostProcessorHelloWorldBeanPostProcessor BeanPostProcessorbeanbean toString()

BeanPostProcessor

BeanPostProcessor

packagescripting;

importorg.springframework.beans.factory.config.BeanPostProcessor;

importorg.springframework.beans.BeansException;

publicclassInstantiationTracingBeanPostProcessorimplementsBeanPostProcessor{

//simplyreturntheinstantiatedbeanas-is

publicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{

returnbean;//wecouldpotentiallyreturnanyobjectreferencehere...

}

publicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{

System.out.println("Bean'"+beanName+"'created:"+bean.toString());

returnbean;

}

}

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:lang="http://www.springframework.org/schema/lang"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd">

<lang:groovyid="messenger"

script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">

<lang:propertyname="message"value="FionaAppleIsJustSoDreamy."/>

</lang:groovy>

<!--

whentheabovebean('messenger')isinstantiated,thiscustom

BeanPostProcessorimplementationwilloutputthefacttothesystemconsole

-->

<beanclass="scripting.InstantiationTracingBeanPostProcessor"/>

</beans>

InstantiationTracingBeanPostProcessorbeanbeanGroovybeanSpring2.0 24

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

importorg.springframework.scripting.Messenger;

publicfinalclassBoot{

publicstaticvoidmain(finalString[]args)throwsException{

ApplicationContextctx=newClassPathXmlApplicationContext("scripting/beans.xml");

Messengermessenger=(Messenger)ctx.getBean("messenger");

System.out.println(messenger);

}

}

Bean'messenger'created:org.springframework.scripting.groovy.GroovyMessenger@272961

org.springframework.scripting.groovy.GroovyMessenger@272961

3.7.1.2.RequiredAnnotationBeanPostProcessorSpringBeanPostProcessorSpringIoC 25.3.1“@ Required”

BeanPostProcessorJavaBeanbean

3.7.2. BeanFactoryPostProcessor

org.springframework.beans.factory.config.BeanFactoryPostProcessor

BeanPostProcessor BeanFactoryPostProcessorbeanSpringIoC BeanFactoryPostProcessorbean

BeanFactoryPostProcessor'order'BeanFactoryPostProcessor

BeanFactoryPostProcessorOrdered BeanFactoryPostProcessor

Ordered BeanFactoryPostProcessorOrderedJavaDoc

bean BeanPostProcessor 3.7.1“ BeanPostProcessor

bean”

BeanFactoryPostProcessor BeanFactoryPostProcessor

bean BeanFactoryPostProcessorbeanbean BeanFactory ApplicationContextSpringbeanPropertyResourceConfigurerPropertyPlaceholderConfigurer

BeanNameAutoProxyCreatorbeanproxy BeanFactoryPostProcessor

BeanFactory BeanFactoryPostProcessor

XmlBeanFactoryfactory=newXmlBeanFactory(newFileSystemResource("beans.xml"));

//bringinsomepropertyvaluesfromaPropertiesfile

PropertyPlaceholderConfigurercfg=newPropertyPlaceholderConfigurer();

cfg.setLocation(newFileSystemResource("jdbc.properties"));

//nowactuallydothereplacement

cfg.postProcessBeanFactory(factory);

Spring ApplicationContext BeanFactoryPostProcessor

ApplicationContextBeanFactoryPostProcessorbeanbeanbean

BeanPostProcessor BeanFactoryPostProcessorsSpring<beans/>'default-lazy-init'

BeanFactoryPostProcessor'lazy-init="false"'

3.7.2.1.PropertyPlaceholderConfigurer

PropertyPlaceholderConfigurerbean BeanFactoryJavaPropertiesURLXMLXML DataSourceProperties PropertyPlaceholderConfigurer

dataSource

<beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<propertyname="locations">

<value>classpath:com/foo/jdbc.properties</value>

</property>

</bean>

<beanid="dataSource"destroy-method="close"

class="org.apache.commons.dbcp.BasicDataSource">

<propertyname="driverClassName"value="${jdbc.driverClassName}

<propertyname="url"value="${jdbc.url}"/>

<propertyname="username"value="${jdbc.username}"/>

<propertyname="password"value="${jdbc.password}"/>

</bean>

JavaProperties

jdbc.driverClassName=org.hsqldb.jdbcDriver

jdbc.url=jdbc:hsqldb:hsql://production:9002

jdbc.username=sa

jdbc.password=root

Spring2.5 context()

<context:property-placeholderlocation="classpath:com/foo/jdbc.properties"/>

PropertyPlaceholderConfigurerPropertiesJava System

systemPropertiesMode PropertiesPlaceholderConfigurer

JavaDoc

PropertyPlaceholderConfigurer

<beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">

<propertyname="locations">

<value>classpath:com/foo/strategy.properties</value>

</property>

<propertyname="properties">

<value>custom.strategy.class=com.foo.DefaultStrategy</value>

</property>

</bean>

<beanid="serviceStrategy"class="${custom.strategy.class}"/>

beanbean ApplicationContext

preInstantiateSingletons()

3.7.2.2.PropertyOverrideConfigurerbeanPropertyOverrideConfigurerPropertyPlaceholderConfigurerbean

PropertiesbeanbeanXML PropertyOverrideConfigurerbeanProperties

beanName.property=value

Anexamplepropertiesfilemightlooklikethis:properties

dataSource.driverClassName=com.mysql.jdbc.Driver

dataSource.url=jdbc:mysql:mydb

bean dataSourcebeanbean driverurl

foo.fred.bob.sammy=123

... thesammypropertyof thebobpropertyof thefredpropertyof thefoobeanisbeingsettothescalarvalue123.foobeanfredbobsammy123

3.7.3. FactoryBean

beanorg.springframework.beans.factory.FactoryBeanFactoryBeanSpringIoCJava()XML FactoryBean FactoryBean

FactoryBean

ObjectgetObject()isSingleton()singletonprototype

booleanisSingleton()FactoryBeansingletontruefalse

ClassgetObjectType()getObject()nullSpringFactoryBeanSpring FactoryBean50

FactoryBeanbean FactoryBean ApplicationContextgetBeanbeanid '&'()id myBeanFactoryBeangetBean("myBean")FactoryBeanbeangetBean("&myBean")FactoryBean

3.8.TheApplicationContextbeansbean contextApplicationContextBeanFactory ApplicationContext

ContextLoaderJ2EEwebApplicationContextcontextApplicationContext BeanFactory BeanFactorycontext

MessageSource,

URL

ApplicationListenerbean

web

3.8.1.BeanFactory ApplicationContext?ApplicationContext""

ApplicationContextBeanFactory BeanFactory Applet""ApplicationContextSpring2.0 link linkend="beans-factory-

extension-bpp">BeanPostProcessor BeanFactoryAOPBeanFactoryApplicationContext ApplicationContext

BeanFactory

3.5.FeatureMatrixBeanFactory ApplicationContext

Bean/ Yes Yes

BeanPostProcessor No Yes

BeanFactoryPostProcessor No Yes

MessageSource( i18n) No Yes

ApplicationEvent No Yes

3.8.2. MessageSource

ApplicationContextMessageSourcei18nHierarchicalMessageSourceSpring

String getMessage(String code, Object[] args, String default,

Localeloc) MessageSourcelocaleargs MessageFormat

StringgetMessage(Stringcode,Object[]args,Localeloc)

NoSuchMessageException

String getMessage(MessageSourceResolvable resolvable, Locale

locale)MessageSourceResolvable MessageSourceResolvable

ApplicationContextcontext MessageSourcebeanbean messageSource

bean ApplicationContextbeanStaticMessageSource

SpringMessageSource: ResourceBundleMessageSourceStaticMessageSource

NestingMessageSource StaticMessageSource

ResourceBundleMessageSource

<beans>

<beanid="messageSource"

class="org.springframework.context.support.ResourceBundleMessageSource">

<propertyname="basenames">

<list>

<value>format</value>

<value>exceptions</value>

<value>windows</value>

</list>

</property>

</bean>

</beans>

classpathresource bundle format exceptionswindows

ResourceBundleJDK…

#in'format.properties'

message=Alligatorsrock!

#in'exceptions.properties'

argument.required=The'{0}'argumentisrequired.

ApplicationContextMessageSource MessageSource

publicstaticvoidmain(String[]args){

MessageSourceresources=newClassPathXmlApplicationContext("beans.xml");

Stringmessage=resources.getMessage("message",null,"Default",null);

System.out.println(message);

}

...

Alligatorsrock!

'beans.xml'classpath messageSourcebean basenames

basenameslistclasspath format.propertiesexceptions.properties

windows.properties

<beans>

<!--thisMessageSourceisbeingusedinawebapplication-->

<beanid="messageSource"class="org.springframework.context.support.ResourceBundleMessageSource">

<propertyname="baseName"value="WEB-INF/test-messages"/>

</bean>

<!--let'sinjecttheaboveMessageSourceintothisPOJO-->

<beanid="example"class="com.foo.Example">

<propertyname="messages"ref="messageSource"/>

</bean>

</beans>

publicclassExample{

privateMessageSourcemessages;

publicvoidsetMessages(MessageSourcemessages){

this.messages=messages;

}

publicvoidexecute(){

Stringmessage=this.messages.getMessage("argument.required",

newObject[]{"userDao"},"Required",null);

System.out.println(message);

}

}

execute()...

The'userDao'argumentisrequired.

i18nSpring MessageResourceJDKResourceBundlelocalemessageSource beanBritish (en-GB) localeformat_en_GB.propertiesexceptions_en_GB.properties

windows_en_GB.properties

Locale(British)locale

#in'exceptions_en_GB.properties'

argument.required=Ebagumlad,the'{0}'argumentisrequired,Isay,required.

publicstaticvoidmain(finalString[]args){

MessageSourceresources=newClassPathXmlApplicationContext("beans.xml");

Stringmessage=resources.getMessage("argument.required",

newObject[]{"userDao"},"Required",Locale.UK);

System.out.println(message);

}

...

Ebagumlad,the'userDao'argumentisrequired,Isay,required.

MessageSourceAwareMessageSource MessageSourceAwarebeanMessageSource

3.8.3.ApplicationContextApplicationEventApplicationListener

ApplicationListenerbean ApplicationEventApplicationContextbeanObserverSpring

3.6.

ContextRefreshedEvent

ApplicationContext

ConfigurableApplicationContextrefresh()

beanbeansingleton ApplicationContext

context ApplicationContext“”( XmlWebApplicationContextGenericApplicationContext.)

ContextStartedEvent

ApplicationContext,ConfigurableApplicationContextstart()"" beans()

ContextStoppedEvent

ConfigurableApplicationContextstop()ApplicationContext"" beans.contextstart()

ContextClosedEventConfigurableApplicationContextclose()ApplicationContext singletonbeancontext

RequestHandledEventwebbeanhttprequestrequestSpringDispatcherServletweb

ApplicationContextpublishEvent() ApplicationEvent

publishEvent()( ApplicationEventMulticaster)contextcontext, ApplicationContext:

<beanid="emailer"class="example.EmailBean">

<propertyname="blackList">

<list>

<value>black@list.org</value>

<value>white@list.org</value>

<value>john@doe.org</value>

</list>

</property>

</bean>

<beanid="blackListListener"class="example.BlackListNotifier">

<propertyname="notificationAddress"value="spam@list.org"/>

</bean>

:

publicclassEmailBeanimplementsApplicationContextAware{

privateListblackList;

privateApplicationContextctx;

publicvoidsetBlackList(ListblackList){

this.blackList=blackList;

}

publicvoidsetApplicationContext(ApplicationContextctx){

this.ctx=ctx;

}

publicvoidsendEmail(Stringaddress,Stringtext){

if(blackList.contains(address)){

BlackListEventevent=newBlackListEvent(address,text);

ctx.publishEvent(event);

return;

}

//sendemail...

}

}

publicclassBlackListNotifierimplementsApplicationListener{

privateStringnotificationAddress;

publicvoidsetNotificationAddress(StringnotificationAddress){

this.notificationAddress=notificationAddress;

}

publicvoidonApplicationEvent(ApplicationEventevent){

if(eventinstanceofBlackListEvent){

//notifyappropriateperson...

}

}

}

AOP

3.8.4.Spring Resource 4

ResourceLoader ResourceResourcejava.net.URLclasspathURLbeanResource ResourceApplicationContext PropertyEditor

Resource

ApplicationContext ClassPathXmlApplicationContext

classpathclasspathURLbean

3.8.5.ApplicationContextWEBBeanFactory ApplicationContext ContextLoaderApplicationContext

ApplicationContext ContextLoader

ContextLoader ContextLoaderListenerContextLoaderServletlistenerServlet2.3Servlet2.4servletcontextlistenersweb(servletcontextlistener)servletcontextlistenerSpring ApplicationContext

ContextLoaderListener ContextLoaderServletJavadocContextLoaderListenerApplicationContext

<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>

<!--orusetheContextLoaderServletinsteadoftheabovelistener

<servlet>

<servlet-name>context</servlet-name>

<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

-->

contextConfigLocation /WEB-INF/applicationContext.xml

ant- /WEB-INF/*Context.xml

/WEB-INF/**/*Context.xml(WEB-INF"Context.xml")ContextLoaderServletContextLoaderListener'contextConfigLocation'

3.9.singletonSpringIoCsingletonsingletonSpringIoC

Class.forName()SpringIoCstubproxysingletonSpringIoCEJBstub/proxySpringIoCJavaSpringIoCsingletonbeannon-singletonSpringIoCSpringIoCbeanHibernateSessionFactoryJ2EEJAREJBWAREARSpringIoCweb-appWARXMLSpringIoCSpringIoCweb-appsweb-appSpringIoCApplicationContextbeanbeanHibernateSessionFactory ContextSingletonBeanFactoryLocator

SingletonBeanFactoryLocatorsingletonSpringIoCwebSpringIoCbeanSingletonBeanFactoryLocatorContextSingletonBeanFactoryLocatorJavaDoc EJBSpringEJBnon-singleton BeanFactoryLocator

SingletonBeanFactoryLocatorContextSingletonBeanFactoryLocator

3.10.J2EERARSpringApplicationContextSpring2.5RARSpringApplicationContextbeanJARsJ2EERARApplicationContextJ2EEJ2EERAR“”(headless)WAR——HTTPJ2EESpringApplicationContextWARRARHTTPBeansJTAJNDIJDBCJMSConnectionFactorybeansJMX——SpringJNDIJMXSpringWorkManagerSpringContextResourceAdapterJavaDocRAR

RAR JAR jarsRAR”META-INF/ra.xml“SpringContextResourceAdapterJavaDocSpringXMLbean"META-INF/applicationContext.xml"RAR

RAR“”JMSRARApplicationContextRMI

3.11.Annotation-based3.7.1.2“ RequiredAnnotationBeanPostProcessor” BeanPostProcessor

SpringIoCSpring2.0 @RequiredSpring2.5Spring@Autowired 3.3.5 “autowire” Spring 2.5 JSR-250

@Resource@PostConstruct@PreDestroyJava5(Tiger)beanXML'

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:annotation-config/>

</beans>

post-processorsAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessor

RequiredAnnotationBeanPostProcessor

3.11.1.@Autowired@Autowired“”setter

publicclassSimpleMovieLister{

privateMovieFindermovieFinder;

@Autowired

publicvoidsetMovieFinder(MovieFindermovieFinder){

this.movieFinder=movieFinder;

}

//...

}

publicclassMovieRecommender{

privateMovieCatalogmovieCatalog;

privateCustomerPreferenceDaocustomerPreferenceDao;

@Autowired

publicvoidprepare(MovieCatalogmovieCatalog,CustomerPreferenceDaocustomerPreferenceDao){

this.movieCatalog=movieCatalog;

this.customerPreferenceDao=customerPreferenceDao;

}

//...

}

@Autowired

publicclassMovieRecommender{

@Autowired

privateMovieCatalogmovieCatalog;

privateCustomerPreferenceDaocustomerPreferenceDao;

@Autowired

publicMovieRecommender(CustomerPreferenceDaocustomerPreferenceDao){

this.customerPreferenceDao=customerPreferenceDao;

}

//...

}

ApplicationContextbeans

publicclassMovieRecommender{

@Autowired

privateMovieCatalog[]movieCatalogs;

//...

}

publicclassMovieRecommender{

privateSet<MovieCatalog>movieCatalogs;

@Autowired

publicvoidsetMovieCatalogs(Set<MovieCatalog>movieCatalogs){

this.movieCatalogs=movieCatalogs;

}

//...

}

MapsMapkey StringMapvalueskeysbean

publicclassMovieRecommender{

privateMap<String,MovieCatalog>movieCatalogs;

@Autowired

publicvoidsetMovieCatalogs(Map<String,MovieCatalog>movieCatalogs){

this.movieCatalogs=movieCatalogs;

}

//...

}

0beans required

publicclassSimpleMovieLister{

privateMovieFindermovieFinder;

@Autowired(required=false)

publicvoidsetMovieFinder(MovieFindermovieFinder){

this.movieFinder=movieFinder;

}

//...

}

requiredSpring greediest@Autowired“” BeanFactory ApplicationContext ResourceLoader

ApplicationEventPublisher MessageSource

ConfigurableApplicationContextResourcePatternResolver

publicclassMovieRecommender{

@Autowired

privateApplicationContextcontext;

publicMovieRecommender(){

}

//...

}

3.11.2.@Qualifier

publicclassMovieRecommender{

@Autowired

@Qualifier("mainCatalog")

privateMovieCatalogmovieCatalog;

//...

}

@Qualifier

publicclassMovieRecommender{

privateMovieCatalogmovieCatalog;

privateCustomerPreferenceDaocustomerPreferenceDao;

@Autowired

publicvoidprepare(@Qualifier("mainCatalog")MovieCatalogmovieCatalog,CustomerPreferenceDaocustomerPreferenceDao){

this.movieCatalog=movieCatalog;

this.customerPreferenceDao=customerPreferenceDao;

}

//...

}

@Qualifier

@Target({ElementType.FIELD,ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

@Qualifier

public@interfaceGenre{

Stringvalue();

}

publicclassMovieRecommender{

@Autowired

@Genre("Action")

privateMovieCatalogactionCatalog;

privateMovieCatalogcomedyCatalog;

@Autowired

publicvoidsetComedyCatalog(@Genre("Comedy")MovieCatalogcomedyCatalog){

this.comedyCatalog=comedyCatalog;

}

//...

}

bean <qualifier/><bean/> 'type''value'“”

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:annotation-config/>

<beanclass="example.SimpleMovieCatalog">

<qualifiertype="Genre"value="Action"/>

<!--injectanydependenciesrequiredbythisbean-->

</bean>

<beanclass="example.SimpleMovieCatalog">

<qualifiertype="example.Genre"value="Comedy"/>

<!--injectanydependenciesrequiredbythisbean-->

</bean>

<beanid="movieRecommender"class="example.MovieRecommender"/>

</beans>

3.12“Classpath” XML 3.12.6“”

Internet

@Target({ElementType.FIELD,ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

@Qualifier

public@interfaceOffline{

}

publicclassMovieRecommender{

@Autowired

@Offline

privateMovieCatalogofflineCatalog;

//...

}

bean

<beanclass="example.SimpleMovieCatalog">

<qualifiertype="Offline"/>

<!--injectanydependenciesrequiredbythisbean-->

</bean>

'value'bean

@Target({ElementType.FIELD,ElementType.PARAMETER})

@Retention(RetentionPolicy.RUNTIME)

@Qualifier

public@interfaceMovieQualifier{

Stringgenre();

Formatformat();

}

Format

publicenumFormat{

VHS,DVD,BLURAY

}

'genre' 'format'

publicclassMovieRecommender{

@Autowired

@MovieQualifier(format=Format.VHS,genre="Action")

privateMovieCatalogactionVhsCatalog;

@Autowired

@MovieQualifier(format=Format.VHS,genre="Comedy")

privateMovieCatalogcomedyVhsCatalog;

@Autowired

@MovieQualifier(format=Format.DVD,genre="Action")

privateMovieCatalogactionDvdCatalog;

@Autowired

@MovieQualifier(format=Format.BLURAY,genre="Comedy")

privateMovieCatalogcomedyBluRayCatalog;

//...

}

beanbean <qualifier/> <qualifier/>bean<meta/>

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:annotation-config/>

<beanclass="example.SimpleMovieCatalog">

<qualifiertype="MovieQualifier">

<attributename="format"value="VHS"/>

<attributename="genre"value="Action"/>

</qualifier>

<!--injectanydependenciesrequiredbythisbean-->

</bean>

<beanclass="example.SimpleMovieCatalog">

<qualifiertype="MovieQualifier">

<attributename="format"value="VHS"/>

<attributename="genre"value="Comedy"/>

</qualifier>

<!--injectanydependenciesrequiredbythisbean-->

</bean>

<beanclass="example.SimpleMovieCatalog">

<metakey="format"value="DVD"/>

<metakey="genre"value="Action"/>

<!--injectanydependenciesrequiredbythisbean-->

</bean>

<beanclass="example.SimpleMovieCatalog">

<metakey="format"value="BLURAY"/>

<metakey="genre"value="Comedy"/>

<!--injectanydependenciesrequiredbythisbean-->

</bean>

</beans>

3.11.3.CustomAutowireConfigurerCustomAutowireConfigurerBeanFactoryPostProcessor Spring@Qualifier

<beanid="customAutowireConfigurer"class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">

<propertyname="customQualifierTypes">

<set>

<value>example.CustomQualifier</value>

</set>

</property>

</bean>

AutowireCandidateResolver Java Java 5 'autowire-

candidate'<beans/>'default-autowire-candidates'Java5@QualifierCustomAutowireConfigurer

Java“”beansbean 'primary''true'

3.11.4.@ResourceSpringJSR-250beanJavaEE5Java6JSF1.2beansJAX-WS2.0SpringSpring@Resource‘name’Springbean by-name

publicclassSimpleMovieLister{

privateMovieFindermovieFinder;

@Resource(name="myMovieFinder")

publicvoidsetMovieFinder(MovieFindermovieFinder){

this.movieFinder=movieFinder;

}

}

settersetterbean"movieFinder"setter

publicclassSimpleMovieLister{

privateMovieFindermovieFinder;

@Resource

publicvoidsetMovieFinder(MovieFindermovieFinder){

this.movieFinder=movieFinder;

}

}

BeanFactory bean JNDI SpringSimpleJndiBeanFactorySpringJNDI

@Autowired @Resourcebeanbean"resolvabledependencies" BeanFactory ApplicationContext

ResourceLoader ApplicationEventPublisher MessageSource@Resource

customerPreferenceDao “customerPreferenceDao” beanCustomerPreferenceDao"context" ApplicationContext

publicclassMovieRecommender{

@Resource

privateCustomerPreferenceDaocustomerPreferenceDao;

@Resource

privateApplicationContextcontext;

publicMovieRecommender(){

}

//...

}

3.11.5.@PostConstruct @PreDestroy

CommonAnnotationBeanPostProcessor @Resource JSR-250 lifecycleSpring2.5 initializationcallbacks destructioncallbacks

CommonAnnotationBeanPostProcessorSpring ApplicationContext

Spring

publicclassCachingMovieLister{

@PostConstruct

publicvoidpopulateMovieCache(){

//populatesthemoviecacheuponinitialization...

}

@PreDestroy

publicvoidclearMovieCache(){

//clearsthemoviecacheupondestruction...

}

}

3.5.1.4“”

3.12.ClasspathXML Spring”beanXML classpath

3.12.1.@ComponentSpring2.0 @Repository (DataAccessObjectDAO)12.6.4“”

Spring2.5(stereotypeannotations) @Component@Service@Controller@ComponentSpring @Repository@Service@Controller@Component) @ComponentSpringFramework@Component@Service@Service @Repository

3.12.2.Spring“”(stereotyped) ApplicationContext BeanDefinition

@Service

publicclassSimpleMovieLister{

privateMovieFindermovieFinder;

@Autowired

publicSimpleMovieLister(MovieFindermovieFinder){

this.movieFinder=movieFinder;

}

}

@Repository

publicclassJpaMovieFinderimplementsMovieFinder{

//implementationelidedforclarity

}

beanXML'basePackage'

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:component-scanbase-package="org.example"/>

</beans>

AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor

'false' annotation-config

3.12.3.@Component@Repository@Service@Controller( @Component)

' component-scan' include-filterexclude-filter '

3.7.

annotation org.example.SomeAnnotation

assignable org.example.SomeClass

regex org\.example\.Default.*

aspectj org.example..*Service+

XML@Repository“stub”

<beans...>

<context:component-scanbase-package="org.example">

<context:include-filtertype="regex"expression=".*Stub.*Repository"/>

<context:exclude-filtertype="annotation"expression="org.springframework.stereotype.Repository"/>

</context:component-scan>

</beans>

<component-scan/>use-default-filters="false"@Repository@Service@Controller

3.12.4.BeanNameGeneratorbean nameSpring“”

(@Component@Repository@Service@Controller)bean(non-qualified) 'myMovieLister''movieFinderImpl'

@Service("myMovieLister")

publicclassSimpleMovieLister{

//...

}

@Repository

publicclassMovieFinderImplimplementsMovieFinder{

//...

}

bean BeanNameGenerator

<beans...>

<context:component-scanbase-package="org.example"

name-generator="org.example.MyNameGenerator"/>

</beans>

3.12.5.Spring“singleton”

@Scope("prototype")

@Repository

publicclassMovieFinderImplimplementsMovieFinder{

//...

}

ScopeMetadataResolver

<beans...>

<context:component-scanbase-package="org.example"

scope-resolver="org.example.MyScopeResolver"/>

</beans>

singleton 3.4.4.5“bean” 'no''interfaces''targetClass'JDK

<beans...>

<context:component-scanbase-package="org.example"

scoped-proxy="interfaces"/>

</beans>

3.12.6.3.11.2“” @Qualifier @Qualifier'qualifier'' meta'classpath (type-level)

@Component

@Qualifier("Action")

publicclassActionMovieCatalogimplementsMovieCatalog{

//...

}

@Component

@Genre("Action")

publicclassActionMovieCatalogimplementsMovieCatalog{

//...

}

@Component

@Offline

publicclassCachingMovieCatalogimplementsMovieCatalog{

//...

}

XML

3.13. LoadTimeWeaver

Spring2.5contextload-time-weaver

<beans...>

<context:load-time-weaver/>

</beans>

XMLSpringApplicationContext Spring LoadTimeWeaverApplicationContextbean LoadTimeWeaverAware(load-timeweaver)JPA JPA LocalContainerEntityManagerFactoryBean

AspectJ 6.8.4“SpringAspectJLTW”

4

4.1.4.2.Resource4.3. Resource

4.3.1.UrlResource4.3.2.ClassPathResource4.3.3.FileSystemResource4.3.4.ServletContextResource4.3.5.InputStreamResource4.3.6.ByteArrayResource

4.4.ResourceLoader4.5.ResourceLoaderAware4.6. Resource

4.7.Applicationcontext Resource4.7.1.applicationcontext4.7.2.Applicationcontext4.7.3.FileSystemResource

4.1.Java java.net.URLURL ServletContextURLURL( http:) URL

4.2.ResourceSpring Resource

publicinterfaceInputStreamSource{

booleanexists();

booleanisOpen();

URLgetURL()throwsIOException;

FilegetFile()throwsIOException;

ResourcecreateRelative(StringrelativePath)throwsIOException;

StringgetFilename();

StringgetDescription();

}

publicinterfaceInputStreamSource{

InputStreamgetInputStream()throwsIOException;

}

Resource

getInputStream(): InputStream InputStream

exists(): boolean

isOpen(): boolean trueInputStreamInputStreamResourceresource false

getDescription():URL URL File()SpringResourceSpringAPIs( ApplicationContext) Stringcontext ResourceString ResourceResourceSpringSpringSpring URL

Resource UrlResourceURL URL

4.3. ResourceSpring Resource

4.3.1.UrlResourceUrlResource java.net.URLURLHTTPFTPURL String

URL file: http:HTTP ftp:FTPUrlResourceJava UrlResource StringAPIJavaBeansPropertyEditor Resource

UrlResource

4.3.2.ClassPathResourceclasspathcontext(classloader) Resource java.io.File(servlet)jar Resourcejava.net.URLClassPathResourceJavaClassPathResource StringAPIJavaBeans PropertyEditor classpath: ClassPathResource

4.3.3.FileSystemResource java.io.FileResource File URL

4.3.4.ServletContextResource ServletContext ResourcewebURLweb java.io.FileJARDB()Servlet

4.3.5.InputStreamResource InputStream Resource ResourceByteArrayResourceResource Resource - isOpen() true

4.3.6.ByteArrayResourcebyte Resource byte ByteArrayInputStream

byte InputStreamResource

4.4.ResourceLoaderResourceLoader() Resource

publicinterfaceResourceLoader{

ResourcegetResource(Stringlocation);

}

applicationcontext ResourceLoader Resourceapplicationcontext getResource() applicationcontextResource ClassPathXmlApplicationContext

Resourcetemplate=ctx.getResource("some/resource/path/myTemplate.txt");

ClassPathResourceFileSystemXmlApplicationContextFileSystemResource WebApplicationContextServletContextResource

applicationcontextapplicationcontext classpath:ClassPathResource

Resourcetemplate=ctx.getResource("classpath:some/resource/path/myTemplate.txt");

java.net.URL UrlResource

Resourcetemplate=ctx.getResource("file:/some/resource/path/myTemplate.txt");

Resourcetemplate=ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");

String Resource

4.1.Resourcestrings

classpath: classpath:com/myapp/config.xml classpath

file: file:/data/config.xml URL [a]

http: http://myserver/logo.png URL

(none) /data/config.xml ApplicationContext

[a] 4.7.3“ FileSystemResource”

4.5.ResourceLoaderAwareResourceLoaderAware ResourceLoader

publicinterfaceResourceLoaderAware{

voidsetResourceLoader(ResourceLoaderresourceLoader);

}

ResourceLoaderAwareapplicationcontext(Springbean)applicationcontext ResourceLoaderAware application contextsetResourceLoader(ResourceLoader)(Springapplication contextResourceLoader) ApplicationContextResourceLoaderbean ApplicationContextAware

applicationcontext ResourceLoader

ApplicationContextSpring 2.5, ResourceLoader ResourceLoaderAware “”constructor byType( 3.3.5“autowire” )setter ResourceLoader 3.11.1“ @Autowired”

4.6. Resource

beanbean ResourceLoaderbean Resourceapplication context String Resource PropertyEditor

JavaBeans myBean Resourcetemplate

<beanid="myBean"class="...">

<propertyname="template"value="some/resource/path/myTemplate.txt"/>

</bean>

applicationcontext ResourceLoader ClassPathResource

FileSystemResourceServletContextResourcecontext Resource ClassPathResource UrlResource()

<propertyname="template"value="classpath:some/resource/path/myTemplate.txt">

<propertyname="template"value="file:/some/resource/path/myTemplate.txt"/>

4.7.Applicationcontext Resource

4.7.1.applicationcontextapplicationcontext(contextXML) Resource beanapplication contextClassPathXmlApplicationContext

ApplicationContextctx=newClassPathXmlApplicationContext("conf/appContext.xml");

BeanclasspathClassPathResourceFileSystemXmlApplicationContext

ApplicationContextctx=

newFileSystemXmlApplicationContext("conf/appContext.xml");

BeanclasspathURL Resource FileSystemXmlApplicationContext...

ApplicationContextctx=

newFileSystemXmlApplicationContext("classpath:conf/appContext.xml");

...classpathbean FileSystemXmlApplicationContextResourceLoader

4.7.1.1. ClassPathXmlApplicationContext-ClassPathXmlApplicationContext XML() Class

ClassPathXmlApplicationContext

com/

foo/

services.xml

daos.xml

MessengerService.class

'services.xml' 'daos.xml'bean ClassPathXmlApplicationContext

...

ApplicationContextctx=newClassPathXmlApplicationContext(

newString[]{"services.xml","daos.xml"},MessengerService.class);

ClassPathXmlApplicationContextJavadocs

4.7.2.ApplicationcontextApplicationcontext())“”contextapplicationcontext ( PathMatcher

classpath*:Resource

4.7.2.1.AntpatternAntpattern

/WEB-INF/*-context.xml

com/mycompany/**/applicationContext.xml

file:C:/some/path/*-context.xml

classpath:com/mycompany/**/applicationContext.xml

ResourceURL" wsjar") java.io.FilejarURLURL jar

4.7.2.1.1.

URL() ResourceLoaderclasspath Classloader.getResource()

Javadocs) URLclasspath

jarURL java.net.JarURLConnection

4.7.2.2.classpath*:XMLapplicationcontext classpath*:

ApplicationContextctx=

newClassPathXmlApplicationContext("classpath*:conf/appContext.xml");

classpath( ClassLoader.getResources(...)))applicationcontext

Classpath*:classpathclassloader getResources() classloaderjar classpath*:classloaderclasspathjargetClass().getClassLoader().getResources("

<someFileInsideTheJar>")"classpath*:" PathMatcher pattern" classpath*:META-INF/*-

beans.xml" ClassLoader.getResources()

4.7.2.3." classpath*:"Antpatternpattern JDK ClassLoader.getResources()

" classpath:"Antpattern

com/mycompany/package1/service-context.xml

classpath:com/mycompany/**/service-context.xml

getResource("com/mycompany");()URL classloader" classpath*:"

4.7.3.FileSystemResource FileSystemApplicationContext FileSystemResource(FileSystemApplicationContextResourceLoader) FileSystemApplicationContext ResourceLoader

FileSystemApplicationContext FileSystemResource

ApplicationContextctx=

newFileSystemXmlApplicationContext("conf/context.xml");

ApplicationContextctx=

newFileSystemXmlApplicationContext("/conf/context.xml");

()

FileSystemXmlApplicationContextctx=...;

ctx.getResource("some/resource/path/myTemplate.txt");

FileSystemXmlApplicationContextctx=...;

ctx.getResource("/some/resource/path/myTemplate.txt");

FileSystemResource FileSystemXmlApplicationContext file:

URL UrlResource

//actualcontexttypedoesn'tmatter,theResourcewillalwaysbe

ctx.getResource("file:/some/resource/path/myTemplate.txt");

//forcethisFileSystemXmlApplicationContexttoloadit'sdefinitionviaa

ApplicationContextctx=

newFileSystemXmlApplicationContext("file:/conf/context.xml");

5 BeanWrapper

5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper

5.4.1.5.4.2.PropertyEditor

5.1.Spring()WebSpring Validator

Data bindingSpring DataBinder ValidatorDataBinder

validationSpringMVCBeanWrapperSpring BeanWrapper BeanWrapper BeanWrapper

SpringPropertyEditor PropertyEditorJavaBean BeanWrapper

BeanWrapperDataBinder PropertyEditor

5.2.Spring Validator

Springvalidator ValidatorErrorsSpring Errors

publicclassPerson{

privateStringname;

privateintage;

//theusualgettersandsetters...

}

org.springframework.validation.Validator Person

supports(Class)ValidatorClass

validate(Object, org.springframework.validation.Errors)

ErrorsValidatorSpring ValidationUtils

publicclassPersonValidatorimplementsValidator{

/**

*ThisValidatorvalidatesjustPersoninstances

*/

publicbooleansupports(Classclazz){

returnPerson.class.equals(clazz);

}

publicvoidvalidate(Objectobj,Errorse){

ValidationUtils.rejectIfEmpty(e,"name","name.empty");

Personp=(Person)obj;

if(p.getAge()<0){

e.rejectValue("age","negativevalue");

}elseif(p.getAge()>110){

e.rejectValue("age","too.darn.old");

}

}

}

ValidationUtilsrejectIfEmpty(..)name 'name' nullValidationUtilsJavaDoc

Validator Validator 'rich'Customer String(firstnamesecondname) Address AddressCustomer AddressValidator

CustomerValidatorAddressValidator CustomerValidator

AddressValidator

publicclassCustomerValidatorimplementsValidator{

privatefinalValidatoraddressValidator;

publicCustomerValidator(ValidatoraddressValidator){

if(addressValidator==null){

thrownewIllegalArgumentException("Thesupplied[Validator]isrequiredandmustnotbenull.");

}

if(!addressValidator.supports(Address.class)){

thrownewIllegalArgumentException(

"Thesupplied[Validator]mustsupportthevalidationof[Address]instances.");

}

this.addressValidator=addressValidator;

}

/**

*ThisValidatorvalidatesCustomerinstances,andanysubclassesof

*/

publicbooleansupports(Classclazz){

returnCustomer.class.isAssignableFrom(clazz);

}

publicvoidvalidate(Objecttarget,Errorserrors){

ValidationUtils.rejectIfEmptyOrWhitespace(errors,"firstName","field.required");

ValidationUtils.rejectIfEmptyOrWhitespace(errors,"surname","field.required");

Customercustomer=(Customer)target;

try{

errors.pushNestedPath("address");

ValidationUtils.invokeValidator(this.addressValidator,customer.getAddress(),errors);

}finally{

errors.popNestedPath();

}

}

}

ErrorsSpringWebMVC <spring:bind/>Javadoc

5.3.nameage MessageSourcenameage ValidationUtils

ErrorsrejectValuereject MessageCodesResolver

DefaultMessageCodesResolver DefaultMessageCodesResolverrejectrejectValue("age","too.darn.old")Spring too.darn.old

too.darn.old.agetoo.darn.old.age.int

MessageCodesResolverJavaDocs MessageCodesResolver

DefaultMessageCodesResolver

5.4.BeanBeanWrapperorg.springframework.beansSunJavaBeanJavaBeanJavasettergetter bingoMadnesssetter setBingoMadness(..)

getBingoMadness()JavaBeanSun( java.sun.com/products/javabeans)BeanWrapper(BeanWrapperImpl)JavaDoc BeanWrapper

BeanWrapper BeanWrapperJavaBeanPropertyChangeListenersVetoableChangeListeners BeanWrapper BeanWrapperDataBinderBeanFactory

BeanWrapper bean

5.4.1.setPropertyValue(s)getPropertyValue(s)SpringJavaDoc

5.1.

name namegetName() isName()setName(..)

account.name accountnamegetAccount().setName()getAccount().getName()

account[2] accountarraylist

account[COMPANYNAME] MapaccountCOMPANYNAMEkey

BeanWrapper

BeanWrapper DataBinderBeanFactory PropertyEditor

publicclassCompany{

privateStringname;

privateEmployeemanagingDirector;

publicStringgetName() {

returnthis.name;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicEmployeegetManagingDirector(){

returnthis.managingDirector;

}

publicvoidsetManagingDirector(EmployeemanagingDirector){

this.managingDirector=managingDirector;

}

}

publicclassEmployee{

privateStringname;

privatefloatsalary;

publicStringgetName() {

returnthis.name;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicfloatgetSalary(){

returnsalary;

}

publicvoidsetSalary(floatsalary){

this.salary=salary;

}

}

CompaniesEmployees

BeanWrappercompany=BeanWrapperImpl(newCompany());

//settingthecompanyname..

company.setPropertyValue("name","SomeCompanyInc.");

//...canalsobedonelikethis:

PropertyValuevalue=newPropertyValue("name","SomeCompanyInc.");

company.setPropertyValue(value);

//ok,let'screatethedirectorandtieittothecompany:

BeanWrapperjim=BeanWrapperImpl(newEmployee());

jim.setPropertyValue("name","JimStravinsky");

company.setPropertyValue("managingDirector",jim.getWrappedInstance());

//retrievingthesalaryofthemanagingDirectorthroughthecompany

Floatsalary=(Float)company.getPropertyValue("managingDirector.salary");

5.4.2. PropertyEditorSpringPropertyEditorObject String Date String

' 2007-14-09'Date Date java.beans.PropertyEditor

BeanWrapperIoCSun java.beansJavaDocPropertyEditors

PropertyEditorsBeanXMLbeanjava.lang.StringSpring ClassEditor

StringClasssetter Class

SpringMVCPropertyEditorsHTTPCommandControllerSpringPropertyEditorsSpring PropertyEditor

org.springframework.beans.PropertyEditors BeanWrapperImpl

5.2. PropertyEditors

ByteArrayPropertyEditor bytebyte BeanWrapperImpl

ClassEditorClassClassBeanWrapperImpl

CustomBooleanEditor Boolean BeanWrapperImpl

CustomCollectionEditor ( Collection)( Collection)

CustomDateEditorjava.util.DateDateFormat

CustomNumberEditorInteger Long Float DoubleNumberBeanWrapperImpl

FileEditor java.io.File BeanWrapperImpl

InputStreamEditor

InputStream ResourceEditor

InputStream InputStream

BeanWrapperImpl

LocaleEditorStringLocaleString[]_[]_[]LocaltoString() BeanWrapperImpl

PatternEditor JDK1.5 Pattern

PropertiesEditorString PropertiesJavaDocjava.lang.PropertiesBeanWrapperImpl

StringTrimmerEditor (trim)String null

URLEditor StringURL URL BeanWrapperImpl

Springjava.beans.PropertyEditorManager sun.bean.editors

PropertyEditor FontColorJavaBean PropertyEditor

EditorEditor“Editor” FooEditor

PropertyEditor

com

chank

pop

Foo

FooEditor//thePropertyEditorfortheFooclass

BeanInfoJavaBean( ) BeanInfoPropertyEditor

com

chank

pop

Foo

FooBeanInfo//theBeanInfofortheFooclass

FooBeanInfo CustomNumberEditorFooage

publicclassFooBeanInfoextendsSimpleBeanInfo{

publicPropertyDescriptor[]getPropertyDescriptors(){

try{

finalPropertyEditornumberPE=newCustomNumberEditor(Integer.class,true);

PropertyDescriptorageDescriptor=newPropertyDescriptor("age",Foo.class){

publicPropertyEditorcreatePropertyEditor(Objectbean){

returnnumberPE;

};

};

returnnewPropertyDescriptor[]{ageDescriptor};

}

catch(IntrospectionExceptionex){

thrownewError(ex.toString());

}

}

}

5.4.2.1. PropertyEditor

beanSpring IoC JavaBean PropertyEditorSpringPropertyEditor(Class Class)JavaJavaBean PropertyEditor

EditorEditorPropertyEditor BeanFactory ConfigurableBeanFactory

registerCustomEditor() CustomEditorConfigurerbeanfactorybeanfactory BeanFactory

beanfactoryapplicationcontext BeanWrapper BeanWrapper

ApplicationContextapplicationcontextJavaBeanPropertyEditorString CustomEditorConfigurerbeanfactory

PropertyEditorApplicationContext

ExoticTypeDependsOnExoticType

packageexample;

publicclassExoticType{

privateStringname;

publicExoticType(Stringname){

this.name=name;

}

}

publicclassDependsOnExoticType{

privateExoticTypetype;

publicvoidsetType(ExoticTypetype){

this.type=type;

}

}

type PropertyEditorExoticType

<beanid="sample"class="example.DependsOnExoticType">

<propertyname="type"value="aNameForExoticType"/>

</bean>

PropertyEditor

//convertsstringrepresentationtoExoticTypeobject

packageexample;

publicclassExoticTypeEditorextendsPropertyEditorSupport{

privateStringformat;

publicvoidsetFormat(Stringformat){

this.format=format;

}

publicvoidsetAsText(Stringtext){

if(format!=null&&format.equals("upperCase")){

text=text.toUpperCase();

}

ExoticTypetype=newExoticType(text);

setValue(type);

}

}

CustomEditorConfigurerApplicationContextPropertyEditor

<beanclass="org.springframework.beans.factory.config.CustomEditorConfigurer">

<propertyname="customEditors">

<map>

<entrykey="example.ExoticType">

<beanclass="example.ExoticTypeEditor">

<propertyname="format"value="upperCase"/>

</bean>

</entry>

</map>

</property>

</bean>

5.4.2.1.1. PropertyEditorRegistrars

Spring PropertyEditorRegistrarPropertyEditorRegistry PropertyEditorRegistrySpringBeanWrapper

DataBinder CustomEditorConfigurerPropertyEditorRegistrars CustomEditorConfigurer

setPropertyEditorRegistrars(..) DataBinderSpringMVCControllersCustomEditorConfigurerPropertyEditorRegistrarsbeanPropertyEditorRegistrarPropertyEditor

PropertyEditorRegistrar PropertyEditorRegistrar

packagecom.foo.editors.spring;

publicfinalclassCustomPropertyEditorRegistrarimplementsPropertyEditorRegistrar{

publicvoidregisterCustomEditors(PropertyEditorRegistryregistry){

//itisexpectedthatnewPropertyEditorinstancesarecreated

registry.registerCustomEditor(ExoticType.class,newExoticTypeEditor());

//youcouldregisterasmanycustompropertyeditorsasarerequiredhere...

}

}

org.springframework.beans.support.ResourceEditorRegistrar

PropertyEditorRegistrar registerCustomEditors(..)

CustomEditorConfigurerCustomPropertyEditorRegistrar

<beanclass="org.springframework.beans.factory.config.CustomEditorConfigurer">

<propertyname="propertyEditorRegistrars">

<list>

<refbean="customPropertyEditorRegistrar"/>

</list>

</property>

</bean>

<beanid="customPropertyEditorRegistrar"class="com.foo.editors.spring.CustomPropertyEditorRegistrar"/>

SpringMVC web Controllers SimpleFormController

PropertyEditorRegistrars initBinder(..)PropertyEditorRegistrar

publicfinalclassRegisterUserControllerextendsSimpleFormController{

privatefinalPropertyEditorRegistrarcustomPropertyEditorRegistrar;

publicRegisterUserController(PropertyEditorRegistrarpropertyEditorRegistrar){

this.customPropertyEditorRegistrar=propertyEditorRegistrar;

}

protectedvoidinitBinder(HttpServletRequestrequest,ServletRequestDataBinderbinder)throwsException{

this.customPropertyEditorRegistrar.registerCustomEditors(binder);

}

//othermethodstodowithregisteringaUser

}

PropertyEditorinitBinder(..) PropertyEditor Controllers

6SpringAOP

6.1.6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP

6.2.@AspectJ6.2.1.@AspectJ6.2.2.6.2.3.pointcut6.2.4.6.2.5.Introduction6.2.6.6.2.7.

6.3.SchemaAOP6.3.1.6.3.2.6.3.3.6.3.4.6.3.5.6.3.6.Advisor6.3.7.

6.4.AOP6.4.1.SpringAOPAspectJ6.4.2.SpringAOP@AspectJXML

6.5.6.6.

6.6.1.AOP6.7.@AspectJ6.8.SpringAspectJ

6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW

6.9.

Spring2.0AOPSpring2.0 @AspectJ(advice)AspectJSpringAOPWeavingSpring2.0@AspectJAOPSpring2.0Spring1.21.2APIAOP

6.1.AOPOOPOOPclassesAOP AOP crosscutting

AOPSpringSpringIoCAOPAOPAOPSpringIoC,AOPSpringFramework

EJB

AOPOOPpoolingSpringAOP

6.1.1.AOPAOPSpringAOPSpring

Aspect J2EESpringAOP @Aspect

Joinpoint SpringAOP

Advice “around”“before”“after”AOPSpring

Pointcut AOPSpringAspectJ

Introduction inter-typedeclarationSpringbean IsModified

TargetObject advised SpringAOP

AOPAOPProxy AOPSpringAOPJDKCGLIB

Weaving AspectJSpringJavaAOP

Beforeadvice

Afterreturningadvice

Afterthrowingadvice

After(finally)advice

AroundAdviceAspectJSpring JoinPointproceed()

Spring2.0 Object

AOPAOP

6.1.2.SpringAOPSpringAOPJavaSpringAOPJ2EEwebSpringjoinpointSpringbeanSpringAOPAPISpringAspectJSpringAOPSpringAOPSpringAOPAOPSpringIoCSpringAOPSpringIoCbeanSpring"autoproxying"AOPSpringAOPAspectJJ2EEAOPSpringAOPSpringAOPAOPAspectJproxy-basedSpringAOPAspectJSpring2.0SpringAOPIoCAspectJAOPSpringSpringAOPAPIAOPAllianceAPISpringAOP SpringAOPAPI

SpringFrameworknon-invasiveness ;/SpringFrameworkSpringSpringFrameworkAspectJSpringAOP@AspectJSpringXML@AspectJSpring@AspectJSpringXML6.4“AOP”

6.1.3.AOPSpringJ2SEdynamicproxies AOPSpringCGLIB.CGLIBCGLIBSpringAOPproxy-based 6.6.1“AOP”

6.2.@AspectJ@AspectJJava5Java@AspectJAspectJ5 AspectJprojectSpring2.0AspectJ5AspectJAOPSpringAOPAspectJweaverAspectJAspectJ 6.8“SpringAspectJ”

6.2.1.@AspectJSpring@AspectJSpring@AspectJ autoproxying beanSpringbeanSpringSpring@AspectJ

<aop:aspectj-autoproxy/>

A,XMLSchema-basedconfigurationschemaaop A.2.7“The aopschema”

DTDapplicationcontext@AspectJ

<beanclass="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>

classpathAspectJ aspectjweaver.jaraspectjrt.jarAspectJ1.5.1'lib'Spring-with-dependencies 'lib/aspectj'

6.2.2.@AspectJapplicationcontext@Aspect @AspectbeanSpringSpringAOPapplicationcontextbean @Aspectbean

<beanid="myAspect"class="org.xyz.NotVeryUsefulAspect">

<!--configurepropertiesofaspecthereasnormal-->

</bean>

NotVeryUsefulAspect org.aspectj.lang.annotation.Aspect

packageorg.xyz;

importorg.aspectj.lang.annotation.Aspect;

@Aspect

AspectJSpring call,get,

set, preinitialization,

staticinitialization,

initialization, handler,

adviceexecution, withincode,

cflow,cflowbelow, if, @this

@withincodeSpring AOPIllegalArgumentException

SpringAOPAspectJ

publicclassNotVeryUsefulAspect{

}

@Aspectinter-type

SpringAOP @Aspect

6.2.3.pointcutSpringAOPSpringbeanSpringbean

@AspectJAOP'anyOldTransfer'"transfer"

@Pointcut"execution*transfer.." //thepointcutexpression

privatevoidanyOldTransfer{} //thepointcutsignature

@PointcutAspectJ5AspectJ AspectJJava5 AspectJ5

AspectJColyeret.al.“ EclipseAspectJ”RamnivasLaddad“ AspectJinAction”

6.2.3.1.PCDSpringAOPAspectJ

execution-Spring

within-SpringAOP

this-SpringAOPbeanreferenceSpringAOPtarget-SpringAOP

args-SpringAOP

@target-SpringAOP

@args-SpringAOP

@within-SpringAOP

@annotation-SpringAOP,SpringAOP' bean'PCDPCDSpringbeanSpringbean' bean'PCD:

beanidOrNameOfBean

'idOrNameOfBean'Springbean' *'Springbean' bean'PCD' bean'PCD&&,||!

' bean'PCD SpringAOPAspectJ.SpringAspectJPCD'bean'PCDAOP Springbean

SpringAOPpointcutAspectJAspectJ'this''target'SpringAOP'this''target'

6.2.3.2.'&','||' '!' tradingOperation

@Pointcut"executionpublic**.."

privatevoidanyPublicOperation{}

@Pointcut"withincom.xyz.someapp.trading..*"

privatevoidinTrading{}

@Pointcut"anyPublicOperation&&inTrading"

privatevoidtradingOperation{}

Java

6.2.3.3.“SystemArchitecture”

packagecom.xyz.someapp;

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.Pointcut;

@Aspect

publicclassSystemArchitecture{

/**

*Ajoinpointisintheweblayerifthemethodisdefined

*inatypeinthecom.xyz.someapp.webpackageoranysub-package

*underthat.

*/

@Pointcut"withincom.xyz.someapp.web..*"

publicvoidinWebLayer{}

/**

*Ajoinpointisintheservicelayerifthemethodisdefined

*inatypeinthecom.xyz.someapp.servicepackageoranysub-package

*underthat.

*/

@Pointcut"withincom.xyz.someapp.service..*"

publicvoidinServiceLayer{}

/**

*Ajoinpointisinthedataaccesslayerifthemethodisdefined

*inatypeinthecom.xyz.someapp.daopackageoranysub-package

*underthat.

*/

@Pointcut"withincom.xyz.someapp.dao..*"

publicvoidinDataAccessLayer{}

/**

*Abusinessserviceistheexecutionofanymethoddefinedonaservice

*interface.Thisdefinitionassumesthatinterfacesareplacedinthe

*"service"package,andthatimplementationtypesareinsub-packages.

*

*Ifyougroupserviceinterfacesbyfunctionalareaforexample,

*inpackagescom.xyz.someapp.abc.serviceandcom.xyz.def.service

*thepointcutexpression"execution*com.xyz.someapp..service.*.*..

*couldbeusedinstead.

*

*Alternatively,youcanwritetheexpressionusingthe'

*PCD,likeso"bean*Service ".Thisassumesthatyouhave

*namedyourSpringservicebeansinaconsistentfashion.

*/

@Pointcut"execution*com.xyz.someapp.service.*.*.."

publicvoidbusinessService{}

/**

*Adataaccessoperationistheexecutionofanymethoddefinedona

*daointerface.Thisdefinitionassumesthatinterfacesareplacedinthe

*"dao"package,andthatimplementationtypesareinsub-packages.

*/

@Pointcut"execution*com.xyz.someapp.dao.*.*.."

publicvoiddataAccessOperation{}

}

service

<aop:config>

<aop:advisor

pointcut="com.xyz.someapp.SystemArchitecture.businessService"

advice-ref="tx-advice"/>

</aop:config>

<tx:adviceid="tx-advice">

<tx:attributes>

<tx:methodname="*"propagation="REQUIRED"/>

</tx:attributes>

</tx:advice>

6.3“SchemaAOP” <aop:config><aop:advisor> 9

6.2.3.4.SpringAOP execution

executionmodifiers-pattern?ret-type-patterndeclaring-type-pattern?name-patternparam-pattern

throws-pattern?

ret-type-pattern (*) (*,String)

executionpublic**..

“set”

execution*set*..

AccountService

execution*com.xyz.service.AccountService.*..

service

execution*com.xyz.service.*.*..

service

execution*com.xyz.service..*.*..

serviceSpringAOP

withincom.xyz.service.*

serviceSpringAOP

withincom.xyz.service..*

AccountService SpringAOP

thiscom.xyz.service.AccountService

'this'-AccountService SpringAOP

targetcom.xyz.service.AccountService

'target'-SerializableSpringAOP

argsjava.io.Serializable

'args'- execution(**(java.io.Serializable))argsSerializableexecution Serializable

@Transactional SpringAOP

@targetorg.springframework.transaction.annotation.Transactional

'@target'- @Transactional SpringAOP

@withinorg.springframework.transaction.annotation.Transactional

'@within'- @Transactional SpringAOP

@annotationorg.springframework.transaction.annotation.Transactional

'@annotation'-@ClassifiedSpringAOP

@argscom.xyz.security.Classified

'@args'-' tradeService'Springbean SpringAOP

beantradeService

' *Service'Springbean SpringAOP

bean*Service

6.2.4.

6.2.4.1. @Before

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.Before;

@Aspect

publicclassBeforeExample{

@Before"com.xyz.myapp.SystemArchitecture.dataAccessOperation"

publicvoiddoAccessCheck{

//...

}

}

in-place

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.Before;

@Aspect

publicclassBeforeExample{

@Before"execution*com.xyz.myapp.dao.*.*.."

publicvoiddoAccessCheck{

//...

}

}

6.2.4.2.Afterreturningadvice @AfterReturning

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.AfterReturning;

@Aspect

publicclassAfterReturningExample{

@AfterReturning"com.xyz.myapp.SystemArchitecture.dataAccessOperation"

publicvoiddoAccessCheck{

//...

}

}

@AfterReturning

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.AfterReturning;

@Aspect

publicclassAfterReturningExample{

@AfterReturning

pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation",

returning="retVal"

publicvoiddoAccessCheckObjectretVal{

//...

}

}

returning

6.2.4.3.Afterthrowingadvice@AfterThrowing

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.AfterThrowing;

@Aspect

publicclassAfterThrowingExample{

@AfterThrowing"com.xyz.myapp.SystemArchitecture.dataAccessOperation"

publicvoiddoRecoveryActions{

//...

}

}

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.AfterThrowing;

@Aspect

publicclassAfterThrowingExample{

@AfterThrowing

pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation",

throwing="ex"

publicvoiddoRecoveryActionsDataAccessExceptionex{

//...

}

}

throwing

6.2.4.4.After(finally)advice@After

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.After;

@Aspect

publicclassAfterFinallyExample{

@After"com.xyz.myapp.SystemArchitecture.dataAccessOperation"

publicvoiddoReleaseLock{

//...

}

}

6.2.4.5. @Around ProceedingJoinPoint

proceed Object[]-Object[]AspectJ AspectJ

based AspectJSpring@AspectJ

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.Around;

importorg.aspectj.lang.ProceedingJoinPoint;

@Aspect

publicclassAroundExample{

@Around"com.xyz.myapp.SystemArchitecture.businessService"

publicObjectdoBasicProfilingProceedingJoinPointpjpthrowsThrowable{

//startstopwatch

ObjectretVal=pjp.proceed;

//stopstopwatch

returnretVal;

}

}

proceed()

6.2.4.6.AdviceparametersSpring2.0- Object[]

6.2.4.6.1.

org.aspectj.lang.JoinPoint ProceedingJoinPoint

JoinPoint getArgs() getThis()

getSignature() toString()JavaDoc

6.2.4.6.2.

@Before"com.xyz.myapp.SystemArchitecture.dataAccessOperation&&"+

"argsaccount,.."

publicvoidvalidateAccountAccountaccount{

//...

}

args(account,..)“” Account

@Pointcut"com.xyz.myapp.SystemArchitecture.dataAccessOperation&&"+

"argsaccount,.."

privatevoidaccountDataAccessOperationAccountaccount{}

@Before"accountDataAccessOperationaccount"

publicvoidvalidateAccountAccountaccount{

//...

}

AspectJthis target @within,@target,@annotation,@argsAudit@Auditable

@RetentionRetentionPolicy.RUNTIME

@TargetElementType.METHOD

public@interfaceAuditable{

AuditCodevalue;

}

@Auditable

@Before"com.xyz.lib.Pointcuts.anyPublicMethod&&"+

"@annotationauditable"

publicvoidauditAuditableauditable{

AuditCodecode=auditable.value;

//...

}

6.2.4.6.3.

"argNames"-

@Before

value="com.xyz.lib.Pointcuts.anyPublicMethod&&targetbean&&@annotationauditable",

argNames="bean,auditable"

publicvoidauditObjectbean,Auditableauditable{

AuditCodecode=auditable.value;

//...usecodeandbean

}

JoinPoint ProceedingJoinPoint JoinPoint.StaticPart“argNames”

@Before

value="com.xyz.lib.Pointcuts.anyPublicMethod&&targetbean&&@annotationauditable",

argNames="bean,auditable"

publicvoidauditJoinPointjp,Objectbean,Auditableauditable{

AuditCodecode=auditable.value;

//...usecode,bean,andjp

}

JoinPointProceedingJoinPoint JoinPoint.StaticPart“argNames” “argNames”

@Before

"com.xyz.lib.Pointcuts.anyPublicMethod"

publicvoidauditJoinPointjp{

//...usejp

}

'argNames' 'argNames'SpringAOPdebugdebugg:vars' 1@AspectJAspectJajcdebug

debugSpringAOPAmbiguousBindingException

IllegalArgumentException

6.2.4.6.4.

proceed() SpringAOPAspectJ

@Around"executionList<Account>find*..&&"+

"com.xyz.myapp.SystemArchitecture.inDataAccessLayer&&"+

"argsaccountHolderNamePattern"

publicObjectpreProcessQueryPatternProceedingJoinPointpjp,StringaccountHolderNamePattern

throwsThrowable{

StringnewPattern=preProcessaccountHolderNamePattern;

returnpjp.proceednewObject[]{newPattern};

}

6.2.4.7.SpringAOPAspectJ

Ordered.getValue()

javac

6.2.5.IntroductionAspectJinter-type@DeclareParentsservice UsageTracked JMX

@Aspect

publicclassUsageTracking{

@DeclareParentsvalue="com.xzy.myapp.service.*+",

defaultImpl=DefaultUsageTracked.class

publicstaticUsageTrackedmixin;

@Before"com.xyz.myapp.SystemArchitecture.businessService&&"+

"thisusageTracked"

publicvoidrecordUsageUsageTrackedusageTracked{

usageTracked.incrementUseCount;

}

}

@DeclareParents valueAspectJ-beanservicebeans UsageTrackedbean

UsageTrackedusageTracked=UsageTrackedcontext.getBean"myService";

6.2.6.AOPapplicationcontextAspectJpertarget percflowpercflowbelow pertypewithin"perthis" @Aspectperthis

@Aspect"perthiscom.xyz.myapp.SystemArchitecture.businessService"

publicclassMyAspect{

privateintsomeState;

@Beforecom.xyz.myapp.SystemArchitecture.businessService

publicvoidrecordServiceUsage{

//...

}

}

'perthis'service 'this'

service AspectJper-clauses'pertarget'“perthis”

6.2.7.

businessservicesPessimisticLockingFailureExceptionproceed()

@Aspect

publicclassConcurrentOperationExecutorimplementsOrdered{

privatestaticfinalintDEFAULT_MAX_RETRIES=2;

privateintmaxRetries=DEFAULT_MAX_RETRIES;

privateintorder=1;

publicvoidsetMaxRetriesintmaxRetries{

this.maxRetries=maxRetries;

}

publicintgetOrder{

returnthis.order;

}

publicvoidsetOrderintorder{

this.order=order;

}

@Around"com.xyz.myapp.SystemArchitecture.businessService"

publicObjectdoConcurrentOperationProceedingJoinPointpjpthrowsThrowable{

intnumAttempts=0;

PessimisticLockingFailureExceptionlockFailureException;

do{

numAttempts++;

try{

returnpjp.proceed;

}

catchPessimisticLockingFailureExceptionex{

lockFailureException=ex;

}

}

whilenumAttempts<=this.maxRetries;

throwlockFailureException;

}

}

OrdereddoConcurrentOperation businessService()

PessimisticLockingFailureExceptionSpring

<aop:aspectj-autoproxy/>

<beanid="concurrentOperationExecutor"

class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">

<propertyname="maxRetries"value="3"/>

<propertyname="order"value="100"/>

</bean>

idempotent Idempotent

@RetentionRetentionPolicy.RUNTIME

public@interfaceIdempotent{

//markerannotation

}

serviceidempotent

@Around"com.xyz.myapp.SystemArchitecture.businessService&&"+

"@annotationcom.xyz.myapp.service.Idempotent"

publicObjectdoConcurrentOperationProceedingJoinPointpjpthrowsThrowable{

...

}

6.3.SchemaAOP

Java5XMLSpring2.0"aop"

aop A,XMLSchema-basedconfigurationspring-aopschema A.2.7“Theschema”aop

Spring <aop:config> applicationcontext <aop:config>

<aop:config>pointcutadvisoraspect

<aop:config>Spring auto-proxyingauto-proxying

6.3.1.

schemaJavaapplicationcontextbean

<aop:aspect>backingbeanbean ref

<aop:config>

<aop:aspectid="myAspect"ref="aBean">

...

</aop:aspect>

</aop:config>

<beanid="aBean"class="...">

...

</bean>

bean" aBean"Springbean

6.3.2.

<aop:config>

serviceservice

<aop:config>

<aop:pointcutid="businessService"

expression="execution*com.xyz.myapp.service.*.*.."/>

</aop:config>

6.2“@AspectJ” AspectJ Java5schema@AspectsJDK1.4Java5AspectJAPIJDK1.5

<aop:config>

<aop:pointcutid="businessService"

expression="com.xyz.myapp.SystemArchitecture.businessService"/>

</aop:config>

6.2.3.3“” SystemArchitecture

<aop:config>

<aop:aspectid="myAspect"ref="aBean">

<aop:pointcutid="businessService"

expression="execution*com.xyz.myapp.service.*.*.."/>

...

</aop:aspect>

</aop:config>

@AspectJschema(collect)

<aop:config>

<aop:aspectid="myAspect"ref="aBean">

<aop:pointcutid="businessService"

expression="execution*com.xyz.myapp.service.*.*..&amp;&amp;thisservice"/>

<aop:beforepointcut-ref="businessService"method="monitor"/>

...

</aop:aspect>

</aop:config>

publicvoidmonitorObjectservice{

...

}

'&&'XML'and','or''not''&&','||''!'

<aop:config>

<aop:aspectid="myAspect"ref="aBean">

<aop:pointcutid="businessService"

expression="execution*com.xyz.myapp.service.*.*..

<aop:beforepointcut-ref="businessService"method="monitor"/>

...

</aop:aspect>

</aop:config>

XMLidschema

6.3.3.

@AspectJschema5

6.3.3.1.

<aop:aspect><aop:before>

<aop:aspectid="beforeExample"ref="aBean">

<aop:before

pointcut-ref="dataAccessOperation"

method="doAccessCheck"/>

...

</aop:aspect>

dataAccessOperation<aop:config>id pointcut-refpointcut

<aop:aspectid="beforeExample"ref="aBean">

<aop:before

pointcut="execution*com.xyz.myapp.dao.*.*.."

method="doAccessCheck"/>

...

</aop:aspect>

@AspectJMethoddoAccessCheck bean

6.3.3.2.

<aop:aspect>

<aop:aspectid="afterReturningExample"ref="aBean">

<aop:after-returning

pointcut-ref="dataAccessOperation"

method="doAccessCheck"/>

...

</aop:aspect>

@AspectJreturning

<aop:aspectid="afterReturningExample"ref="aBean">

<aop:after-returning

pointcut-ref="dataAccessOperation"

returning="retVal"

method="doAccessCheck"/>

...

</aop:aspect>

doAccessCheck retVal @AfterReturning

publicvoiddoAccessCheckObjectretVal{...

6.3.3.3.<aop:aspect> after-throwing

<aop:aspectid="afterThrowingExample"ref="aBean">

<aop:after-throwing

pointcut-ref="dataAccessOperation"

method="doRecoveryActions"/>

...

</aop:aspect>

@AspectJthrowing

<aop:aspectid="afterThrowingExample"ref="aBean">

<aop:after-throwing

pointcut-ref="dataAccessOperation"

throwing="dataAccessEx"

method="doRecoveryActions"/>

...

</aop:aspect>

doRecoveryActionsdataAccessEx @AfterThrowing

publicvoiddoRecoveryActionsDataAccessExceptiondataAccessEx{...

6.3.3.4.after

<aop:aspectid="afterFinallyExample"ref="aBean">

<aop:after

pointcut-ref="dataAccessOperation"

method="doReleaseLock"/>

...

</aop:aspect>

6.3.3.5.“” Aroundaop:around ProceedingJoinPoint

proceed() proceedObject[]-

<aop:aspectid="aroundExample"ref="aBean">

<aop:around

pointcut-ref="businessService"

method="doBasicProfiling"/>

...

</aop:aspect>

doBasicProfiling@AspectJ

publicObjectdoBasicProfilingProceedingJoinPointpjpthrowsThrowable{

//startstopwatch

ObjectretVal=pjp.proceed;

//stopstopwatch

returnretVal;

}

6.3.3.6.Schema-based@AspectJ

arg-names 6.2.4.6.3“” "argNames"

<aop:before

pointcut="com.xyz.lib.Pointcuts.anyPublicMethodand@annotationauditable"

method="audit"

arg-names="auditable"/>

arg-names

XSD

packagex.y.service;

publicinterfaceFooService{

FoogetFooStringfooName,intage;

}

publicclassDefaultFooServiceimplementsFooService{

publicFoogetFooStringname,intage{

returnnewFooname,age;

}

}

profile.. profile..

packagex.y;

importorg.aspectj.lang.ProceedingJoinPoint;

importorg.springframework.util.StopWatch;

publicclassSimpleProfiler{

publicObjectprofileProceedingJoinPointcall,Stringname,intagethrowsThrowable{

StopWatchclock=newStopWatch

"Profilingfor'"+name+"'and'"+age+"'";

try{

clock.startcall.toShortString;

returncall.proceed;

}finally{

clock.stop;

System.out.printlnclock.prettyPrint;

}

}

}

XML

<beansxmlns="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/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<!--thisistheobjectthatwillbeproxiedbySpring'sAOPinfrastructure-->

<beanid="fooService"class="x.y.service.DefaultFooService"/>

<!--thisistheactualadviceitself-->

<beanid="profiler"class="x.y.SimpleProfiler"/>

<aop:config>

<aop:aspectref="profiler">

<aop:pointcutid="theExecutionOfSomeFooServiceMethod"

expression="execution*x.y.service.FooService.getFooString,int

andargsname,age"/>

<aop:aroundpointcut-ref="theExecutionOfSomeFooServiceMethod"

method="profile"/>

</aop:aspect>

</aop:config>

</beans>

importorg.springframework.beans.factory.BeanFactory;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

importx.y.service.FooService;

publicfinalclassBoot{

publicstaticvoidmainfinalString[]argsthrowsException{

BeanFactoryctx=newClassPathXmlApplicationContext"x/y/plain.xml";

FooServicefoo=FooServicectx.getBean"fooService";

foo.getFoo"Pengo",12;

}

}

StopWatch'Profilingfor'Pengo'and'12'':runningtimemillis=0

-----------------------------------------

ms%Taskname

-----------------------------------------

00000?executiongetFoo

6.3.3.7. 6.2.4.7“” bean

6.3.4.AspectJinter-typeaop:aspectaop:declare-parents DefaultUsageTrackedservice UsageTracked

<aop:aspectid="usageTrackerAspect"ref="usageTracking">

<aop:declare-parents

types-matching="com.xzy.myapp.service.*+"

implement-interface="com.xyz.myapp.service.tracking.UsageTracked"

default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>

<aop:before

pointcut="com.xyz.myapp.SystemArchitecture.businessService

andthisusageTracked"

method="recordUsage"/>

</aop:aspect>

usageTrackingbean

publicvoidrecordUsageUsageTrackedusageTracked{

usageTracked.incrementUseCount;

}

implement-interface types-matchingAspectJbean serevicebean UsageTracked bean

UsageTrackedusageTracked=UsageTrackedcontext.getBean"myService";

6.3.5.Schemasinglton

6.3.6.Advisor"advisor"Spring1.2AOPAspectJ advisorbean“Spring” AdvisorAspectJ

Spring2.0<aop:advisor>advisor transactionaladviceSpring2.0

<aop:config>

<aop:pointcutid="businessService"

expression="execution*com.xyz.myapp.service.*.*.."/>

<aop:advisor

pointcut-ref="businessService"

advice-ref="tx-advice"/>

</aop:config>

<tx:adviceid="tx-advice">

<tx:attributes>

<tx:methodname="*"propagation="REQUIRED"/>

</tx:attributes>

</tx:advice>

pointcut-ref pointcutadvisor orderadvisor Ordered

6.3.7.6.2.7“” schemabusinessservicesIdempotentproceed() schemaJava

publicclassConcurrentOperationExecutorimplementsOrdered{

privatestaticfinalintDEFAULT_MAX_RETRIES=2;

privateintmaxRetries=DEFAULT_MAX_RETRIES;

privateintorder=1;

publicvoidsetMaxRetriesintmaxRetries{

this.maxRetries=maxRetries;

}

publicintgetOrder{

returnthis.order;

}

publicvoidsetOrderintorder{

this.order=order;

}

publicObjectdoConcurrentOperationProceedingJoinPointpjpthrowsThrowable{

intnumAttempts=0;

PessimisticLockingFailureExceptionlockFailureException;

do{

numAttempts++;

try{

returnpjp.proceed;

}

catchPessimisticLockingFailureExceptionex{

lockFailureException=ex;

}

}

whilenumAttempts<=this.maxRetries;

throwlockFailureException;

}

}

Ordered doConcurrentOperation OptimisticLockingFailureException

@AspectJ

Spring

<aop:config>

<aop:aspectid="concurrentOperationRetry"ref="concurrentOperationExecutor">

<aop:pointcutid="idempotentOperation"

expression="execution*com.xyz.myapp.service.*.*.."/>

<aop:around

pointcut-ref="idempotentOperation"

method="doConcurrentOperation"/>

</aop:aspect>

</aop:config>

<beanid="concurrentOperationExecutor"

class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">

<propertyname="maxRetries"value="3"/>

<propertyname="order"value="100"/>

</bean>

bussinessservicesidempotent

@RetentionRetentionPolicy.RUNTIME

public@interfaceIdempotent{

//markerannotation

}

serviceidempotent

<aop:pointcutid="idempotentOperation"

expression="execution*com.xyz.myapp.service.*.*..and

@annotationcom.xyz.myapp.service.Idempotent"/>

6.4.AOPSpringAOPAspectJ

6.4.1.SpringAOPAspectJSpringAOPAspectJ AspectJdomainSpringAspectJ getsetAspectJAspectJ“”@AspectJAspectJDevelopmentTools(AJDT)AspectJ:-@AspectJ IDEJava

6.4.2.SpringAOP@AspectJXMLSpringAOP@AspectJXMLXMLSpringJava Java5+XMLXML DRY@AspectJ"singleton" XML@AspectJ

@Pointcut(execution(*get*()))

publicvoidpropertyAccess(){}

@Pointcut(execution(org.xyz.Account+*(..))

publicvoidoperationReturningAnAccount(){}

@Pointcut(propertyAccess()&&operationReturningAnAccount())

publicvoidaccountPropertyAccess(){}

XML

<aop:pointcutid="propertyAccess"

expression="execution(*get*())"/>

<aop:pointcutid="operationReturningAnAccount"

expression="execution(org.xyz.Account+*(..))"/>

accountPropertyAccess

@AspectJ @AspectJ“”

6.5.@AspectJ schema-definedadvisorSpring1.2

6.6.SpringAOPJDKCGLIBJDKJDKCGLIB

advise Final

CGLIB2classpathJDK

CGLIBCGLIB <aop:config>proxy-target-classtrue:

<aop:configproxy-target-class="true">

<!--otherbeansdefinedhere...-->

</aop:config>

@AspectJCGLIB <aop:aspectj-autoproxy>proxy-target-classtrue:

<aop:aspectj-autoproxyproxy-target-class="true"/>

<aop:config/> <aop:config/>

<tx:annotation-driven/><aop:aspectj-autoproxy/><tx:annotation-driven/> <aop:aspectj-autoproxy/>

<aop:config/>' proxy-target-class="true"'CGLIB

6.6.1.AOPSpringAOP SpringSpringAOPPOJO

publicclassSimplePojoimplementsPojo{

publicvoidfoo(){

//thisnextmethodinvocationisadirectcallonthe'this'reference

this.bar();

}

publicvoidbar(){

//somelogic...

}

}

publicclassMain{

publicstaticvoidmain(String[]args){

Pojopojo=newSimplePojo();

//thisisadirectmethodcallonthe'pojo'reference

pojo.foo();

}

}

publicclassMain{

publicstaticvoidmain(String[]args){

ProxyFactoryfactory=newProxyFactory(newSimplePojo());

factory.addInterface(Pojo.class);

factory.addAdvice(newRetryAdvice());

Pojopojo=(Pojo)factory.getProxy();

//thisisamethodcallontheproxy!

pojo.foo();

}

}

Mainmain(..)

publicclassSimplePojoimplementsPojo{

publicvoidfoo(){

//thisworks,but...gah!

((Pojo)AopContext.currentProxy()).bar();

}

publicvoidbar(){

//somelogic...

}

}

SpringAOP AOP AOP

publicclassMain{

publicstaticvoidmain(String[]args){

ProxyFactoryfactory=newProxyFactory(newSimplePojo());

factory.adddInterface(Pojo.class);

factory.addAdvice(newRetryAdvice());

factory.setExposeProxy(true);

Pojopojo=(Pojo)factory.getProxy();

//thisisamethodcallontheproxy!

pojo.foo();

}

}

AspectJAOP

6.7.@AspectJ<aop:config><aop:aspectj-autoproxy> SpringAOPAPIorg.springframework.aop.aspectj.annotation.AspectJProxyFactory

@AspectJJavadoc

//createafactorythatcangenerateaproxyforthegiventargetobject

AspectJProxyFactoryfactory=newAspectJProxyFactory(targetObject);

//addanaspect,theclassmustbean@AspectJaspect

//youcancallthisasmanytimesasyouneedwithdifferentaspects

factory.addAspect(SecurityManager.class);

//youcanalsoaddexistingaspectinstances,thetypeoftheobjectsuppliedmustbean@AspectJaspect

factory.addAspect(usageTracker);

//nowgettheproxyobject...

MyInterfaceTypeproxy=factory.getProxy();

6.8.SpringAspectJSpringAOPAspectJcompiler/weaverSpringAspectJaspectlibrary spring-aspects.jar

“SpringAspectJdomainobject” 6.8.2“SpringAspectJ” AspectJ” AspectJcompilerAspectJ 6.8.4“SpringAspectJLTW”Springload-timeweaving

6.8.1.SpringAspectJdomainobjectSpringapplicationcontextbeanbeanfactoryaspects.jarannotation-driven @ConfigurableSpring-driven

packagecom.xyz.myapp.domain;

importorg.springframework.beans.factory.annotation.Configurable;

@Configurable

publicclassAccount{

//...

}

Spring Account

id

<beanclass="com.xyz.myapp.domain.Account"scope="prototype">

<propertyname="fundsTransferService"ref="fundsTransferService"/>

</bean>

bean

packagecom.xyz.myapp.domain;

importorg.springframework.beans.factory.annotation.Configurable;

@Configurable("account")

publicclassAccount{

//...

}

Spring"account"bean Account

@Configurable autowire

@Configurable(autowire=Autowire.BY_TYPE)

@Configurable(autowire=Autowire.BY_NAME Spring2.5@Resource@Configurablebeans 3.11“Annotation-based”

dependencyCheckSpring@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)

trueSpringprimitivescollectionsspring-aspects.jar AnnotationBeanConfigurerAspect

@Configurable Spring” readResolve()

“ inessence”“ ”...@Configurable

@Configurable(preConstruction=true)

AspectJProgrammingGuideAspectJAspectJweaver-ant/maven 6.8.4“SpringAspectJLTW” AnnotationBeanConfigurerAspect

SpringbeanfactorybeanfactorySpringcontext

<context:spring-configured/>

DTDSchema

<bean

class="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"

factory-method="aspectOf"/>

@Configurablelogwarningbean"depends-on"beanconfiguration

<beanid="myService"

class="com.xzy.myapp.service.MyService"

depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect">

<!--...-->

</bean>

6.8.1.1.@Configurable@Configurabledomainobject

stub @ConfigurableAspectJ

6.8.1.2.Workingwithmultipleapplicationcontexts

6.8.1.2.WorkingwithmultipleapplicationcontextsAnnotationBeanConfigurerAspectAspectJsingleton @Configurable

singleton classloader<aop:spring-configured/>beanclasspath spring-aspects.jar

Springwebapplicationcontextbusinessservicecontextcontext classloader AnnotationBeanConfigurerAspect

contextapplicationcontext <aop:spring-configured/>

service domainobjectapplicationcontextobjectbeanweb-appweb-applicationclassloaderaspects.jarWEB-INF/lib spring-aspects.jarclasspathclassloader webapplicationaspect

6.8.2.SpringAspectJ@Configurable spring-aspects.jarAspectJ

SpringSpring@Transactional AnnotationTransactionAspectAspectJJava

@Transactional public@Transactional publicprotecteddefault

AspectJSpringAbstractBeanConfigurerAspectAbstractTransactionAspectJavadocbean domianobject

publicaspectDomainObjectConfigurationextendsAbstractBeanConfigurerAspect{

publicDomainObjectConfiguration(){

setBeanWiringInfoResolver(newClassNameBeanWiringInfoResolver());

}

//thecreationofanewbean(anyobjectinthedomainmodel)

protectedpointcutbeanCreation(ObjectbeanInstance):

initialization(new(..))&&

SystemArchitecture.inDomainModel()&&

this(beanInstance);

}

6.8.3.SpringIoCAspectJSpringapplicationAspectJSpringAspectJAspectJinstantiationmodel(per-clause)AspectJ singleton beanbeanSpringAspectJ

<beanid="profiler"class="com.xyz.profiler.Profiler"

factory-method="aspectOf">

<propertyname="profilingStrategy"ref="jamonProfilingStrategy"/>

</bean>

non-singletonbean spring-aspects.jar

runtime@AspectJAspectJload-timedomainobjectSpringSpringAOP @AspectJ beanSpringAOP

<aop:aspectj-autoproxy>

<aop:includename="thisBean"/>

<aop:includename="thatBean"/>

</aop:aspectj-autoproxy>

<aop:aspectj-autoproxy/> SpringAOP@AspectJAspectJ

6.8.4.SpringAspectJLTWLoad-timeweavingLTWAspectJLTWLTW LTWAspectJLTWSpringDevelopmentEnvironmentGuide

SpringAspectJLTWJava5+JVMSpringLTW

LTW -javaagent:path/to/aspectjweaver.jar()-javaagent:path/to/spring-agent.jar LTWSpringAspectJLTW

6.8.4.1. @AspectJ

packagefoo;

importorg.aspectj.lang.ProceedingJoinPoint;

importorg.aspectj.lang.annotation.Aspect;

importorg.aspectj.lang.annotation.Around;

importorg.aspectj.lang.annotation.Pointcut;

importorg.springframework.util.StopWatch;

importorg.springframework.core.annotation.Order;

@Aspect

publicclassProfilingAspect{

@Around("methodsToBeProfiled()")

publicObjectprofile(ProceedingJoinPointpjp)throwsThrowable{

StopWatchsw=newStopWatch(getClass().getSimpleName());

try{

sw.start(pjp.getSignature().getName());

returnpjp.proceed();

}finally{

sw.stop();

System.out.println(sw.prettyPrint());

}

}

@Pointcut("execution(public*foo..*.*(..))")

publicvoidmethodsToBeProfiled(){}

}

“ META-INF/aop.xml”AspectJweaver ProfilingAspectJavaclasspath“ META-INF/aop.xml”AspectJ

<!DOCTYPEaspectjPUBLIC

"-//AspectJ//DTD//EN""http://www.eclipse.org/aspectj/dtd/aspectj.dtd">

<aspectj>

<weaver>

<!--onlyweaveclassesinourapplication-specificpackages-->

<includewithin="foo.*"/>

</weaver>

<aspects>

<!--weaveinjustthisaspect-->

<aspectname="foo.ProfilingAspect"/>

</aspects>

</aspectj>

Spring LoadTimeWeaver“ META-INF/aop.xml

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">

<!--aserviceobject;wewillbeprofilingit'smethods-->

<beanid="entitlementCalculationService"

class="foo.StubEntitlementCalculationService"/>

<!--thisswitchesontheload-timeweaving-->

<context:load-time-weaver/>

</beans>

- META-INF/aop.xmlSpring- main(..)LTW

packagefoo;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

publicfinalclassMain{

publicstaticvoidmain(String[]args){

ApplicationContextctx=newClassPathXmlApplicationContext("beans.xml",Main.class);

EntitlementCalculationServiceentitlementCalculationService

=(EntitlementCalculationService)ctx.getBean("entitlementCalculationService");

//theprofilingaspectis'woven'aroundthismethodexecution

entitlementCalculationService.calculateEntitlement();

}

}

Spring per-ClassLoaderLTW

java-javaagent:C:/projects/foo/lib/global/spring-agent.jarfoo.Main

-javaagentJava5+ JVM SpringInstrumentationSavingAgentjavaagent spring-agent.jar

Main calculateEntitlement()Thread.sleep(..)AOP

Calculatingentitlement

StopWatch'ProfilingAspect':runningtime(millis)=1234

---------------------------------------

ms%Taskname

---------------------------------------

01234100%calculateEntitlement

LTWAspectJSpringbeans

packagefoo;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

publicfinalclassMain{

publicstaticvoidmain(String[]args){

newClassPathXmlApplicationContext("beans.xml",Main.class);

EntitlementCalculationServiceentitlementCalculationService=

newStubEntitlementCalculationService();

//theprofilingaspectwillbe'woven'aroundthismethodexecution

entitlementCalculationService.calculateEntitlement();

}

}

SpringSpring StubEntitlementCalculationService

SpringLTW

ProfilingAspect

6.8.4.2.LTWAspectJAspectJ@AspectJ

classpath

6.8.4.3.'META-INF/aop.xml'AspectJLTWJavaclasspathAspectJ

6.8.4.4.JARSSpringAspectJLTW

spring.jar2.5

aspectjrt.jar1.5

aspectjweaver.jar1.5Springinstrumentation

spring-agent.jar

6.8.4.5.SpringSpring LTW LoadTimeWeaver

org.springframework.instrument.classloading SpringLoadTimeWeaver java.lang.instrument.ClassFileTransformers

ClassLoaderLTW

java.lang.instrument

XML ApplicationContext LoadTimeWeaverSpring- BeanFactory LTW BeanFactoryPostProcessors

SpringLTW LoadTimeWeaver <context:load-time-weaver/>

<context:load-time-weaver/>

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:load-time-weaver/>

</beans>

<context:load-time-weaver/>bean LTWbeansAspectJWeavingEnabler <context:load-time-weaver/>contextXMLSchemaSpring2.5

LoadTimeWeaverbean LoadTimeWeaver

LoadTimeWeaver LoadTimeWeaver“”

6.1. DefaultContextLoadTimeWeaver

LoadTimeWeaversDefaultContextLoadTimeWeaver

LoadTimeWeavers

LoadTimeWeaver

BEA'sWeblogic10 WebLogicLoadTimeWeaver

Oracle'sOC4J OC4JLoadTimeWeaver

GlassFish GlassFishLoadTimeWeaver

SpringInstrumentationSavingAgent

JVM(java-javaagent:path/to/spring-agent.jar)

InstrumentationLoadTimeWeaver

( TomcatInstrumentableClassLoaderResin)ReflectiveLoadTimeWeaver

DefaultContextLoadTimeWeaver LoadTimeWeaverstime-weaver/> weaver-class LoadTimeWeaver

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:load-time-weaver

weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"

</beans>

<context:load-time-weaver/> LoadTimeWeaverSpringLoadTimeWeaverSpringLTW ClassFileTransformers

ClassFileTransformer ClassPreProcessorAgentAdapter

org.aspectj.weaver.loadtimeLTW ClassPreProcessorAgentAdapter

javadoc<context:load-time-weaver/> aspectj-weavingLTW

autodetect

6.2.aspectj-weaving

on AspectJ

off LTW...

autodetect SpringLTW META-INF/aop.xmlAspectJ

6.8.4.6.webSpringLTW

6.8.4.6.1.Java

JavaSpringSpringLTW agent.jar

6.8.4.6.2.Tomcat

ApacheTomcat5.0webSpring TomcatInstrumentableClassLoader

TomcatTomcatWAR server.xml

spring-tomcat-weaver.jarTomcat commonlib

<Contextpath="/myWebApp"docBase="/my/webApp/location">

<LoaderloaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"

useSystemClassLoaderAsParent="false"/>

</Context>

LTWTomcat5.5.20 ClassLoader

TomcatSpring webTomcatTomcat 12.6.1.3.1“Tomcat5.0”Tomcat

6.8.4.6.3.WebLogic,OC4J,Resin,GlassFish

BEAWebLogic10OracleJavaEEOC4J10.1.3.1 SrpingLTWAspectJjavaagent:path/to/spring-agent.jar

GlassFishEAR GlassFishwebtomcat

6.9.AspectJ AspectJwebsite

EclipseAspectJAdrianColyer(Addison-Wesley,2005) AspectJAspectJinActionRamnivasLaddad(Manning,2003)AOPAOP

7SpringAOPAPIs

7.1.7.2.SpringAPI

7.2.1.7.2.2.7.2.3.AspectJ7.2.4.7.2.5.7.2.6.

7.3.SpringAPI7.3.1.7.3.2.Spring

7.4.SpringAdvisorAPI7.5.ProxyFactoryBeanAOP

7.5.1.7.5.2.JavaBean7.5.3.JDKCGLIB7.5.4.7.5.5.7.5.6.“”

7.6.7.7.ProxyFactoryAOP7.8.7.9.“autoproxy”

7.9.1.bean7.9.2.

7.10.TargetSource7.10.1.7.10.2.7.10.3.7.10.4.ThreadLocal

7.11.Advice7.12.

7.1.Spring2.0@AspectJSchemaAOPSpringAOPAPISpring2.0AOP Spring1.2Spring2.0Spring1.2Spring2.0

7.2.SpringAPISpring

7.2.1.Springadvicepointcutorg.springframework.aop.Pointcut

publicinterfacePointcut{

ClassFiltergetClassFilter();

MethodMatchergetMethodMatcher();

}

Pointcut “”ClassFilter matches()true

publicinterfaceClassFilter{

booleanmatches(Classclazz);

}

MethodMatcher

publicinterfaceMethodMatcher{

booleanmatches(Methodm,ClasstargetClass);

booleanisRuntime();

booleanmatches(Methodm,ClasstargetClass,Object[]args);

}

matches(Method,Class) AOPisRuntime()true matches(Method,Class,Object[])MethodMatcher isRuntime()false matches(Method,Class,

Object[])

AOPAOP

7.2.2.Spring

org.springframework.aop.support.PointcutsAspectJ

7.2.3.AspectJ2.0Springorg.springframework.aop.aspectj.AspectJExpressionPointcutAspectJAspectJAspectJ

7.2.4.Spring

7.2.4.1.Spring

7.2.4.1.1.

SpringAOPorg.springframework.aop.support.Perl5RegexpMethodPointcut

Perl5RegexpMethodPointcutJakartaORO SpringJdkRegexpMethodPointcutJDK1.4Perl5RegexpMethodPointcut true

<beanid="settersAndAbsquatulatePointcut"

class="org.springframework.aop.support.Perl5RegexpMethodPointcut">

<propertyname="patterns">

<list>

<value>.*set.*</value>

<value>.*absquatulate</value>

</list>

</property>

</bean>

Spring RegexpMethodPointcutAdvisorbeforeadvicethrowsadvice J2SE1.4Spring JdkRegexpMethodPointcut

Perl5RegexpMethodPointcut perl5truePerl5RegexpMethodPointcutRegexpMethodPointcutAdvisorbeanadvisor

<beanid="settersAndAbsquatulateAdvisor"

class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">

<propertyname="advice">

<reflocal="beanNameOfAopAllianceInterceptor"/>

</property>

<propertyname="patterns">

<list>

<value>.*set.*</value>

<value>.*absquatulate</value>

</list>

</property>

</bean>

RegexpMethodPointcutAdvisor

7.2.4.1.2.

(metadata-driven)

7.2.4.2.

7.2.4.2.1.

SpringAspectJcflow SomeCallerorg.springframework.aop.support.ControlFlowPointcut

Java1.4

7.2.5.SpringStaticMethodMatcherPointcut

classTestStaticPointcutextendsStaticMethodMatcherPointcut{

publicbooleanmatches(Methodm,ClasstargetClass){

//returntrueifcustomcriteriamatch

}

}

Spring1.0RC2

7.2.6.SpringAOPJavaAspectJ

Spring“”JAC“”

7.3.SpringAPISPringAOP

7.3.1.SpringbeanadvisormixinAOP

7.3.2.SpringSpring

7.3.2.1.SpringinterceptionaroundadviceSpringAOPMethodInterceptor

publicinterfaceMethodInterceptorextendsInterceptor{

Objectinvoke(MethodInvocationinvocation)throwsThrowable;

}

invoke()MethodInvocation AOPMethodInterceptor

publicclassDebugInterceptorimplementsMethodInterceptor{

publicObjectinvoke(MethodInvocationinvocation)throwsThrowable{

System.out.println("Before:invocation=["+invocation+"]");

Objectrval=invocation.proceed();

System.out.println("Invocationreturned");

returnrval;

}

}

MethodInvocationproceed() proceed()MethodInterceptorproceed

MethodInterceptorAOPMethodInterceptorAOP AOP

7.3.2.2.beforeadvice MethodInvocation

proceed()MethodBeforeAdvice SpringAPISpring

publicinterfaceMethodBeforeAdviceextendsBeforeAdvice{

voidbefore(Methodm,Object[]args,Objecttarget)throwsThrowable;

}

void Spring

publicclassCountingBeforeAdviceimplementsMethodBeforeAdvice{

privateintcount;

publicvoidbefore(Methodm,Object[]args,Objecttarget)throwsThrowable{

++count;

}

publicintgetCount(){

returncount;

}

}

7.3.2.3.throwsadvice Springtypedthrowsadvice

org.springframework.aop.ThrowsAdvice :

afterThrowing([Method,args,target],subclassOfThrowable)

RemoteException

publicclassRemoteThrowsAdviceimplementsThrowsAdvice{

publicvoidafterThrowing(RemoteExceptionex)throwsThrowable{

//Dosomethingwithremoteexception

}

}

ServletException 4

publicclassServletThrowsAdviceWithArgumentsimplementsThrowsAdvice{

publicvoidafterThrowing(Methodm,Object[]args,Objecttarget,ServletExceptionex){

//Dosomethingwithallarguments

}

}

RemoteExceptionServletException

publicstaticclassCombinedThrowsAdviceimplementsThrowsAdvice{

publicvoidafterThrowing(RemoteExceptionex)throwsThrowable{

//Dosomethingwithremoteexception

}

publicvoidafterThrowing(Methodm,Object[]args,Objecttarget,ServletExceptionex){

//Dosomethingwithallarguments

}

}

7.3.2.4.

SpringAfter Returning adviceorg.springframework.aop.AfterReturningAdvice

publicinterfaceAfterReturningAdviceextendsAdvice{

voidafterReturning(ObjectreturnValue,Methodm,Object[]args,Objecttarget)

throwsThrowable;

}

publicclassCountingAfterReturningAdviceimplementsAfterReturningAdvice{

privateintcount;

publicvoidafterReturning(ObjectreturnValue,Methodm,Object[]args,Objecttarget)

throwsThrowable{

++count;

}

publicintgetCount(){

returncount;

}

}

7.3.2.5.SpringintroductionadviceIntroductionAdvisor, IntroductionInterceptor,

publicinterfaceIntroductionInterceptorextendsMethodInterceptor{

booleanimplementsInterface(Classintf);

}

AOPMethodInterceptorinvoke() -- IntroductionAdvisor

publicinterfaceIntroductionAdvisorextendsAdvisor,IntroductionInfo{

ClassFiltergetClassFilter();

voidvalidateInterfaces()throwsIllegalArgumentException;

}

publicinterfaceIntroductionInfo{

Class[]getInterfaces();

}

MethodMatcher Pointcut

getInterfaces()

validateInterfaces()IntroductionInterceptor

Spring

publicinterfaceLockable{

voidlock();

voidunlock();

booleanlocked();

}

mixinLockablelockunlockLockedException AOP

IntroductionInterceptor

org.springframework.aop.support.DelegatingIntroductionInterceptor

IntroductionInterceptor DelegatingIntroductionInterceptor

DelegatingIntroductionInterceptor ()DelegatingIntroductionInterceptor LockMixin

DelegatingIntroductionInterceptor IntroductionInterceptorLockMixin suppressInterface(Classintf)

IntroductionInterceptor IntroductionAdvisorLockMixinDelegatingIntroductionInterceptorLockable Lockable

locked

publicclassLockMixinextendsDelegatingIntroductionInterceptor

implementsLockable{

privatebooleanlocked;

publicvoidlock(){

this.locked=true;

}

publicvoidunlock(){

this.locked=false;

}

publicbooleanlocked(){

returnthis.locked;

}

publicObjectinvoke(MethodInvocationinvocation)throwsThrowable{

if(locked()&&invocation.getMethod().getName().indexOf("set")==0)

thrownewLockedException();

returnsuper.invoke(invocation);

}

}

invoke() DelegatingIntroductionInterceptor

lockedsetterLockMixin - Lockable

publicclassLockMixinAdvisorextendsDefaultIntroductionAdvisor{

publicLockMixinAdvisor(){

super(newLockMixin(),Lockable.class);

}

}

IntroductionAdvisorIntroductionInterceptor

LockMixinAdvisorLockMixinAdvised.addAdvisor()XML“”

7.4.SpringAdvisorAPISpringAdvisoradvisororg.springframework.aop.support.DefaultPointcutAdvisor

MethodInterceptorBeforeAdvice ThrowsAdvice

SpringAOP Spring

7.5.ProxyFactoryBeanAOPSpringIoCApplicationContextBeanFactory----SpringAOPFactoryBean bean

Spring2.0AOPbeanSpringAOPorg.springframework.aop.framework.ProxyFactoryBean

7.5.1.FactoryBean ProxyFactoryBean fooProxyFactoryBean foo

ProxyFactoryBean ProxyFactoryBeangetObject() AOPProxyFactoryBeanIoCAOPIoC

7.5.2.JavaBeanSpring FactoryBean ProxyFactoryBeanJavaBean

CGLIB 7.5.3“JDKCGLIB”

org.springframework.aop.framework.ProxyConfigSpringAOP

proxyTargetClasstrue trueCGLIB 7.5.3“JDKCGLIB”

optimizeCGLIB AOPCGLIB

frozenfrozen

exposeProxyThreadLocal exposeProxy

AopContext.currentProxy()

aopProxyFactoryAopProxyFactoryCGLIB1.1

ProxyFactoryBean

proxyInterfaces CGLIB

interceptorNamesAdvisorbeanbeanbean

*

getObject() FactoryBean

7.5.3.JDKCGLIBProxyFactryBean

ProxyFactoryBeanJDKCGLIB1.2.x2.0TransactionProxyFactoryBean

CGLIBCGLIB ProxyFactoryBeanproxyTargetClassfalsebean

ProxyFactoryBean

ProxyFactoryBeanproxyTargetClasstrueCGLIBProxyFactoryBeanproxyInterfaces proxyTargetClass

ProxyFactoryBeanproxyInterfacesJDKproxyInterfaces

ProxyFactoryBeanproxyInterfaces ProxyFactoryBean

proxyInterfaces

7.5.4.ProxyFactoryBean

beanbean“personTarget”

AOPbeanpersonTargetbean

<beanid="personTarget"class="com.mycompany.PersonImpl">

<propertyname="name"><value>Tony</value></property>

<propertyname="age"><value>51</value></property>

</bean>

<beanid="myAdvisor"class="com.mycompany.MyAdvisor">

<propertyname="someProperty"><value>Customstringpropertyvalue</value></property>

</bean>

<beanid="debugInterceptor"class="org.springframework.aop.interceptor.DebugInterceptor">

</bean>

<beanid="person"

class="org.springframework.aop.framework.ProxyFactoryBean">

<propertyname="proxyInterfaces"><value>com.mycompany.Person</value></property>

<propertyname="target"><reflocal="personTarget"/></property>

<propertyname="interceptorNames">

<list>

<value>myAdvisor</value>

<value>debugInterceptor</value>

</list>

</property>

</bean>

interceptorNamesbean ,

beanProxyFactoryBeansingletonfalse“person”beanPerson

Personperson=(Person)factory.getBean("person");

IoCbeanbeanJava

<beanid="personUser"class="com.mycompany.PersonUser">

<propertyname="person"><reflocal="person"/></property>

</bean>

PersonUserPersonAOP“”person

bean ProxyFactoryBean

<beanid="myAdvisor"class="com.mycompany.MyAdvisor">

<propertyname="someProperty"><value>Customstringpropertyvalue</value></property>

</bean>

<beanid="debugInterceptor"class="org.springframework.aop.interceptor.DebugInterceptor"/>

<beanid="person"class="org.springframework.aop.framework.ProxyFactoryBean">

<propertyname="proxyInterfaces"><value>com.mycompany.Person</value></property>

<!--Useinnerbean,notlocalreferencetotarget-->

<propertyname="target">

<beanclass="com.mycompany.PersonImpl">

<propertyname="name"><value>Tony</value></property>

<propertyname="age"><value>51</value></property>

</bean>

</property>

<propertyname="interceptorNames">

<list>

<value>myAdvisor</value>

<value>debugInterceptor</value>

</list>

</property>

</bean>

PersonSpringIoC ProxyFactoryBean

7.5.5.

Person Person SpringCGLIBProxyFactoryBeanproxyTargetClasstrue CGLIBCGLIB SpringCGLIB

Final

CGLIB2JDKCGLIBSpring1.0

7.5.6.“”bean“”

<beanid="proxy"class="org.springframework.aop.framework.ProxyFactoryBean">

<propertyname="target"ref="service"/>

<propertyname="interceptorNames">

<list>

<value>globa*</value>

</list>

</property>

</bean>

<beanid="global_debug"class="org.springframework.aop.interceptor.DebugInterceptor"/>

<beanid="global_performance"class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>

7.6.beanbeanbeanbeanbean

<beanid="txProxyTemplate"abstract="true"

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<propertyname="transactionManager"ref="transactionManager"/>

<propertyname="transactionAttributes">

<props>

<propkey="*">PROPAGATION_REQUIRED</prop>

</props>

</property>

</bean>

beanbeanbeanbean

<beanid="myService"parent="txProxyTemplate">

<propertyname="target">

<beanclass="org.springframework.samples.MyServiceImpl">

</bean>

</property>

</bean>

<beanid="mySpecialService"parent="txProxyTemplate">

<propertyname="target">

<beanclass="org.springframework.samples.MySpecialServiceImpl">

</bean>

</property>

<propertyname="transactionAttributes">

<props>

<propkey="get*">PROPAGATION_REQUIRED,readOnly</prop>

<propkey="find*">PROPAGATION_REQUIRED,readOnly</prop>

<propkey="load*">PROPAGATION_REQUIRED,readOnly</prop>

<propkey="store*">PROPAGATION_REQUIRED</prop>

</props>

</property>

</bean>

abstractbeanabstract beanabstracttrue

7.7.ProxyFactoryAOPSpringAOPSpringAOPSpringIoC

ProxyFactoryfactory=newProxyFactory(myBusinessInterfaceImpl);

factory.addInterceptor(myMethodInterceptor);

factory.addAdvisor(myAdvisor);

MyBusinessInterfacetb=(MyBusinessInterface)factory.getProxy();

org.springframework.aop.framework.ProxyFactoryProxyFactoryIntroductionInterceptionAroundAdvisorProxyFactory AdvisedSupport AdvisedSupportProxyFactoryProxyFactoryBean

AOPIoCJavaAOP

7.8.AOP org.springframework.aop.framework.Advised AOP

Advisor[]getAdvisors();

voidaddAdvice(Adviceadvice)throwsAopConfigException;

voidaddAdvice(intpos,Adviceadvice)

throwsAopConfigException;

voidaddAdvisor(Advisoradvisor)throwsAopConfigException;

voidaddAdvisor(intpos,Advisoradvisor)throwsAopConfigException;

intindexOf(Advisoradvisor);

booleanremoveAdvisor(Advisoradvisor)throwsAopConfigException;

voidremoveAdvisor(intindex)throwsAopConfigException;

booleanreplaceAdvisor(Advisora,Advisorb)throwsAopConfigException;

booleanisFrozen();

getAdvisors()DefaultPointcutAdvisorMethodInterceptor

addAdvisor() DefaultPointcutAdvisor

AOP Advised

Advisedadvised=(Advised)myObject;

Advisor[]advisors=advised.getAdvisors();

intoldAdvisorCount=advisors.length;

System.out.println(oldAdvisorCount+"advisors");

//Addanadvicelikeaninterceptorwithoutapointcut

//Willmatchallproxiedmethods

//Canuseforinterceptors,before,afterreturningorthrowsadvice

advised.addAdvice(newDebugInterceptor());

//Addselectiveadviceusingapointcut

advised.addAdvisor(newDefaultPointcutAdvisor(mySpecialPointcut,myAdvice));

assertEquals("Addedtwoadvisors",

oldAdvisorCount+2,advised.getAdvisors().length);

frozen AdvisedisFrozen()trueSpring1.1

7.9.“autoproxy”ProxyFactoryBeanbeanAOPSpring“”beanbean Spring“beanpostprocessor”bean

XMLbeanbean

bean

7.9.1.beanorg.springframework.aop.framework.autoproxy

7.9.1.1.BeanNameAutoProxyCreatorBeanNameAutoProxyCreatorbeanAOP

<beanclass="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">

<propertyname="beanNames"><value>jdk*,onlyJdk</value></property>

<propertyname="interceptorNames">

<list>

<value>myInterceptor</value>

</list>

</property>

</bean>

ProxyFactoryBean interceptorNamesprototype“”BeanNameAutoProxyCreator

Bean“jdkMyBean”“onlyJdk”beanAOPBeanNameAutoProxyCreator beanbean

7.9.1.2.DefaultAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreatorbeanbeanBeanNameAutoProxyCreator

SpecifyingaDefaultAdvisorAutoProxyCreatorbeandefinition.

DefaultAdvisorAutoProxyCreatorbean

beanDefaultAdvisorAutoProxyCreator“businessObject1”“businessObject2” bean ApplicationContextgetBean("businessObject1")AOP“bean”

<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<beanclass="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">

<propertyname="transactionInterceptor"ref="transactionInterceptor"/>

</bean>

<beanid="customAdvisor"class="com.mycompany.MyAdvisor"/>

<beanid="businessObject1"class="com.mycompany.BusinessObject1">

<!--Propertiesomitted-->

</bean>

<beanid="businessObject2"class="com.mycompany.BusinessObject2"/>

DefaultAdvisorAutoProxyCreator ----DefaultAdvisorAutoProxyCreatorAdvisorAutoProxyCreatororg.springframework.core.OrderedTransactionAttributeSourceAdvisor

7.9.1.3.AbstractAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreator DefaultAdvisorAutoProxyCreator

7.9.2..NET ServicedComponents EJBXML

DefaultAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreatorAOP

JPetStore/attributes TransactionProxyFactoryBeanINF/declarativeServices.xmlbeanJPetStore

<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<beanclass="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">

<propertyname="transactionInterceptor"ref="transactionInterceptor"/>

</bean>

<beanid="transactionInterceptor"

class="org.springframework.transaction.interceptor.TransactionInterceptor">

<propertyname="transactionManager"ref="transactionManager"/>

<propertyname="transactionAttributeSource">

<beanclass="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource">

<propertyname="attributes"ref="attributes"/>

</bean>

</property>

</bean>

<beanid="attributes"class="org.springframework.metadata.commons.CommonsAttributes"/>

DefaultAdvisorAutoProxyCreatorbeanTransactionAttributeSourceAdvisor“transactionAdvisor”bean

TransactionAttributeSourceAdvisorTransactionInterceptorAttributesTransactionAttributeSource

org.springframework.metadata.Attributes “attributes”beanJakartaCommonsAttributesAPICommonsAttributesJPetStore /annotationJDK1.5+ Spring

<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<beanclass="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">

<propertyname="transactionInterceptor"ref="transactionInterceptor"/>

</bean>

<beanid="transactionInterceptor"

class="org.springframework.transaction.interceptor.TransactionInterceptor">

<propertyname="transactionManager"ref="transactionManager"/>

<propertyname="transactionAttributeSource">

<beanclass="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"/>

</property>

</bean>

TransactionInterceptorPlatformTransactionManager JTAHibernateJDOJDBC

<beanid="transactionManager"

class="org.springframework.transaction.jta.JtaTransactionManager"/>

XMLSpringAOP

mixinsbeanDefaultPointcutAdvisorJavaBean

<beanid="lockMixin"class="org.springframework.aop.LockMixin"

scope="prototype"/>

<beanid="lockableAdvisor"class="org.springframework.aop.support.DefaultPointcutAdvisor"

scope="prototype">

<propertyname="pointcut"ref="myAttributeAwarePointcut"/>

<propertyname="advice"ref="lockMixin"/>

</bean>

<beanid="anyBean"class="anyclass"...

anyBeanbeanmixin lockMixinlockableAdvisor

myAttributeAwarePointcut

7.10.TargetSourceSpringTargetSource org.springframework.aop.TargetSource “targetobject”AOP TargetSource

SpringAOPTargetSourcepoolinghotswappableTargetSourceTargetSourceSpringtargetsource

beanSpring

7.10.1.org.springframework.aop.target.HotSwappableTargetSourceAOP HotSwappableTargetSource

HotSwappableTargetSource swap()

HotSwappableTargetSourceswapper=

(HotSwappableTargetSource)beanFactory.getBean("swapper");

ObjectoldTarget=swapper.swap(newTarget);

XML

<beanid="initialTarget"class="mycompany.OldTarget"/>

<beanid="swapper"class="org.springframework.aop.target.HotSwappableTargetSource">

<constructor-argref="initialTarget"/>

</bean>

<beanid="swappable"class="org.springframework.aop.framework.ProxyFactoryBean">

<propertyname="targetSource"ref="swapper"/>

</bean>

swap()swappablebeanbean-- TargetSource-- TargetSource

7.10.2.sessionEJBSpringSLSBSpringPOJOSpringSpringJakartaCommonsPool1.3commons-poolJarorg.springframework.aop.target.AbstractPoolingTargetSourceAPI

<beanid="businessObjectTarget"class="com.mycompany.MyBusinessObject"

scope="prototype">

...propertiesomitted

</bean>

<beanid="poolTargetSource"class="org.springframework.aop.target.CommonsPoolTargetSource">

<propertyname="targetBeanName"value="businessObjectTarget"/>

<propertyname="maxSize"value="25"/>

</bean>

<beanid="businessObject"class="org.springframework.aop.framework.ProxyFactoryBean">

<propertyname="targetSource"ref="poolTargetSource"/>

<propertyname="interceptorNames"value="myInterceptor"/>

</bean>

--“businessObjectTarget”-- PoolingTargetSourceAbstractPoolingTargetSourceJavadocmaxSize“myInterceptor”IoCSpringorg.springframework.aop.target.PoolingConfig introduction

<beanid="poolConfigAdvisor"class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">

<propertyname="targetObject"ref="poolTargetSource"/>

<propertyname="targetMethod"value="getPoolingConfigMixin"/>

</bean>

AbstractPoolingTargetSourceMethodInvokingFactoryBean“poolConfigAdvisor”ProxyFactoryBean

PoolingConfigconf=(PoolingConfig)beanFactory.getBean("businessObject");

System.out.println("Maxpoolsizeis"+conf.getMaxSize());

TargetSource

7.10.3.“”TargetSource

poolTargetSourcebean

<beanid="prototypeTargetSource"class="org.springframework.aop.target.PrototypeTargetSource">

<propertyname="targetBeanName"ref="businessObjectTarget"/>

</bean>

beanTargetSourcebeanbean

7.10.4.ThreadLocalThreadLocal ThreadLocalJDK

ThreadLocalTargetSource

<beanid="threadlocalTargetSource"class="org.springframework.aop.target.ThreadLocalTargetSource">

<propertyname="targetBeanName"value="businessObjectTarget"/>

</bean>

ThreadLocalthreadlocal setunset SpringThreadLocal

7.11. Advice

SpringAOPorg.springframework.aop.framework.adapterSPIorg.aopalliance.aop.Advice

org.springframework.aop.framework.adapterJavadoc

7.12.SpringSpringAOP

JPetStoreTransactionProxyFactoryBean

JPetStore/attributes

8

8.1.8.2.

8.2.1.Mock8.2.2.

8.3.8.3.1.8.3.2.8.3.3.8.3.4.JDBC8.3.5.8.3.6.JUnit3.88.3.7.SpringTestContextFramework8.3.8.PetClinic

8.4.

8.1.SpringIoC Spring

8.2.J2EE Spring new,POJOJUnitTestNG Mock()Spring

stub()mock()DAORepository()ORMIoC“” Springmock

8.2.1.Mock8.2.1.1.JNDIorg.springframework.mock.jndi JNDI SPIJNDIJNDI <font></font>JDBCDataSourceJ2EE

8.2.1.2.ServletAPIorg.springframework.mock.webServletAPImockSpringWebMVCwebmockmock

8.2.1.3.PortletAPIorg.springframework.mock.web.portletPortletAPImockSpringPortletMVC

8.2.2.8.2.2.1.org.springframework.test.utilReflectionTestUtilspublicsetter

ORMJPAHibernate publicSetterprivateprotected

Spring@Autowired@Resourceprivateprotectedsetter

8.2.2.2.SpringMVCorg.springframework.test.webAbstractModelAndViewTestsJUnit3.8SpringMVCModelAndViewJava1.4JUnit4+,TestNGModelAndViewAssert ModelAndView

: AbstractModelAndViewTests ModelAndViewAssert

MockHttpServletRequest,MockHttpSession org.springframework.mock.web

SpringMVC Controller.

8.3.

8.3.1.

SpringIoC

JDBCORMSQLHibernatequeryJPASpring spring-test.jar org.springframework.testSpringCactusApacheJavahttp://jakarta.apache.org/cactus/index.html2.5Spring JUnit3.8.2.5,Spring SpringTestContext4.4,TestNG SpringTestContextJava5+.

8.3.2.SpringSpringTestContext ApplicationContext

JPA shadowclassJPA(classinstrumentation)JUnit3.8instrumentationTestContext

8.3.3.Spring

SpringIoC

fixture()

()

Spring

8.3.3.1.SpringApplicationContext ——SpringHibernate10-20 fixtureXML——classpath—— web.xml

, ApplicationContext fixture——Springfixture

JUnit3.8

TestContext

8.3.3.2.fixturesSpring beanfixture

HibernateTitleDao Title

Spring: HibernateTitleDaobean

Hibernate:lazy-loading

HibernateTitleDao

fixturesJUnit3.8

TestContext

8.3.3.3. ——Spring bean——,——Spring:

JUnit3.8

TestContext

8.3.3.4.Springabstract

ApplicationContext:bean

JdbcTemplateSimpleJdbcTemplate: ORMORM'flush' Hibernate Sessionflush()

JUnit3.8

TestContext

8.3.4.JDBCorg.springframework.test.jdbcSimpleJdbcTestUtils Java5JDBC

AbstractTransactionalJUnit38SpringContextTests,AbstractTransactionalJUnit4SpringContextTests,AbstractTransactionalTestNGSpringContextTests SimpleJdbcTestUtils

8.3.5.Springorg.springframework.test.annotation SpringJava5

@IfProfileValue

ProfileValueSource

@IfProfileValue(name="java.vendor",value="SunMicrosystemsInc.")

publicvoidtestProcessWhichRunsOnlyOnSunJvm(){

//somelogicthatshouldrunonlyonJavaVMsfromSunMicrosystems

}

@IfProfileValue ( OR)JUnitTestNG

@IfProfileValue(name="test-groups",values={"unit-tests","integration-tests"})

publicvoidtestProcessWhichRunsForUnitOrIntegrationTestGroups(){

//somelogicthatshouldrunonlyforunitandintegrationtestgroups

}

@ProfileValueSourceConfiguration

@IfProfileValueprofileProfileValueSource@ProfileValueSourceConfiguration SystemProfileValueSource

@ProfileValueSourceConfiguration(CustomProfileValueSource.class)

publicclassCustomProfileValueSourceTests{

//classbody...

}

@DirtiesContext

Spring“”

@DirtiesContext

publicvoidtestProcessWhichDirtiesAppCtx(){

//somelogicthatresultsintheSpringcontainerbeingdirtied

}

@ExpectedException

@ExpectedException(SomeBusinessException.class)

publicvoidtestProcessRainyDayScenario(){

//somelogicthatshouldresultinanExceptionbeingthrown

}

@Timed

@Repeatfixture setupteardown

@Timed(millis=1000)

publicvoidtestProcessWithOneSecondTimeout(){

//somelogicthatshouldnottakelongerthan1secondtoexecute

}

@Repeat

fixture setupteardown

@Repeat(10)

publicvoidtestProcessRepeatedly(){

//...

}

@Rollback

true @Rollback

@Rollback(false)

publicvoidtestProcessWithoutRollback(){

//...

}

@NotTransactional

@NotTransactional

publicvoidtestProcessWithoutTransaction(){

//...

}

JUnit3.8 AbstractAnnotationAwareTransactionalTests

TestContext TestContext (@ContextConfiguration@BeforeTransaction) JUnit(SpringJUnit4ClassRunnerJUnit3.8JUnit4.4) TestContext

8.3.6.JUnit3.8SpringJUnit3.8org.springframework.test JUnit TestCase

ApplicationContext

8.3.6.1.AbstractSingleSpringContextTestsJUnit3.8

protectedString[]getConfigLocations()

XML————

protectedString[]getConfigPaths()

protectedStringgetConfigPath()

fixtureAbstractSingleSpringContextTests setDirty()fixtureAbstractAnnotationAwareTransactionalTests @DirtiesContext

8.3.6.2.fixture

AbstractDependencyInjectionSpringContextTests() AbstractDependencyInjectionSpringContextTests

getConfigLocations()

HibernateTitleDao( ) JUnit3.8()

publicfinalclassHibernateTitleDaoTestsextendsAbstractDependencyInjectionSpringContextTests

//thisinstancewillbe(automatically)dependencyinjected

privateHibernateTitleDaotitleDao;

//asettermethodtoenableDIofthe'titleDao'instancevariable

publicvoidsetTitleDao(HibernateTitleDaotitleDao){

this.titleDao=titleDao;

}

publicvoidtestLoadTitle()throwsException{

Titletitle=this.titleDao.loadTitle(newLong(10));

assertNotNull(title);

}

//specifiestheSpringconfigurationtoloadforthistestfixture

protectedString[]getConfigLocations(){

returnnewString[]{"classpath:com/foo/daos.xml"};

}

}

getConfigLocations()( "classpath:com/foo/daos.xml")

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<!--thisbeanwillbeinjectedintotheHibernateTitleDaoTests

<beanid="titleDao"class="com.foo.dao.hibernate.HibernateTitleDao

<propertyname="sessionFactory"ref="sessionFactory"/>

</bean>

<beanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<!--dependencieselidedforclarity-->

</bean>

</beans>

AbstractDependencyInjectionSpringContextTestsbeanbeanapplicationContext applicationContext.getBean("titleDao")

publicsetter AbstractSpringContextTests

org.springframework.testJUnit3.8-Springfixture

8.3.6.2.1.FieldLevel

fixturesetterSpring protected SpringXMLfixture

publicfinalclassHibernateTitleDaoTestsextendsAbstractDependencyInjectionSpringContextTests

publicHibernateTitleDaoTests(){

//switchonfieldlevelinjection

setPopulateProtectedVariables(true);

}

//thisinstancewillbe(automatically)dependencyinjected

protectedHibernateTitleDaotitleDao;

publicvoidtestLoadTitle()throwsException{

Titletitle=this.titleDao.loadTitle(newLong(10));

assertNotNull(title);

}

//specifiestheSpringconfigurationtoloadforthistestfixture

protectedString[]getConfigLocations(){

returnnewString[]{"classpath:com/foo/daos.xml"};

}

}

protectedSpringbean

8.3.6.3.

AbstractTransactionalSpringContextTests PlatformTransactionManager

bean .AbstractTransactionalDataSourceSpringContextTests) JdbcTemplate———— AbstractTransactionalSpringContextTests

Java5 AbstractAnnotationAwareTransactionalTests

@Rollback(false)

endTransaction()Hibernate UI endTransaction()

8.3.6.4.JUnit3.8 AbstractTransactionalDataSourceSpringContextTests protected:

applicationContext(ConfigurableApplicationContext):AbstractSingleSpringContextTestsbean

jdbcTemplate:AbstractTransactionalDataSourceSpringContextTestsORMSpringORM‘’Hibernateflush()

8.3.6.5.Java5+

8.3.6.5.1.

org.springframework.test.annotationJUnitTestCaseAbstractAnnotationAwareTransactionalTests

AbstractTransactionalDataSourceSpringContextTests fixtureSpringAbstractAnnotationAwareTransactionalTests

@Transactional

8.3.6.5.2.JPA

org.springframework.test.jpaJavaAPI(JPA)

AbstractJpaTestsJPA

AbstractTransactionalDataSourceSpringContextTestsJPAEntityManagerFactoryEntityManager EntityManagerFactory

DataSourceJpaTransactionManager

AbstractAspectjJpaTestsAbstractJpaTests AspectJAspectJaop.xml

8.3.7.SpringTestContextFrameworkSpringTestContextFramework( org.springframework.test.context)JUnit3.8JUnit4.4,TestNG5.5TestContext JUnit3.8JUnit4.4TestNG5.5TestContext (

8.3.7.1.TestContextTestContextManagerTestExecutionListenerTestContextManagerTestContextManagerTestContext

TestContextManagerTestContextTestExecutionListenerJavaDocSpring

TestContext

TestContextManagerSpringTestContextFrameworkTestExecutionListener

TestExecutionListenerAPITestContextManagerTestContextManager

SpringTestExecutionListener ( @TestExecutionListeners

DependencyInjectionTestExecutionListenerDirtiesContextTestExecutionListener

TransactionalTestExecutionListenerTestContext

8.3.7.2.TestContextApplicationContext DependencyInjectionTestExecutionListener

AbstractJUnit38SpringContextTests AbstractJUnit4SpringContextTests

AbstractTestNGSpringContextTestsApplicationContextAwareJUnit3.8TestContext protected @ContextConfiguration

ContextLoader GenericXmlContextLoader

com.example.MyTestGenericXmlContextLoader

"classpath:/com/example/MyTest-context.xml"

packagecom.example;

@RunWith(SpringJUnit4ClassRunner.class)

//ApplicationContextwillbeloadedfrom"classpath:/com/example/MyTest-context.xml"

@ContextConfiguration

publicclassMyTest{

//classbody...

}

XML @ContextConfigurationlocations XMLclasspath web.xml

@RunWith(SpringJUnit4ClassRunner.class)

//ApplicationContextwillbeloadedfrom"/applicationContext.xml"

//intherootoftheclasspath

@ContextConfiguration(locations={"/applicationContext.xml","/applicationContext-test.xml"})

publicclassMyTest{

//classbody...

}

@ContextConfigurationbooleaninheritLocationslocations true

"/base-context.xml" "/extended-context.xml"ApplicationContext"/extended-context.xml"Beans"/base-context.xml"Beans

@RunWith(SpringJUnit4ClassRunner.class)

//ApplicationContextwillbeloadedfrom"/base-context.xml"

@ContextConfiguration(locations={"/base-context.xml"})

publicclassBaseTest{

//classbody...

}

//ApplicationContextwillbeloadedfrom"/base-context.xml"

//intherootoftheclasspath

@ContextConfiguration(locations={"/extended-context.xml"})

publicclassExtendedTestextendsBaseTest{

//classbody...

}

inheritLocationsfalse

, ApplicationContextfixture@DirtiesContext DirtiesContextTestExecutionListenerfixture

8.3.7.3.fixtureDependencyInjectionTestExecutionListener - -@TestExecutionListeners bean bean@ContextConfigurationField setterSpring2.5Spring @Autowiredsettter

TestContext @Autowired

@AutowiredbeanbeanApplicationContextAware ApplicationContext

applicationContext.getBean("titleDao")

@Autowired@ResourcesetterDependencyInjectionTestExecutionListener.class

HibernateTitleDao JUnit4.4JUnit4.4

@RunWith(SpringJUnit4ClassRunner.class)

//specifiestheSpringconfigurationtoloadforthistestfixture

@ContextConfiguration(locations={"daos.xml"})

publicfinalclassHibernateTitleDaoTests{

//thisinstancewillbedependencyinjectedbytype

@Autowired

privateHibernateTitleDaotitleDao;

publicvoidtestLoadTitle()throwsException{

Titletitle=this.titleDao.loadTitle(newLong(10));

assertNotNull(title);

}

}

@Autowiredsetter

@RunWith(SpringJUnit4ClassRunner.class)

//specifiestheSpringconfigurationtoloadforthistestfixture

@ContextConfiguration(locations={"daos.xml"})

publicfinalclassHibernateTitleDaoTests{

//thisinstancewillbedependencyinjectedbytype

privateHibernateTitleDaotitleDao;

@Autowired

publicvoidsetTitleDao(HibernateTitleDaotitleDao){

this.titleDao=titleDao;

}

publicvoidtestLoadTitle()throwsException{

Titletitle=this.titleDao.loadTitle(newLong(10));

assertNotNull(title);

}

}

@Resource

@RunWith(SpringJUnit4ClassRunner.class)

//specifiestheSpringconfigurationtoloadforthistestfixture

@ContextConfiguration(locations={"daos.xml"})

publicfinalclassHibernateTitleDaoTests{

//thisinstancewillbedependencyinjectedbyname

@Resource

privateHibernateTitleDaotitleDao;

publicvoidtestLoadTitle()throwsException{

Titletitle=this.titleDao.loadTitle(newLong(10));

assertNotNull(title);

}

}

@Resourcesetter

@RunWith(SpringJUnit4ClassRunner.class)

//specifiestheSpringconfigurationtoloadforthistestfixture

@ContextConfiguration(locations={"daos.xml"})

publicfinalclassHibernateTitleDaoTests{

//thisinstancewillbedependencyinjectedbyname

privateHibernateTitleDaotitleDao;

@Resource

publicvoidsetTitleDao(HibernateTitleDaotitleDao){

this.titleDao=titleDao;

}

publicvoidtestLoadTitle()throwsException{

Titletitle=this.titleDao.loadTitle(newLong(10));

assertNotNull(title);

}

}

XML @ContextConfiguration( "daos.xml")

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<!--thisbeanwillbeinjectedintotheHibernateTitleDaoTests

<beanid="titleDao"class="com.foo.dao.hibernate.HibernateTitleDao

<propertyname="sessionFactory"ref="sessionFactory"/>

</bean>

<beanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<!--dependencieselidedforclarity-->

</bean>

</beans>

8.3.7.4.TestContext TransactionalTestExecutionListener@TestExecutionListeners @TestExecutionListeners

@ContextConfigurationPlatformTransactionManagerbean@Transactional

TestContext@TransactionConfigurationbean@Transactional @NotTransactional

AbstractTransactionalJUnit38SpringContextTests

AbstractTransactionalJUnit4SpringContextTestsAbstractTransactionalTestNGSpringContextTests

TransactionalTestExecutionListenerTransactionalTestExecutionListener

(JUnit4@Before) (JUnit4@After) @NotTransactional@BeforeTransaction@AfterTransaction

JUnit4 TestContext

@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration

@TransactionConfiguration(transactionManager="txMgr",defaultRollback=false)

@Transactional

publicclassFictitiousTransactionalTest{

@BeforeTransaction

publicvoidverifyInitialDatabaseState(){

//logictoverifytheinitialstatebeforeatransactionisstarted

}

@Before

publicvoidsetUpTestDataWithinTransaction(){

//setuptestdatawithinthetransaction

}

@Test

//overridestheclass-leveldefaultRollbacksetting

@Rollback(true)

publicvoidmodifyDatabaseWithinTransaction(){

//logicwhichusesthetestdataandmodifiesdatabasestate

}

@After

publicvoidtearDownWithinTransaction(){

//execute"teardown"logicwithinthetransaction

}

@AfterTransaction

publicvoidverifyFinalDatabaseState(){

//logictoverifythefinalstateaftertransactionhasrolledback

}

@Test

@NotTransactional

publicvoidperformNonDatabaseRelatedAction(){

//logicwhichdoesnotmodifydatabasestate

}

}

8.3.7.5.TestContext

8.3.7.5.1.JUnit3.8

org.springframework.test.context.junit38JUnit3.8

AbstractJUnit38SpringContextTests

SpringTestContextFrameworkJUnit3.8ApplicationContextTestCase AbstractJUnit38SpringContextTests protected

applicationContextbean

AbstractTransactionalJUnit38SpringContextTests

JDBCAbstractJUnit38SpringContextTests ApplicationContext

javax.sql.DataSourcebeanPlatformTransactionManagerbeanAbstractTransactionalJUnit38SpringContextTests protected

applicationContextAbstractJUnit38SpringContextTestsbean

simpleJdbcTemplateORM‘flush’Hibernate Sessionflush()

8.3.7.5.2.JUnit4.4

org.springframework.test.context.junit4JUnit4.4

AbstractJUnit4SpringContextTests

SpringTestContextFrameworkJUnit4.4ApplicationContextAbstractJUnit4SpringContextTests protected

applicationContextbean

AbstractTransactionalJUnit4SpringContextTests

JDBCAbstractJUnit4SpringContextTests ApplicationContext

javax.sql.DataSourcebeanPlatformTransactionManagerbeanAbstractTransactionalJUnit4SpringContextTests protected

applicationContextAbstractJUnit4SpringContextTestsbean

simpleJdbcTemplateORM‘flush’ Hibernate Sessionflush()

Spring - -@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration@TestExecutionListeners

8.3.7.5.3.JUnit4.4

SpringTestContextFrameworkJUnit4.4@Runwith(SpringJUnit4ClassRunner.class)JUnit4.4 SpringRunner@ContextConfiguration ApplicationContext

@RunWith(SpringJUnit4ClassRunner.class)

@TestExecutionListeners({})

publicclassSimpleTest{

@Test

publicvoidtestMethod(){

//executetestlogic...

}

}

8.3.7.5.4.TestNG

org.springframework.test.context.testngTestNG

AbstractTestNGSpringContextTests

SpringTestContextFrameworkTestNGApplicationContext

AbstractTestNGSpringContextTests protected

applicationContextbean

AbstractTransactionalTestNGSpringContextTests

JDBCAbstractTestNGSpringContextTests ApplicationContext

javax.sql.DataSourcebeanPlatformTransactionManagerbeanAbstractTransactionalTestNGSpringContextTests protected

applicationContextAbstractTestNGSpringContextTestsbean

simpleJdbcTemplateORM‘flush’Hibernate Sessionflush()

Spring--@ContextConfiguration@TestExecutionListenersTestContextManager AbstractTestNGSpringContextTests

8.3.7.6.TestContextSpringTestContextFramework JUnit SpringJUnit4ClassRunnerJUnit4.4

@IfProfileValue

@ProfileValueSourceConfiguration

@ExpectedException

Spring@ExpectedExceptionJUnit4@Test(expected=...)

JUnit4@Timed

Spring@TimedJUnit4@Test(timeout=...) JUnit4JUnit @Test(timeout=...) Spring@Test(timeout=...)

@Repeat

SpringTestContextFramework@Autowired

@Qualifier

@Resource(javax.annotation)JSR-250

@PersistenceContext(javax.persistence)JPA

@PersistenceUnit(javax.persistence)JPA

@Required

@Transactional

SpringTestContextFrameworkJavaDoc@ContextConfiguration

ApplicationContext @ContextConfiguration

@ContextConfiguration(locations={"example/test-context.xml"},loader=CustomContextLoader.class)

publicclassCustomConfiguredApplicationContextTests{

//classbody...

}

@ContextConfiguration JavaDoc

@TestExecutionListeners

TestExecutionListenersTestContextManager@TestExecutionListeners@ContextConfiguration

@ContextConfiguration

@TestExecutionListeners({CustomTestExecutionListener.class,AnotherTestExecutionListener.class})

publicclassCustomTestExecutionListenerTests{

//classbody...

}

@TestExecutionListenersJavaDoc

@TransactionConfiguration

PlatformTransactionManager“transactionManager”PlatformTransactionManagerbean defaultRollbackfalse

@TransactionConfiguration@ContextConfiguration

@ContextConfiguration

@TransactionConfiguration(transactionManager="txMgr",defaultRollback=false)

publicclassCustomConfiguredTransactionalTests{

//classbody...

}

@BeforeTransaction

publicvoid @Transactional

@BeforeTransaction

publicvoidbeforeTransaction(){

//logictobeexecutedbeforeatransactionisstarted

}

@AfterTransaction

publicvoid @Transactional

@AfterTransaction

publicvoidafterTransaction(){

//logictobeexecutedafteratransactionhasended

}

8.3.8.PetClinicSpringPetClinicJUnit4.4 SpringTestContextFrameworkAbstractClinicTests

@ContextConfiguration

publicabstractclassAbstractClinicTestsextendsAbstractTransactionalJUnit4SpringContextTests

@Autowired

protectedClinicclinic;

@Test

publicvoidgetVets(){

Collection<Vet>vets=this.clinic.getVets();

assertEquals("JDBCquerymustshowthesamenumberofvets",

super.countRowsInTable("VETS"),vets.size());

Vetv1=EntityUtils.getById(vets,Vet.class,2);

assertEquals("Leary",v1.getLastName());

assertEquals(1,v1.getNrOfSpecialties());

assertEquals("radiology",(v1.getSpecialties().get(0)).getName());

//...

}

//...

}

AbstractTransactionalJUnit4SpringContextTestsDependencyInjectionTestExecutionListener

TransactionalTestExecutionListener

clinic-- @Autowired

testGetVets()countRowsInTable()

AbstractClinicTestsPetClinic-JDBCHibernateJPAAbstractClinicTests "AbstractClinicTests-context.xml"

PlatformTransactionManagerClinic

PetClinicHibernate HibernateClinicTests@ContextConfigurationAbstractClinicTestsSpringTestContextFramework"AbstractClinicTests-context.xml"()"HibernateClinicTests-context.xml" "HibernateClinicTests-

context.xml"bean"AbstractClinicTests-context.xml"bean

@ContextConfiguration

publicclassHibernateClinicTestsextendsAbstractClinicTests{}

PetClinicSpringSpringDataSourceJtaTransactionManagerJNDIJTABasicDataSourceDataSourceTransactionManager

HibernateTransactionManagerXML''

8.4.

JUnitSpringJUnit3.8

TestNGTestNGJUnit3.8Java5

MockObjectsMockObjects

“MockObjects”

EasyMockSpringEasyMock

JMockJMockmockJava

DbUnitDbUnitJUnitAnt

GrinderGrinderJava

II.

SpringSpringFramework9

10 DAO

11 JDBC

12 ORM

9.9.1.9.2.9.3.9.4.

9.4.1.9.4.2.9.4.3.TransactionAwareDataSourceProxy

9.5.9.5.1.Spring9.5.2.9.5.3.9.5.4.bean9.5.5.<tx:advice/>9.5.6. @Transactional

9.5.7.9.5.8.9.5.9.AspectJ @Transactional

9.6.9.6.1.TransactionTemplate9.6.2.PlatformTransactionManager

9.7.9.8.

9.8.1.IBMWebSphere9.8.2.BEAWebLogic9.8.3.OracleOC4J

9.9.9.9.1. DataSource

9.10.

10.DAO10.1.10.2.10.3.DAO

11.JDBC11.1.

11.1.1.11.1.2.SpringJDBC

11.2.JDBCJDBC11.2.1.JdbcTemplate11.2.2.NamedParameterJdbcTemplate11.2.3.SimpleJdbcTemplate11.2.4.DataSource11.2.5.SQLExceptionTranslator11.2.6.SQL11.2.7.11.2.8.11.2.9.

11.3.11.3.1.DataSourceUtils11.3.2.SmartDataSource11.3.3.AbstractDataSource11.3.4.SingleConnectionDataSource11.3.5.DriverManagerDataSource11.3.6.TransactionAwareDataSourceProxy11.3.7.DataSourceTransactionManager11.3.8.NativeJdbcExtractor

11.4.JDBC11.4.1.JdbcTemplate11.4.2.SimpleJdbcTemplate

11.5.SimpleJdbcJDBC11.5.1.SimpleJdbcInsert11.5.2.SimpleJdbcInsert11.5.3.SimpleJdbcInsert11.5.4.SqlParameterSource11.5.5.SimpleJdbcCall11.5.6.SimpleJdbcCall11.5.7.SqlParameters11.5.8.SimpleJdbcCall11.5.9.SimpleJdbcCallResultSet/REFCursor

11.6.JavaJDBC11.6.1.SqlQuery11.6.2.MappingSqlQuery11.6.3.SqlUpdate11.6.4.StoredProcedure11.6.5.SqlFunction

11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.

12.ORM12.1.12.2.Hibernate

12.2.1.12.2.2.Spring SessionFactory

12.2.3.TheHibernateTemplate12.2.4.SpringDAO12.2.5.Hibernate3APIDAO12.2.6.12.2.7.12.2.8.12.2.9.vs12.2.10.Hibernate

12.3.JDO12.3.1.PersistenceManagerFactory12.3.2.JdoTemplateJdoDaoSupport12.3.3.JDOAPIDAO12.3.4.12.3.5.JdoDialect

12.4.OracleTopLink12.4.1.SessionFactory12.4.2.TopLinkTemplateandTopLinkDaoSupport12.4.3.TopLinkAPIDAO12.4.4.

12.5.iBATISSQLMaps12.5.1.SqlMapClient12.5.2. SqlMapClientTemplate SqlMapClientDaoSupport

12.5.3.iBATISAPIDAO12.6.JPA

12.6.1.SpringJPA12.6.2.JpaTemplate JpaDaoSupport

12.6.3.JPADAO12.6.4.

12.7.12.8.JpaDialect

9

9.1.9.2.9.3.9.4.

9.4.1.9.4.2.9.4.3.TransactionAwareDataSourceProxy

9.5.9.5.1.Spring9.5.2.9.5.3.9.5.4.bean9.5.5.<tx:advice/>9.5.6. @Transactional

9.5.7.9.5.8.9.5.9.AspectJ @Transactional

9.6.9.6.1.TransactionTemplate9.6.2.PlatformTransactionManager

9.7.9.8.

9.8.1.IBMWebSphere9.8.2.BEAWebLogic9.8.3.OracleOC4J

9.9.9.9.1. DataSource

9.10.

9.1.SpringSpring

APIJTAJDBCHibernateJPAJDO

APIJTA API

SpringSpring

SpringEJBCMTAPIHibernate

Spring DataSource

Spring

Spring

SpringJ2EEEJBJTASpringEJBCMTJTAOracle9iRACJMSJCASpring EJBCMTJTAJDBCSpring

9.2.J2EE JTAJDBC

. JTAAPIJTAUserTransactionJNDIJTA JNDIJTAJTA EJBCMTJNDIEJBJNDICMTJTAEJBEJBFacadeEJBEJB. JDBCJTASpring Spring

SpringSpringAPI

9.3.Spring org.springframework.transaction.PlatformTransactionManager

publicinterfacePlatformTransactionManager{

TransactionStatusgetTransaction(TransactionDefinitiondefinition)

throwsTransactionException;

voidcommit(TransactionStatusstatus)throwsTransactionException;

voidrollback(TransactionStatusstatus)throwsTransactionException;

}

SPI Spring PlatformTransactionManager JNDIPlatformTransactionManagerSpringIoCJTAJTA

Spring PlatformTransactionManager TransactionExceptionuncheckedexception java.lang.RuntimeException

TransactionException

getTransaction(..) TransactionDefinition TransactionStatus TransactionStatusJ2EE TransactionStatus TransactionDefinition

SpringEJBCMT

:

:HibernateSpringTransactionStatusAPI:

publicinterfaceTransactionStatus{

booleanisNewTransaction();

voidsetRollbackOnly();

booleanisRollbackOnly();

}

Spring PlatformTransactionManagerSpringIoCPlatformTransactionManagerJDBCJTAHibernateSpring

——jPetStore——dataAccessContext-local.xml

PlatformTransactionManagerJDBCJDBCDataSourceSpringDataSourceTransactionManagerDataSource

<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<propertyname="driverClassName"value="${jdbc.driverClassName}"/>

<propertyname="url"value="${jdbc.url}"/>

<propertyname="username"value="${jdbc.username}"/>

<propertyname="password"value="${jdbc.password}"/>

</bean>

PlatformTransactionManagerbean

<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<propertyname="dataSource"ref="dataSource"/>

</bean>

J2EEJTA 'dataAccessContext-jta.xml'JNDISpringJtaTransactionManager DataSourceJtaTransactionManagerDataSource

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:jee="http://www.springframework.org/schema/jee"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd

http://www.springframework.org/schema/jeehttp://www.springframework.org/schema/jee/spring-jee-2.0.xsd">

<jee:jndi-lookupid="dataSource"jndi-name="jdbc/jpetstore"/>

<beanid="txManager"class="org.springframework.transaction.jta.JtaTransactionManager"/>

<!--other<bean/>definitionshere-->

</beans>

'dataSource'bean 'jee' <jndi-lookup/>, A, XML Schema-based configuration <jee/> A.2.3 “The jee

schema”HibernateSpring PetClinicHibernateLocalSessionFactoryBeanHibernateSessionDataSourcebeanJEE DataSourceJEESpring'txManager' bean HibernateTransactionManager

DataSourceTransactionManager DataSourceHibernateTransactionManager SessionFactory

<beanid="sessionFactory"class="org.springframework.orm.hibernate.LocalSessionFactoryBean">

<propertyname="dataSource"ref="dataSource"/>

<propertyname="mappingResources">

<list>

<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>

</list>

</property>

<propertyname="hibernateProperties">

<value>

hibernate.dialect=${hibernate.dialect}

</value>

</property>

</bean>

<beanid="txManager"class="org.springframework.orm.hibernate.HibernateTransactionManager">

<propertyname="sessionFactory"ref="sessionFactory"/>

</bean>

JtaTransactionManagerHibernateJTAJDBC

<beanid="txManager"class="org.springframework.transaction.jta.JtaTransactionManager"/>

JTA

9.4.DataSourceTransactionManager JDBC DataSource

HibernateTransactionManagerHibernate SessionFactoryAPIJDBCHibernateJDO PlatformTransactionManager

9.4.1.SpringAPIAPIAPI JdbcTemplateHibernateTemplateJdoTemplate

9.4.2.DataSourceUtilsJDBC SessionFactoryUtils

Hibernate PersistenceManagerFactoryUtilsJDOAPISpringbeanAPIJDBC DataSource getConnection() Springorg.springframework.jdbc.datasource.DataSourceUtils

Connectionconn=DataSourceUtils.getConnection(dataSource);

connectionconnectionconnectionSQLExceptionSpring CannotGetJdbcConnectionExceptionSpringuncheckedDataAccessExceptions SQLException

SpringSpringSpringJDBCHibernate DataSourceUtilsSpringAPISpring JdbcTemplate jdbc.objectJDBCSpring

9.4.3.TransactionAwareDataSourceProxy TransactionAwareDataSourceProxy DataSource DataSource

SpringJ2EEJNDI DataSource

JDBC DataSourceSpringSpring

TransactionProxyFactoryBean

Spring2.0TransactionProxyFactoryBean

Spring2.0 <tx:tags/>

TransactionProxyFactoryBean

9.5.Spring SpringSpringAOPSpringEJBCMTSpring

EJBCMTJTASpring

SpringEJB

SpringEJB

SpringAOP

SpringEJBthrowableJavaTransactionStatus setRollbackOnly()

MyApplicationException SpringAPIEJBEJB EJBCMT java.rmi.RemoteExceptioncheckedexception SpringEJBuncheckedexceptions

9.5.1.Spring@Transactional '<tx:annotation-driven/>'Spring

SpringSpringAOP XML AOPPlatformTransactionManager TransactionInterceptor

SpringAOPSpringAOP 6 SpringAOP SpringAOP

9.5.2. Foo Bar

//

packagex.y.service;

publicinterfaceFooService{

FoogetFoo(StringfooName);

FoogetFoo(StringfooName,StringbarName);

voidinsertFoo(Foofoo);

voidupdateFoo(Foofoo);

}

//

packagex.y.service;

publicclassDefaultFooServiceimplementsFooService{

publicFoogetFoo(StringfooName){

thrownewUnsupportedOperationException();

}

publicFoogetFoo(StringfooName,StringbarName){

thrownewUnsupportedOperationException();

}

publicvoidinsertFoo(Foofoo){

thrownewUnsupportedOperationException();

}

publicvoidupdateFoo(Foofoo){

thrownewUnsupportedOperationException();

}

}

DefaultFooService UnsupportedOperationException

UnsupportedOperationExceptionFooServicegetFoo(String) getFoo(String, String) insertFoo(Foo)

updateFoo(Foo)

<!--fromthefile'context.xml'-->

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<!--thisistheserviceobjectthatwewanttomaketransactional-->

<beanid="fooService"class="x.y.service.DefaultFooService"/>

<!--thetransactionaladvice(what'happens';seethe<aop:advisor/>

<tx:adviceid="txAdvice"transaction-manager="txManager">

<!--thetransactionalsemantics...-->

<tx:attributes>

<!--allmethodsstartingwith'get'areread-only-->

<tx:methodname="get*"read-only="true"/>

<!--othermethodsusethedefaulttransactionsettings(seebelow)-->

<tx:methodname="*"/>

</tx:attributes>

</tx:advice>

<!--ensurethattheabovetransactionaladvicerunsforanyexecution

ofanoperationdefinedbytheFooServiceinterface-->

<aop:config>

<aop:pointcutid="fooServiceOperation"expression="execution(*x.y.service.FooService.*(..))"/>

<aop:advisoradvice-ref="txAdvice"pointcut-ref="fooServiceOperation"/>

</aop:config>

<!--don'tforgettheDataSource-->

<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<propertyname="driverClassName"value="oracle.jdbc.driver.OracleDriver"/>

<propertyname="url"value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>

<propertyname="username"value="scott"/>

<propertyname="password"value="tiger"/>

</bean>

<!--similarly,don'tforgetthePlatformTransactionManager

<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<propertyname="dataSource"ref="dataSource"/>

</bean>

<!--other<bean/>definitionshere-->

</beans>

'fooService'bean” 'transaction-manager' PlatformTransactionManager

'txManager' bean

PlatformTransactionManager bean'transactionManager' <tx:advice/> 'transaction-

manager' <aop:config/> 'txAdvice'bean 'fooServiceOperation'advisor 'txAdvice' 'fooServiceOperation' 'txAdvice'<aop:pointcut/>AspectJSpring2.0 6 SpringAOP

<aop:config>

<aop:pointcutid="fooServiceMethods"expression="execution(*x.y.service.*.*(..))"/>

<aop:advisoradvice-ref="txAdvice"pointcut-ref="fooServiceMethods"/>

</aop:config>

'x.y.service' 6 SpringAOP “ ”'fooService'bean

publicfinalclassBoot{

publicstaticvoidmain(finalString[]args)throwsException{

ApplicationContextctx=newClassPathXmlApplicationContext("context.xml",Boot.class);

FooServicefooService=(FooService)ctx.getBean("fooService");

fooService.insertFoo(newFoo());

}

}

Log4J DefaultFooService insertFoo(..)UnsupportedOperationException

<!--Spring...-->

[AspectJInvocationContextExposingAdvisorAutoProxyCreator]-Creatingimplicitproxy

forbean'fooService'with0commoninterceptorsand1specificinterceptors

<!--theDefaultFooServiceisactuallyproxied-->

[JdkDynamicAopProxy]-CreatingJDKdynamicproxyfor[x.y.service.DefaultFooService]

<!--...theinsertFoo(..)methodisnowbeinginvokedontheproxy-->

[TransactionInterceptor]-Gettingtransactionforx.y.service.FooService.insertFoo

<!--thetransactionaladvicekicksinhere...-->

[DataSourceTransactionManager]-Creatingnewtransactionwithname[x.y.service.FooService.insertFoo]

[DataSourceTransactionManager]-AcquiredConnection

[org.apache.commons.dbcp.PoolableConnection@a53de4]forJDBCtransaction

<!--theinsertFoo(..)methodfromDefaultFooServicethrowsanexception...-->

[RuleBasedTransactionAttribute]-Applyingrulestodeterminewhethertransactionshould

rollbackonjava.lang.UnsupportedOperationException

[TransactionInterceptor]-Invokingrollbackfortransactiononx.y.service.FooService.insertFoo

duetothrowable[java.lang.UnsupportedOperationException]

<!--andthetransactionisrolledback(bydefault,RuntimeException

[DataSourceTransactionManager]-RollingbackJDBCtransactiononConnection

[org.apache.commons.dbcp.PoolableConnection@a53de4]

[DataSourceTransactionManager]-ReleasingJDBCConnectionaftertransaction

[DataSourceUtils]-ReturningJDBCConnectiontoDataSource

Exceptioninthread"main"java.lang.UnsupportedOperationException

atx.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14)

<!--AOPinfrastructurestacktraceelementsremovedforclarity-->

at$Proxy0.insertFoo(UnknownSource)

atBoot.main(Boot.java:11)

9.5.3.Springcontext ExceptionSpringSpring uncheckedexceptionsErrors--Checkedexceptions Exception XMLchecked

<tx:adviceid="txAdvice"transaction-manager="txManager">

<tx:attributes>

<tx:methodname="get*"read-only="true"rollback-for="NoProductInStockException"

<tx:methodname="*"/>

</tx:attributes>

</tx:advice>

“” Spring

<tx:adviceid="txAdvice">

<tx:attributes>

<tx:methodname="updateStock"no-rollback-for="InstrumentNotFoundException"

<tx:methodname="*"/>

</tx:attributes>

</tx:advice>

Spring InstrumentNotFoundException

<tx:adviceid="txAdvice">

<tx:attributes>

<tx:methodname="*"rollback-for="Throwable"no-rollback-for="InstrumentNotFoundException"/>

</tx:attributes>

</tx:advice>

Spring

publicvoidresolvePosition(){

try{

//somebusinesslogic...

}catch(NoProductInStockExceptionex){

//triggerrollbackprogrammatically

TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

}

}

POJO

9.5.4.bean Spring <aop:advisor/> advisor'advice-ref'

'x.y.service' service 'Service'

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<aop:config>

<aop:pointcutid="serviceOperation"

expression="execution(*x.y.service..*Service.*(..))

<aop:advisorpointcut-ref="serviceOperation"advice-ref="txAdvice"/>

</aop:config>

<!--thesetwobeanswillbetransactional...-->

<beanid="fooService"class="x.y.service.DefaultFooService"/>

<beanid="barService"class="x.y.service.extras.SimpleBarService"/>

<!--...andthesetwobeanswon't-->

<beanid="anotherService"class="org.xyz.SomeService"/><!--(notintherightpackage)-->

<beanid="barManager"class="x.y.service.SimpleBarManager"/>

<tx:adviceid="txAdvice">

<tx:attributes>

<tx:methodname="get*"read-only="true"/>

<tx:methodname="*"/>

</tx:attributes>

</tx:advice>

<!--othertransactioninfrastructurebeanssuchasaPlatformTransactionManager

</beans>

bean

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<aop:config>

<aop:pointcutid="defaultServiceOperation"

expression="execution(*x.y.service.*Service.*(..))

<aop:pointcutid="noTxServiceOperation"

expression="execution(*x.y.service.ddl.DefaultDdlManager.*(..))

<aop:advisorpointcut-ref="defaultServiceOperation"advice-ref="defaultTxAdvice"/>

<aop:advisorpointcut-ref="noTxServiceOperation"advice-ref="noTxAdvice"/>

</aop:config>

<!--thisbeanwillbetransactional(seethe'defaultServiceOperation'

<beanid="fooService"class="x.y.service.DefaultFooService"/>

<!--thisbeanwillalsobetransactional,butwithtotallydifferenttransactionalsettings-->

<beanid="anotherFooService"class="x.y.service.ddl.DefaultDdlManager"/>

<tx:adviceid="defaultTxAdvice">

<tx:attributes>

<tx:methodname="get*"read-only="true"/>

<tx:methodname="*"/>

</tx:attributes>

</tx:advice>

<tx:adviceid="noTxAdvice">

<tx:attributes>

<tx:methodname="*"propagation="NEVER"/>

</tx:attributes>

</tx:advice>

<!--othertransactioninfrastructurebeanssuchasaPlatformTransactionManager

</beans>

9.5.5.<tx:advice/> <tx:advice/> <tx:advice/>

REQUIRED

DEFAULT

/

RuntimeExceptionchecked Exception <tx:advice/> <tx:attributes/> <tx:method/>

9.1.<tx:method/>

name *

propagation REQUIRED

isolation DEFAULT

timeout -1

read-only false

rollback-

for Exception(s)

'com.foo.MyBusinessException,ServletException'

no-

rollback-

for

Exception(s)

'com.foo.MyBusinessException,ServletException'

WebLogic'com.foo.BusinessService.handlePayment'.

9.5.6. @Transactional

@TransactionalJava5TigerXMLJava @Transactional

//theserviceclassthatwewanttomaketransactional

@Transactional

publicclassDefaultFooServiceimplementsFooService{

FoogetFoo(StringfooName);

FoogetFoo(StringfooName,StringbarName);

voidinsertFoo(Foofoo);

voidupdateFoo(Foofoo);

}

POJOSpringIoCbean xml

<!--fromthefile'context.xml'-->

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<!--thisistheserviceobjectthatwewanttomaketransactional-->

<beanid="fooService"class="x.y.service.DefaultFooService"/>

<!--enabletheconfigurationoftransactionalbehaviorbasedonannotations-->

<tx:annotation-driventransaction-manager="txManager"/>

<!--aPlatformTransactionManagerisstillrequired-->

<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<!--(thisdependencyisdefinedsomewhereelse)-->

@Transactional

@Transactional public protectedprivatepackage-visible@TransactionalAspectJ()

<propertyname="dataSource"ref="dataSource"/>

</bean>

<!--other<bean/>definitionshere-->

</beans>

'transactionManager' PlatformTransactionManager

bean <tx:annotation-driven/> 'transaction-

manager' PlatformTransactionManagerbean'transaction-manager'

@Transactional public@Transactional @Transactionalbeans<tx:annotation-driven/> Spring @Transactional @Transactional

Spring@Transactional‘’ ‘’‘’AspectJ

9.2.<tx:annotation-driven/>

transaction-

managertransactionManager transactionManager

mode proxy

“proxy”SpringAOPbean"aspectj"SpringAspectJAspectJclasspathspring-aspects.jar() (

proxy-

target-classfalse

@Transactional "target-class" "true""proxy-target-class"" false"JDK( 6.6“”

order Ordered.LOWEST_PRECEDENCE @Transactionalbean AOP(6.2.4.7“” ) AOP

<tx:annotation-driven/>" proxy-target-class"@Transactional " proxy-target-class"" true"" proxy-target-class"" false"JDK

DefaultFooService@Transactional

@Transactional(readOnly=true)

publicclassDefaultFooServiceimplementsFooService{

publicFoogetFoo(StringfooName){

//dosomething

}

//thesesettingshaveprecedenceforthismethod

@Transactional(readOnly=false,propagation=Propagation.REQUIRES_NEW)

publicvoidupdateFoo(Foofoo){

//dosomething

}

}

9.5.6.1.@Transactional@Transactional “ ”

PROPAGATION_REQUIRED

ISOLATION_DEFAULT

/

RuntimeExceptionchecked Exception

@Transactional

9.3.@Transactional

propagation Propagation

isolation Isolation ISOLATION_DEFAULT

readOnly vs.

timeout int

rollbackFor ClassThrowable

checkedexceptionsuncheckedexceptions RuntimeException

rollbackForClassname ClassThrowable

noRollbackFor ClassThrowable

noRollbackForClassname ClassThrowable

WebLogichandlePayment(..)

com.foo.BusinessService.handlePayment

9.5.7.Spring SpringSpring

9.5.7.1.required

PROPAGATION_REQUIRED

PROPAGATION_REQUIRED rollback-onlyPROPAGATION_REQUIRED rollback-onlyrollback-only

9.5.7.2.RequiresNew

PROPAGATION_REQUIRES_NEW

PROPAGATION_REQUIRES_NEW

9.5.7.3.NestedPROPAGATION_NESTED Spring DataSourceTransactionManager).

9.5.8. advice profiling <tx:annotation-driven/>

updateFoo(Foo)

profilingaspect

AOP 6 SpringAOP

profilingaspect Ordered

packagex.y;

importorg.aspectj.lang.ProceedingJoinPoint;

importorg.springframework.util.StopWatch;

importorg.springframework.core.Ordered;

publicclassSimpleProfilerimplementsOrdered{

privateintorder;

//allowsustocontroltheorderingofadvice

publicintgetOrder(){

returnthis.order;

}

publicvoidsetOrder(intorder){

this.order=order;

}

//thismethodisthearoundadvice

publicObjectprofile(ProceedingJoinPointcall)throwsThrowable{

ObjectreturnValue;

StopWatchclock=newStopWatch(getClass().getName());

try{

clock.start(call.toShortString());

returnValue=call.proceed();

}finally{

clock.stop();

System.out.println(clock.prettyPrint());

}

returnreturnValue;

}

}

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<beanid="fooService"class="x.y.service.DefaultFooService"/>

<!--thisistheaspect-->

<beanid="profiler"class="x.y.SimpleProfiler">

<!--executebeforethetransactionaladvice(hencethelowerordernumber)-->

<propertyname="order"value="1"/>

</bean>

<tx:annotation-driventransaction-manager="txManager"order="200"

<aop:config>

<!--thisadvicewillexecutearoundthetransactionaladvice-->

<aop:aspectid="profilingAspect"ref="profiler">

<aop:pointcutid="serviceMethodWithReturnValue"

expression="execution(!voidx.y..*Service.*(..))"/>

<aop:aroundmethod="profile"pointcut-ref="serviceMethodWithReturnValue"/>

</aop:aspect>

</aop:config>

<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<propertyname="driverClassName"value="oracle.jdbc.driver.OracleDriver"/>

<propertyname="url"value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>

<propertyname="username"value="scott"/>

<propertyname="password"value="tiger"/>

</bean>

<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">

<propertyname="dataSource"ref="dataSource"/>

</bean>

</beans>

'fooService'beanXML

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<beanid="fooService"class="x.y.service.DefaultFooService"/>

<!--theprofilingadvice-->

<beanid="profiler"class="x.y.SimpleProfiler">

<!--executebeforethetransactionaladvice(hencethelowerordernumber)-->

<propertyname="order"value="1"/>

</bean>

<aop:config>

<aop:pointcutid="entryPointMethod"expression="execution(*x.y..*Service.*(..))"/>

<!--willexecuteaftertheprofilingadvice(c.f.theorderattribute)-->

<aop:advisor

advice-ref="txAdvice"

pointcut-ref="entryPointMethod"

order="2"/><!--ordervalueishigherthantheprofilingaspect-->

<aop:aspectid="profilingAspect"ref="profiler">

<aop:pointcutid="serviceMethodWithReturnValue"

expression="execution(!voidx.y..*Service.*(..))"/>

<aop:aroundmethod="profile"pointcut-ref="serviceMethodWithReturnValue"/>

</aop:aspect>

</aop:config>

<tx:adviceid="txAdvice"transaction-manager="txManager">

<tx:attributes>

<tx:methodname="get*"read-only="true"/>

<tx:methodname="*"/>

</tx:attributes>

</tx:advice>

<!--other<bean/>definitionssuchasaDataSourceanda

</beans>

'fooService'bean beanorder

9.5.9.AspectJ @Transactional

AspectJSpringSpring @Transactional @Transactional

spring-aspects.jarorg.springframework.transaction.aspectj.AnnotationTransactionAspect

SpringSpring

9.5.6“ @Transactional” 6 SpringAOP

//constructanappropriatetransactionmanager

DataSourceTransactionManagertxManager=newDataSourceTransactionManager(getDataSource());

//configuretheAnnotationTransactionAspecttouseit;thismustbedonebeforeexecutinganytransactionalmethods

AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager);

aspect / AspectJJava @Transactional @Transactional AnnotationTransactionAspect AspectJ AspectJ Development

Guide“”load-timeweaving 6.8.4“SpringAspectJLTW” AspectJ“”

9.6.Spring

TransactionTemplate

PlatformTransactionManagerSpring TransactionTemplateJTA UserTransactionAPI

9.6.1. TransactionTemplate

TransactionTemplateSpring JdbcTemplate

TransactionTemplateSpringAPITransactionTemplate TransactionCallback

TransactionCallbackTransactionTemplateexecute(..)

publicclassSimpleServiceimplementsService{

//singleTransactionTemplatesharedamongstallmethodsinthisinstance

privatefinalTransactionTemplatetransactionTemplate;

//useconstructor-injectiontosupplythePlatformTransactionManager

publicSimpleService(PlatformTransactionManagertransactionManager){

Assert.notNull(transactionManager,"The'transactionManager'argumentmustnotbenull.");

this.transactionTemplate=newTransactionTemplate(transactionManager);

}

publicObjectsomeServiceMethod(){

returntransactionTemplate.execute(newTransactionCallback(){

//thecodeinthismethodexecutesinatransactionalcontext

publicObjectdoInTransaction(TransactionStatusstatus){

updateOperation1();

returnresultOfUpdateOperation2();

}

});

}

}

TransactionCallbackWithoutResult

transactionTemplate.execute(newTransactionCallbackWithoutResult

protectedvoiddoInTransactionWithoutResult(TransactionStatusstatus){

updateOperation1();

updateOperation2();

}

});

TransactionStatus setRollbackOnly()

transactionTemplate.execute(newTransactionCallbackWithoutResult(){

protectedvoiddoInTransactionWithoutResult(TransactionStatusstatus){

try{

updateOperation1();

updateOperation2();

}catch(SomeBusinessExeptionex){

status.setRollbackOnly();

}

}

});

9.6.1.1.TransactionTemplate TransactionTemplate

publicclassSimpleServiceimplementsService{

privatefinalTransactionTemplatetransactionTemplate;

publicSimpleService(PlatformTransactionManagertransactionManager){

Assert.notNull(transactionManager,"The'transactionManager'argumentmustnotbenull.");

this.transactionTemplate=newTransactionTemplate(transactionManager);

//thetransactionsettingscanbesethereexplicitlyifsodesired

this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);

this.transactionTemplate.setTimeout(30);//30seconds

//andsoforth...

}

}

SpringXML TransactionTemplate 'sharedTransactionTemplate'

<beanid="sharedTransactionTemplate"

class="org.springframework.transaction.support.TransactionTemplate">

<propertyname="isolationLevelName"value="ISOLATION_READ_UNCOMMITTED"/>

<propertyname="timeout"value="30"/>

</bean>"

TransactionTemplate TransactionTemplate

TransactionTemplate TransactionTemplate()TransactionTemplate

9.6.2. PlatformTransactionManager

org.springframework.transaction.PlatformTransactionManagerbean PlatformTransactionManagerbeanTransactionStatus

DefaultTransactionDefinitiondef=newDefaultTransactionDefinition();

//explicitlysettingthetransactionnameissomethingthatcanonlybedoneprogrammatically

def.setName("SomeTxName");

def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

TransactionStatusstatus=txManager.getTransaction(def);

try{

//executeyourbusinesslogichere

}

catch(MyExceptionex){

txManager.rollback(status);

throwex;

}

txManager.commit(status);

9.7.Web

9.8.SpringSpring JtaTransactionManager JNDIJTAUserTransaction TransactionManagerTransactionManager JtaTransactionManager

J2EESpring JtaTransactionManagerGeronimoOracleOC4J SpringIBMWebSphereBEAWebLogicOracleOC4J.WebLogicWebSphereOC4J '<tx:jta-transaction-manager/>'

9.8.1.IBMWebSphereWebSphere6.0SpringJTA WebSphereUowTransactionManagerWebSphere6.0.2.196.1.0.9 UOWManager

PROPAGATION_REQUIRES_NEW/IBMWebSphere5.1Spring WebSphereTransactionManagerFactoryBeanWebSphere JTATransactionManager beanJTATransactionManager Spring JtaTransactionManager

UserTransactionjavadocWebSphereTransactionManagerFactoryBeanWAS5.16.0WebSphereUowTransactionManager

9.8.2.BEAWebLogicWebLogic 8.1WebLogic WebLogicJtaTransactionManager JtaTransactionManagerWebLogicSpringJTA

9.8.3.OracleOC4JSpringOC4J10.1.3 OC4JJtaTransactionManager

WebLogicJtaTransactionManager OC4J JTA Spring JtaTransactionManager OC4J OC4JJtaTransactionManagerJTA

9.9.

9.9.1. DataSource PlatformTransactionManager Springorg.springframework.transaction.jta.JtaTransactionManager Spring

9.10.Spring

InfoQ JavaJavaTransactionDesignStrategies Java

10DAO

10.1.10.2.10.3.DAO

10.1.SpringDAO() JDBCHibernateJDO

10.2.Spring SQLExceptionJDBCSpringHibernatechecked DAOcatch/throwSpringORMSessionFactoryUtils convertHibernateAccessException

convertJdoAccessException org.springframework.dao

unchecked DAOSpring DataAccessException

10.3.DAOJDBCJDOHibernate Spring

JdbcDaoSupport-JDBC DataSource

HibernateDaoSupport-Hibernate SessionFactory

HibernateTemplate HibernateTemplateexceptiontranslatorJdoDaoSupport-JDO PersistenceManagerFactory

JpaDaoSupport-JPA EntityManagerFactory

11JDBC

11.1.11.1.1.11.1.2.SpringJDBC

11.2.JDBCJDBC11.2.1.JdbcTemplate11.2.2.NamedParameterJdbcTemplate11.2.3.SimpleJdbcTemplate11.2.4.DataSource11.2.5.SQLExceptionTranslator11.2.6.SQL11.2.7.11.2.8.11.2.9.

11.3.11.3.1.DataSourceUtils11.3.2.SmartDataSource11.3.3.AbstractDataSource11.3.4.SingleConnectionDataSource11.3.5.DriverManagerDataSource11.3.6.TransactionAwareDataSourceProxy11.3.7.DataSourceTransactionManager11.3.8.NativeJdbcExtractor

11.4.JDBC11.4.1.JdbcTemplate11.4.2.SimpleJdbcTemplate

11.5.SimpleJdbcJDBC11.5.1.SimpleJdbcInsert11.5.2.SimpleJdbcInsert11.5.3.SimpleJdbcInsert11.5.4.SqlParameterSource11.5.5.SimpleJdbcCall11.5.6.SimpleJdbcCall11.5.7.SqlParameters11.5.8.SimpleJdbcCall11.5.9.SimpleJdbcCallResultSet/REFCursor

11.6.JavaJDBC11.6.1.SqlQuery11.6.2.MappingSqlQuery

11.6.3.SqlUpdate11.6.4.StoredProcedure11.6.5.SqlFunction

11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.

11.1.SpringJDBCSpringJDBC

SQL

SQL

SpringJDBCAPI

11.1.1.SpringJDBCSpringJdbcTemplate,Spring2.5SimpleJdbc;RDBMSObject,JDO .,,

JdbcTemplate-SpringJDBC,JdbcTemplateJdbcTemplateJDK1.4NamedParameterJdbcTemplate-JdbcTemplateJDBC“?”SQLJDK1.4SimpleJdbcTemplate - JdbcTemplateNamedParameterJdbcTemplateJava5varargsautoboxingAPIJava5SimpleJdbcInsertSimpleJdbcCall -MapMapkeySimpleJdbcTemplateJDK5RDBMS MappingSqlQuery, SqlUpdate and StoredProcedure -QueryJDK1.4

11.1.2.SpringJDBC

SpringFrameworkJDBC core dataSourceobjectsupport

org.springframework.jdbc.coreJdbcTemplatecallbackinterfaceorg.springframework.jdbc.core.simple SimpleJdbcTemplateSimpleJdbcInsert SimpleJdbcCallorg.springframework.jdbc.core.namedparamNamedParameterJdbcTemplateorg.springframework.jdbc.datasourceDataSource DataSourceJ2EE JNDI

org.springframework.jdbc.objectRDBMSJDOJDBC org.springframework.jdbc.coreJDBC

org.springframework.jdbc.supportSQLException

JDBC org.springframework.daoSpringJDBCJDBCRDBMSunchecked

11.2.JDBCJDBC

11.2.1.JdbcTemplateJdbcTemplatecoreJDBCSQL SQL

JdbcTemplate PreparedStatementCreator

PreparedStatementSQL CallableStatementCreateor

CallableStatement RowCallbackHandler

DAO DataSourceJdbcTemplateSpringIoCJdbcTemplatebeanDAODataSourceSpringIoCbean DataSourcebeanservice DataSourcebeanJdbcTemplatebeanJdbcTemplateSQL“DEBUG”categoryJdbcTemplate

11.2.1.1.JdbcTemplate JdbcTemplateJavadoc

11.2.1.1.1.SELECT

introwCount=this.jdbcTemplate.queryForInt("selectcount(0)fromt_accrual");

intcountOfActorsNamedJoe=this.jdbcTemplate.queryForInt(

"selectcount(0)fromt_actorswherefirst_name=?",newObject[]{"Joe"});

String

Stringsurname=(String)this.jdbcTemplate.queryForObject(

"selectsurnamefromt_actorwhereid=?",

newObject[]{newLong(1212)},String.class);

Actoractor=(Actor)this.jdbcTemplate.queryForObject(

"selectfirst_name,surnamefromt_actorwhereid=?",

newObject[]{newLong(1212)},

newRowMapper(){

publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{

Actoractor=newActor();

actor.setFirstName(rs.getString("first_name"));

actor.setSurname(rs.getString("surname"));

returnactor;

}

});

Collectionactors=this.jdbcTemplate.query(

"selectfirst_name,surnamefromt_actor",

newRowMapper(){

publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{

Actoractor=newActor();

actor.setFirstName(rs.getString("first_name"));

actor.setSurname(rs.getString("surname"));

returnactor;

}

});

2 RowMapper

publicCollectionfindAllActors(){

returnthis.jdbcTemplate.query("selectfirst_name,surnamefromt_actor",newActorMapper());

}

privatestaticfinalclassActorMapperimplementsRowMapper{

publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{

Actoractor=newActor();

actor.setFirstName(rs.getString("first_name"));

actor.setSurname(rs.getString("surname"));

returnactor;

}

}

11.2.1.1.2.INSERT/UPDATE/DELETE

this.jdbcTemplate.update(

"insertintot_actor(first_name,surname)values(?,?)",

newObject[]{"Leonor","Watling"});

this.jdbcTemplate.update(

"updatet_actorsetweapon=?whereid=?",

newObject[]{"Banjo",newLong(5276)});

this.jdbcTemplate.update(

"deletefromactorwhereid=?",

newObject[]{newLong.valueOf(actorId)});

11.2.1.1.3.

execute(..)SQLDDL

this.jdbcTemplate.execute("createtablemytable(idinteger,namevarchar(100))");

this.jdbcTemplate.update(

"callSUPPORT.REFRESH_ACTORS_SUMMARY(?)",

newObject[]{Long.valueOf(unionId)});

11.2.1.2.JdbcTemplateJdbcTemplate JdbcTemplate“”“”DAOJdbcTemplate DataSourceJdbcTemplate SimpleJdbcTemplateNamedParameterJdbcTemplateSpringDataSource DataSourceDAO JdbcTemplateDataSourcesetter

DAO

publicclassJdbcCorporateEventDaoimplementsCorporateEventDao{

privateJdbcTemplatejdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.jdbcTemplate=newJdbcTemplate(dataSource);

}

//JDBC-backedimplementationsofthemethodsontheCorporateEventDao

}

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<beanid="corporateEventDao"class="com.example.JdbcCorporateEventDao">

<propertyname="dataSource"ref="dataSource"/>

</bean>

<!--theDataSource(parameterizedforconfigurationviaa

<beanid="dataSource"destroy-method="close"class="org.apache.commons.dbcp.BasicDataSource">

<propertyname="driverClassName"value="${jdbc.driverClassName}"/>

<propertyname="url"value="${jdbc.url}"/>

<propertyname="username"value="${jdbc.username}"/>

<propertyname="password"value="${jdbc.password}"/>

</bean>

</beans>

Spring JdbcDaoSupportJDBCDAO JdbcDaoSupportsetDataSource(..)

DAOSQL JdbcTemplate

DataSourcesJdbcTemplates

11.2.2.NamedParameterJdbcTemplateNamedParameterJdbcTemplateJDBC '?' NamedParameterJdbcTemplate

JdbcTemplate JdbcTemplate NamedParameterJdbcTemplate

JdbcTemplateJDBC

//someJDBC-backedDAOclass...

privateNamedParameterJdbcTemplatenamedParameterJdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.namedParameterJdbcTemplate=newNamedParameterJdbcTemplate(dataSource);

}

publicintcountOfActorsByFirstName(StringfirstName){

Stringsql="selectcount(0)fromT_ACTORwherefirst_name=:first_name";

SqlParameterSourcenamedParameters=newMapSqlParameterSource("first_name",firstName);

returnnamedParameterJdbcTemplate.queryForInt(sql,namedParameters);

}

'sql' 'namedParameters' MapSqlParameterSource

Map NamedParameterJdbcTemplate

NamedParameterJdbcOperationsNamedParameterJdbcTemplate

//someJDBC-backedDAOclass...

privateNamedParameterJdbcTemplatenamedParameterJdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.namedParameterJdbcTemplate=newNamedParameterJdbcTemplate(dataSource);

}

publicintcountOfActorsByFirstName(StringfirstName){

Stringsql="selectcount(0)fromT_ACTORwherefirst_name=:first_name";

MapnamedParameters=Collections.singletonMap("first_name",firstName);

returnthis.namedParameterJdbcTemplate.queryForInt(sql,namedParameters);

}

NamedParameterJdbcTemplateSqlParameterSource()MapSqlParameterSource SqlParameterSourceNamedParameterJdbcTemplate MapSqlParameterSource java.util.Map

MapKeyMapValueSqlParameterSourceBeanPropertySqlParameterSourceJava JavaBean

JavaBean

publicclassActor{

privateLongid;

privateStringfirstName;

privateStringlastName;

publicStringgetFirstName(){

returnthis.firstName;

}

publicStringgetLastName(){

returnthis.lastName;

}

publicLonggetId(){

returnthis.id;

}

//settersomitted...

}

//someJDBC-backedDAOclass...

privateNamedParameterJdbcTemplatenamedParameterJdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.namedParameterJdbcTemplate=newNamedParameterJdbcTemplate(dataSource);

}

publicintcountOfActors(ActorexampleActor){

//noticehowthenamedparametersmatchthepropertiesoftheabove'

Stringsql="selectcount(0)fromT_ACTORwherefirst_name=:firstNameandlast_name=:lastName";

SqlParameterSourcenamedParameters=newBeanPropertySqlParameterSource(exampleActor);

returnthis.namedParameterJdbcTemplate.queryForInt(sql,namedParameters);

}

NamedParameterJdbcTemplateJdbcTemplateJdbcTemplate getJdbcOperations()

11.2.1.2“ JdbcTemplate” NamedParameterJdbcTemplate

11.2.3.SimpleJdbcTemplate

SimpleJdbcTemplateJava5SimpleJdbcTemplateJdbcTemplateJava5varargsautoboxingSimpleJdbcTemplateJava5Java5Java5JDK“beforeandafter”SimpleJdbcTemplateSimpleJdbcTemplate

//classicJdbcTemplate-style...

privateJdbcTemplatejdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.jdbcTemplate=newJdbcTemplate(dataSource);

}

publicActorfindActor(longid){

Stringsql="selectid,first_name,last_namefromT_ACTORwhereid=?";

RowMappermapper=newRowMapper(){

publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{

Actoractor=newActor();

actor.setId(rs.getLong("id"));

actor.setFirstName(rs.getString("first_name"));

actor.setLastName(rs.getString("last_name"));

returnactor;

}

};

//noticethecast,thewrappingupofthe'id'argument

//inanarray,andtheboxingofthe'id'argumentasareferencetype

return(Actor)jdbcTemplate.queryForObject(sql,mapper,newObject[]{Long.valueOf(id)});

}

SimpleJdbcTemplate“”

//SimpleJdbcTemplate-style...

privateSimpleJdbcTemplatesimpleJdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

}

publicActorfindActor(longid){

Stringsql="selectid,first_name,last_namefromT_ACTORwhereid=?";

ParameterizedRowMapper<Actor>mapper=newParameterizedRowMapper<Actor>(){

//noticethereturntypewithrespecttoJava5covariantreturntypes

publicActormapRow(ResultSetrs,introwNum)throwsSQLException{

Actoractor=newActor();

actor.setId(rs.getLong("id"));

actor.setFirstName(rs.getString("first_name"));

actor.setLastName(rs.getString("last_name"));

returnactor;

}

};

returnthis.simpleJdbcTemplate.queryForObject(sql,mapper,id);

}

11.2.1.2“ JdbcTemplate” SimpleJdbcTemplate

SimpleJdbcTemplateJdbcTemplate JdbcTemplate

SimpleJdbcTemplate getJdbcOperations()

JdbcOperations

11.2.4.DataSourceSpring DataSourceContainerFrameworkSpringJDBCJNDISpringDataSourceWebDriverManagerDataSourceDataSource DriverManagerDataSource

JDBC JDBC DriverManager

DriverManagerDataSource

DriverManagerDataSourcedataSource=newDriverManagerDataSource();

dataSource.setDriverClassName("org.hsqldb.jdbcDriver");

dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");

dataSource.setUsername("sa");

dataSource.setPassword("");

11.2.5.SQLExceptionTranslatorSQLExceptionTranslator SQLException

org.springframework.dao.DataAccessException (JDBCSQLStatecode)OracleerrorcodeSQLErrorCodeSQLExceptionTranslatorSQLExceptionTranslator errorcode SQLStateJavaBean SQLErrorCodeserrorcode JavaBeanSQLErrorCodesFactory “sql-error-codes.xml”DatabaseProductNameSQLErrorCodeSQLExceptionTranslator

SQLErrorCodeSQLExceptionTranslator

SQLExceptionerrorcodeerrorcodeclasspathsql-error-codes.xmlmetadatadatabasenamefallback SQLStateSQLExceptionTranslatorfallback

SQLErrorCodeSQLExceptionTranslator

publicclassMySQLErrorCodesTranslatorextendsSQLErrorCodeSQLExceptionTranslator{

protectedDataAccessExceptioncustomTranslate(Stringtask,Stringsql,SQLExceptionsqlex){

if(sqlex.getErrorCode()==-12345){

returnnewDeadlockLoserDataAccessException(task,sqlex);

}

returnnull;

}

}

errorcode '-12345'SQLExceptionerrorcodesetExceptionTranslator JdbcTemplate

//createaJdbcTemplateandsetdatasource

JdbcTemplatejt=newJdbcTemplate();

jt.setDataSource(dataSource);

//createacustomtranslatorandsettheDataSourceforthedefaulttranslationlookup

MySQLErrorCodesTransalatortr=newMySQLErrorCodesTransalator();

tr.setDataSource(dataSource);

jt.setExceptionTranslator(tr);

//usetheJdbcTemplateforthisSqlUpdate

SqlUpdatesu=newSqlUpdate();

su.setJdbcTemplate(jt);

su.setSql("updateorderssetshipping_charge=shipping_charge*1.05");

su.compile();

su.update();

sql-error-codes.xml

11.2.6.SQLSQL DataSourceJdbcTemplate

importjavax.sql.DataSource;

importorg.springframework.jdbc.core.JdbcTemplate;

publicclassExecuteAStatement{

privateJdbcTemplatejdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.jdbcTemplate=newJdbcTemplate(dataSource);

}

publicvoiddoExecute(){

this.jdbcTemplate.execute("createtablemytable(idinteger,namevarchar(100))");

}

}

11.2.7.execute JdbcTemplate countqueryForLong(..)queryForObject(..) queryForObjectJDBCJavaInvalidDataAccessApiUsageException

importjavax.sql.DataSource;

importorg.springframework.jdbc.core.JdbcTemplate;

publicclassRunAQuery{

privateJdbcTemplatejdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.jdbcTemplate=newJdbcTemplate(dataSource);

}

publicintgetCount(){

returnthis.jdbcTemplate.queryForInt("selectcount(*)frommytable");

}

publicStringgetName(){

return(String)this.jdbcTemplate.queryForObject("selectnamefrommytable",String.class);

}

publicvoidsetDataSource(DataSourcedataSource){

this.dataSource=dataSource;

}

}

JdbcTemplateList List

privateJdbcTemplatejdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.jdbcTemplate=newJdbcTemplate(dataSource);

}

publicListgetList(){

returnthis.jdbcTemplate.queryForList("select*frommytable");

}

[{name=Bob,id=1},{name=Mary,id=2}]

11.2.8.JdbcTemplate

importjavax.sql.DataSource;

importorg.springframework.jdbc.core.JdbcTemplate;

publicclassExecuteAnUpdate{

privateJdbcTemplatejdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.jdbcTemplate=newJdbcTemplate(dataSource);

}

publicvoidsetName(intid,Stringname){

this.jdbcTemplate.update(

"updatemytablesetname=?whereid=?",

newObject[]{name,newInteger(id)});

}

}

11.2.9.JdbcTemplateupdateJDBC3.0-13.6PreparedStatementCreatorInsert KeyHolderupdatePreparedStatementOracle

finalStringINSERT_SQL="insertintomy_test(name)values(?)";

finalStringname="Rob";

KeyHolderkeyHolder=newGeneratedKeyHolder();

jdbcTemplate.update(

newPreparedStatementCreator(){

publicPreparedStatementcreatePreparedStatement(Connectionconnection)throwsSQLException{

PreparedStatementps=

connection.prepareStatement(INSERT_SQL,newString[]{"id"});

ps.setString(1,name);

returnps;

}

},

keyHolder);

//keyHolder.getKey()nowcontainsthegeneratedkey

11.3.

11.3.1.DataSourceUtilsDataSourceUtils JNDI

11.3.2.SmartDataSourceSmartDataSourceDataSource

11.3.3.AbstractDataSourceAbstractDataSourceDataSource abstract DataSource

11.3.4.SingleConnectionDataSourceSingleConnectionDataSourceSmartDataSourcecloseConnectionSingleConnectionDataSourceJNDI

11.3.5.DriverManagerDataSourceDriverManagerDataSourceSmartDataSourcebeanpropertiesJDBCDriver

J2EEapplicationcontextConnection.close() DataSourceJavaBean

DriverManagerDataSource

11.3.6.TransactionAwareDataSourceProxyTransactionAwareDataSourceProxyDataSource DataSourceSpringJ2EEJNDI DataSource

JDBC DataSource

DataSourceUtils

TransactionAwareDataSourceProxyJavaDocs

11.3.7.DataSourceTransactionManagerDataSourceTransactionManager PlatformTransactionManagerJDBCDataSourceJDBC

DataSourceUtils.getConnection(DataSource) JDBCJ2EEDataSource.getConnection unchecked org.springframework.dao

checkedSQLExceptionSpringFramework JdbcTemplate

DataSourceTransactionManagerDataSourceUtilsDataSourceTransactionManagerSQLDataSourceUtils.applyTransactionTimeout(..)

DataSourceTransactionManagerJtaTransactionManager

DataSourceTransactionManagerJTADataSourceUtils.getConnection(DataSource) JDBCJtaTransactionManager

11.3.8.NativeJdbcExtractorJDBCAPIJDBC Connection,StatementResultSetDataSource

NativeJdbcExtractorJdbcTemplateOracleLobHandler

NativeJdbcExtractorSimpleNativeJdbcExtractor

C3P0NativeJdbcExtractor

CommonsDbcpNativeJdbcExtractor

JBossNativeJdbcExtractor

WebLogicNativeJdbcExtractor

WebSphereNativeJdbcExtractor

XAPoolNativeJdbcExtractorSimpleNativeJdbcExtractor ConnectionJavaDocs

11.4.JDBCJDBCpreparedstatement

11.4.1.JdbcTemplateJdbcTemplate BatchPreparedStatementSetter,getBatchSize setValuespreparedstatementactorlist

publicclassJdbcActorDaoimplementsActorDao{

privateJdbcTemplatejdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.jdbcTemplate=newJdbcTemplate(dataSource);

}

publicint[]batchUpdate(finalListactors){

int[]updateCounts=jdbcTemplate.batchUpdate(

"updatet_actorsetfirst_name=?,last_name=?whereid=?",

newBatchPreparedStatementSetter(){

publicvoidsetValues(PreparedStatementps,inti)throwsSQLException{

ps.setString(1,((Actor)actors.get(i)).getFirstName());

ps.setString(2,((Actor)actors.get(i)).getLastName());

ps.setLong(3,((Actor)actors.get(i)).getId().longValue());

}

publicintgetBatchSize(){

returnactors.size();

}

});

returnupdateCounts;

}

//...additionalmethods

}

isBatchExhausted

11.4.2.SimpleJdbcTemplateSimpleJdbcTemplatepreparedstatementAPISqlParameterSource, SqlParameterSource.createBatch

JavaBeanMap

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

}

publicint[]batchUpdate(finalList<Actor>actors){

SqlParameterSource[]batch=SqlParameterSourceUtils.createBatch(actors.toArray());

int[]updateCounts=simpleJdbcTemplate.batchUpdate(

"updatet_actorsetfirst_name=:firstName,last_name=:lastNamewhereid=:id",

batch);

returnupdateCounts;

}

//...additionalmethods

}

“?”ListSQLStatementSQLStatement“?”

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

}

publicint[]batchUpdate(finalList<Actor>actors){

List<Object[]>batch=newArrayList<Object[]>();

for(Actoractor:actors){

Object[]values=newObject[]{

actor.getFirstName(),

actor.getLastName(),

actor.getId()};

batch.add(values);

}

int[]updateCounts=simpleJdbcTemplate.batchUpdate(

"updatet_actorsetfirst_name=?,last_name=?whereid=?",

batch);

returnupdateCounts;

}

//...additionalmethods

}

int JDBCJDBC-2

11.5.SimpleJdbcJDBCSimpleJdbcInsertSimpleJdbcCallJDBC

11.5.1.SimpleJdbcInsertSimpleJdbcInsert SimpleJdbcInsert

SimpleJdbcInsert withTableNametable “fluid”SimpleJdbcInsert

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

privateSimpleJdbcInsertinsertActor;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

this.insertActor=

newSimpleJdbcInsert(dataSource).withTableName("t_actor");

}

publicvoidadd(Actoractor){

Map<String,Object>parameters=newHashMap<String,Object>(3);

parameters.put("id",actor.getId());

parameters.put("first_name",actor.getFirstName());

parameters.put("last_name",actor.getLastName());

insertActor.execute(parameters);

}

//...additionalmethods

}

java.utils.Map MapkeyInsert

11.5.2.SimpleJdbcInsertidActor

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

privateSimpleJdbcInsertinsertActor;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

this.insertActor=

newSimpleJdbcInsert(dataSource)

.withTableName("t_actor")

.usingGeneratedKeyColumns("id");

}

publicvoidadd(Actoractor){

Map<String,Object>parameters=newHashMap<String,Object>(2);

parameters.put("first_name",actor.getFirstName());

parameters.put("last_name",actor.getLastName());

NumbernewId=insertActor.executeAndReturnKey(parameters);

actor.setId(newId.longValue());

}

//...additionalmethods

}

insertidMapJava java.lang.Number

11.5.3.SimpleJdbcInsertSimpleJdbcInsertinsert

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

privateSimpleJdbcInsertinsertActor;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

this.insertActor=

newSimpleJdbcInsert(dataSource)

.withTableName("t_actor")

.usingColumns("first_name","last_name")

.usingGeneratedKeyColumns("id");

}

publicvoidadd(Actoractor){

Map<String,Object>parameters=newHashMap<String,Object>(2);

parameters.put("first_name",actor.getFirstName());

parameters.put("last_name",actor.getLastName());

NumbernewId=insertActor.executeAndReturnKey(parameters);

actor.setId(newId.longValue());

}

//...additionalmethods

}

insert

11.5.4.SqlParameterSourceMapSpring SqlParameterSourceBeanPropertySqlParameterSourceJavaBeangetter

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

privateSimpleJdbcInsertinsertActor;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

this.insertActor=

newSimpleJdbcInsert(dataSource)

.withTableName("t_actor")

.usingGeneratedKeyColumns("id");

}

publicvoidadd(Actoractor){

SqlParameterSourceparameters=newBeanPropertySqlParameterSource(actor);

NumbernewId=insertActor.executeAndReturnKey(parameters);

actor.setId(newId.longValue());

}

//...additionalmethods

}

MapSqlParameterSourceMap addValue

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

privateSimpleJdbcInsertinsertActor;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

this.insertActor=

newSimpleJdbcInsert(dataSource)

.withTableName("t_actor")

.usingGeneratedKeyColumns("id");

}

publicvoidadd(Actoractor){

SqlParameterSourceparameters=newMapSqlParameterSource()

.addValue("first_name",actor.getFirstName())

.addValue("last_name",actor.getLastName());

NumbernewId=insertActor.executeAndReturnKey(parameters);

actor.setId(newId.longValue());

}

//...additionalmethods

}

11.5.5.SimpleJdbcCall SimpleJdbcCall VARCHARDATEfirst_namelast_namebirth_date MySQL

CREATEPROCEDUREread_actor(

INin_idINTEGER,

OUTout_first_nameVARCHAR(100),

OUTout_last_nameVARCHAR(100),

OUTout_birth_dateDATE)

BEGIN

SELECTfirst_name,last_name,birth_date

INTOout_first_name,out_last_name,out_birth_date

FROMt_actorwhereid=in_id;

END;

“in_id”ActorSimpleJdbcCallSimpleJdbcInsert

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

privateSimpleJdbcCallprocReadActor;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

this.procReadActor=

newSimpleJdbcCall(dataSource)

.withProcedureName("read_actor");

}

publicActorreadActor(Longid){

SqlParameterSourcein=newMapSqlParameterSource()

.addValue("in_id",id);

Mapout=procReadActor.execute(in);

Actoractor=newActor();

actor.setId(id);

actor.setFirstName((String)out.get("out_first_name"));

actor.setLastName((String)out.get("out_last_name"));

actor.setBirthDate((Date)out.get("out_birth_date"));

returnactor;

}

//...additionalmethods

}

SimpleJdbcCall SqlParameterSourceexecuteMapMapkeyout_birth_date

executeActor MapkeyCaseInsensitiveMap JdbcTemplate setResultsMapCaseInsensitive

True JdbcTemplateSimpleJdbcCall commons-collections.jar

classpath

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcCallprocReadActor;

publicvoidsetDataSource(DataSourcedataSource){

JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);

jdbcTemplate.setResultsMapCaseInsensitive(true);

this.procReadActor=

newSimpleJdbcCall(jdbcTemplate)

.withProcedureName("read_actor");

}

//...additionalmethods

}

11.5.6.SimpleJdbcCallSimpleJdbcCall declareParameters SqlParameter

SqlParameter

useInParameterNames

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcCallprocReadActor;

publicvoidsetDataSource(DataSourcedataSource){

JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);

jdbcTemplate.setResultsMapCaseInsensitive(true);

this.procReadActor=

newSimpleJdbcCall(jdbcTemplate)

.withProcedureName("read_actor")

.withoutProcedureColumnMetaDataAccess()

.useInParameterNames("in_id")

.declareParameters(

newSqlParameter("in_id",Types.NUMERIC),

newSqlOutParameter("out_first_name",Types.VARCHAR),

newSqlOutParameter("out_last_name",Types.VARCHAR),

newSqlOutParameter("out_birth_date",Types.DATE)

);

}

//...additionalmethods

}

ServerOracleSybaseMySQLMicrosoftSQLServerOracle

11.5.7.SqlParametersSimpleJdbcRDBMS SqlParameterjava.sql.Types

newSqlParameter("in_id",Types.NUMERIC),

newSqlOutParameter("out_first_name",Types.VARCHAR),

SqlParameter SqlQuery

SqlOutParameter SqlInOutParameterSQLnumeric

11.5.8.SimpleJdbcCallMap executeObject

CREATEFUNCTIONget_actor_name(in_idINTEGER)

RETURNSVARCHAR(200)READSSQLDATA

BEGIN

DECLAREout_nameVARCHAR(200);

SELECTconcat(first_name,'',last_name)

INTOout_name

FROMt_actorwhereid=in_id;

RETURNout_name;

END;

SimpleJdbcCall

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

privateSimpleJdbcCallfuncGetActorName;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);

jdbcTemplate.setResultsMapCaseInsensitive(true);

this.funcGetActorName=

newSimpleJdbcCall(jdbcTemplate)

.withFunctionName("get_actor_name");

}

publicStringgetActorName(Longid){

SqlParameterSourcein=newMapSqlParameterSource()

.addValue("in_id",id);

Stringname=funcGetActorName.executeFunction(String.class,in);

returnname;

}

//...additionalmethods

}

String

11.5.9.SimpleJdbcCallResultSet/REFCursorResultSetJDBCreturningResultSet RowMappert_actorMySQL

CREATEPROCEDUREread_all_actors()

BEGIN

SELECTa.id,a.first_name,a.last_name,a.birth_dateFROMt_actora;

END;

RowMapperJavaBean ParameterizedBeanPropertyRowMapper

classnewInstance

publicclassJdbcActorDaoimplementsActorDao{

privateSimpleJdbcTemplatesimpleJdbcTemplate;

privateSimpleJdbcCallprocReadAllActors;

publicvoidsetDataSource(DataSourcedataSource){

this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);

JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);

jdbcTemplate.setResultsMapCaseInsensitive(true);

this.procReadAllActors=

newSimpleJdbcCall(jdbcTemplate)

.withProcedureName("read_all_actors")

.returningResultSet("actors",

ParameterizedBeanPropertyRowMapper.newInstance(Actor.class));

}

publicListgetActorsList(){

Mapm=procReadAllActors.execute(newHashMap<String,Object>(0));

return(List)m.get("actors");

}

//...additionalmethods

}

MapActors

11.6.JavaJDBCorg.springframework.jdbc.object list

SpringRDBMS StoredProcedure

JdbcTemplate

RDBMS

11.6.1.SqlQuerySqlQuerySQL newResultReader()

MappingSqlQueryJava SqlQueryUpdatableSqlQuery

11.6.2.MappingSqlQueryMappingSqlQuery mapRow(ResultSet,int)

privateclassCustomerMappingQueryextendsMappingSqlQuery{

publicCustomerMappingQuery(DataSourceds){

super(ds,"SELECTid,nameFROMcustomerWHEREid=?");

super.declareParameter(newSqlParameter("id",Types.INTEGER));

compile();

}

publicObjectmapRow(ResultSetrs,introwNumber)throwsSQLException{

Customercust=newCustomer();

cust.setId((Integer)rs.getObject("id"));

cust.setName(rs.getString("name"));

returncust;

}

}

DataSourcedeclareParameter SqlParametercompile()SQL

publicCustomergetCustomer(Integerid){

CustomerMappingQuerycustQry=newCustomerMappingQuery(dataSource);

Object[]parms=newObject[1];

parms[0]=id;

Listcustomers=custQry.execute(parms);

if(customers.size()>0){

return(Customer)customers.get(0);

}

else{

returnnull;

}

}

getCustomeridCustomerMappingQueryexecute ListList Customer

11.6.3.SqlUpdateSqlUpdateSQL RdbmsOperationSqlUpdateSQLSqlQuery execute() SqlUpdateSQL

importjava.sql.Types;

importjavax.sql.DataSource;

importorg.springframework.jdbc.core.SqlParameter;

importorg.springframework.jdbc.object.SqlUpdate;

publicclassUpdateCreditRatingextendsSqlUpdate{

publicUpdateCreditRating(DataSourceds){

setDataSource(ds);

setSql("updatecustomersetcredit_rating=?whereid=?");

declareParameter(newSqlParameter(Types.NUMERIC));

declareParameter(newSqlParameter(Types.NUMERIC));

compile();

}

/**

*@paramidfortheCustomertobeupdated

*@paramratingthenewvalueforcreditrating

*@returnnumberofrowsupdated

*/

publicintrun(intid,intrating){

Object[]params=

newObject[]{

newInteger(rating),

newInteger(id)};

returnupdate(params);

}

}

11.6.4.StoredProcedureStoredProcedureRDBMS execute(..)

sqlRDBMS JDBC3.0JDBC3.0Oracle sysdate() StoredProcedure

execute()mapmapentrykeyvalue

importjava.sql.Types;

importjava.util.HashMap;

importjava.util.Iterator;

importjava.util.Map;

importjavax.sql.DataSource;

importorg.springframework.jdbc.core.SqlOutParameter;

importorg.springframework.jdbc.datasource.*;

importorg.springframework.jdbc.object.StoredProcedure;

publicclassTestStoredProcedure{

publicstaticvoidmain(String[]args){

TestStoredProceduret=newTestStoredProcedure();

t.test();

System.out.println("Done!");

}

voidtest(){

DriverManagerDataSourceds=newDriverManagerDataSource();

ds.setDriverClassName("oracle.jdbc.OracleDriver");

ds.setUrl("jdbc:oracle:thin:@localhost:1521:mydb");

ds.setUsername("scott");

ds.setPassword("tiger");

MyStoredProceduresproc=newMyStoredProcedure(ds);

Mapresults=sproc.execute();

printMap(results);

}

privateclassMyStoredProcedureextendsStoredProcedure{

privatestaticfinalStringSQL="sysdate";

publicMyStoredProcedure(DataSourceds){

setDataSource(ds);

setFunction(true);

setSql(SQL);

declareParameter(newSqlOutParameter("date",Types.DATE));

compile();

}

publicMapexecute(){

//the'sysdate'sprochasnoinputparameters,soanemptyMapissupplied...

returnexecute(newHashMap());

}

}

privatestaticvoidprintMap(Mapresults){

for(Iteratorit=results.entrySet().iterator();it.hasNext();){

System.out.println(it.next());

}

}

}

StoredProcedureOracle

importoracle.jdbc.driver.OracleTypes;

importorg.springframework.jdbc.core.SqlOutParameter;

importorg.springframework.jdbc.object.StoredProcedure;

importjavax.sql.DataSource;

importjava.util.HashMap;

importjava.util.Map;

publicclassTitlesAndGenresStoredProcedureextendsStoredProcedure{

privatestaticfinalStringSPROC_NAME="AllTitlesAndGenres";

publicTitlesAndGenresStoredProcedure(DataSourcedataSource){

super(dataSource,SPROC_NAME);

declareParameter(newSqlOutParameter("titles",OracleTypes.CURSOR,newTitleMapper()));

declareParameter(newSqlOutParameter("genres",OracleTypes.CURSOR,newGenreMapper()));

compile();

}

publicMapexecute(){

//again,thissprochasnoinputparameters,soanemptyMapissupplied...

returnsuper.execute(newHashMap());

}

}

TitlesAndGenresStoredProcedure declareParameter(..)SqlOutParameter

RowMapperTitleMapper ResultSetTitleDomainObject

importcom.foo.sprocs.domain.Title;

importorg.springframework.jdbc.core.RowMapper;

importjava.sql.ResultSet;

importjava.sql.SQLException;

publicfinalclassTitleMapperimplementsRowMapper{

publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{

Titletitle=newTitle();

title.setId(rs.getLong("id"));

title.setName(rs.getString("name"));

returntitle;

}

}

GenreMapper ResultSetGenreDomainObject

importorg.springframework.jdbc.core.RowMapper;

importjava.sql.ResultSet;

importjava.sql.SQLException;

importcom.foo.domain.Genre;

publicfinalclassGenreMapperimplementsRowMapper{

publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{

returnnewGenre(rs.getString("name"));

}

}

RDBMS

importoracle.jdbc.driver.OracleTypes;

importorg.springframework.jdbc.core.SqlOutParameter;

importorg.springframework.jdbc.object.StoredProcedure;

importjavax.sql.DataSource;

importjava.util.HashMap;

importjava.util.Map;

publicclassTitlesAfterDateStoredProcedureextendsStoredProcedure{

privatestaticfinalStringSPROC_NAME="TitlesAfterDate";

privatestaticfinalStringCUTOFF_DATE_PARAM="cutoffDate";

publicTitlesAfterDateStoredProcedure(DataSourcedataSource){

super(dataSource,SPROC_NAME);

declareParameter(newSqlParameter(CUTOFF_DATE_PARAM,Types.DATE);

declareParameter(newSqlOutParameter("titles",OracleTypes.CURSOR,newTitleMapper()));

compile();

}

publicMapexecute(DatecutoffDate){

Mapinputs=newHashMap();

inputs.put(CUTOFF_DATE_PARAM,cutoffDate);

returnsuper.execute(inputs);

}

}

11.6.5.SqlFunctionSqlFunctionRDBMSSQL“”wrapperqueryForXxx SqlFunction JdbcTemplate

SQL“selectuser()” “selectsysdatefromdual”StoredProcedureSqlCall

SqlFunction SQLrun

publicintcountRows(){

SqlFunctionsf=newSqlFunction(dataSource,"selectcount(*)frommytable");

sf.compile();

returnsf.run();

}

11.7.SpringJDBC

11.7.1.SQLSpringSQLSQLNULL:

JdbcTemplateupdatequeryint

SqlParameterValueSQL

SqlParameterSourceBeanPropertySqlParameterSource

MapSqlParameterSource SQL

11.7.2.BLOBCLOBBLOBCLOB

LobHandlerLOB LobHandlerLobCreator

LobCreator/LobHandlerLOB

BLOB

byte[]–getBlobAsBytesandsetBlobAsBytesbyte[]–getBlobAsBytessetBlobAsBytesInputStream – getBlobAsBinaryStream andsetBlobAsBinaryStreamInputStream–getBlobAsBinaryStreamsetBlobAsBinaryStream

CLOB

String–getClobAsStringandsetClobAsStringString–getClobAsStringsetClobAsStringInputStream – getClobAsAsciiStream andsetClobAsAsciiStreamInputStream–getClobAsAsciiStreamsetClobAsAsciiStreamReader – getClobAsCharacterStream andsetClobAsCharacterStreamReader – getClobAsCharacterStream

setClobAsCharacterStreamBLOBBLOBJdbcTemplateAbstractLobCreatingPreparedStatementCallback"setValues"LobCreatorLOB“lobHandler” DefaultLobHandler

finalFileblobIn=newFile("spring2004.jpg");

finalInputStreamblobIs=newFileInputStream(blobIn);

finalFileclobIn=newFile("large.txt");

finalInputStreamclobIs=newFileInputStream(clobIn);

finalInputStreamReaderclobReader=newInputStreamReader(clobIs);

jdbcTemplate.execute(

"INSERTINTOlob_table(id,a_clob,a_blob)VALUES(?,?,?)",

newAbstractLobCreatingPreparedStatementCallback(lobhandler){

protectedvoidsetValues(PreparedStatementps,LobCreatorlobCreator)

throwsSQLException{

ps.setLong(1,1L);

lobCreator.setClobAsCharacterStream(ps,2,clobReader,(int)clobIn.length());

lobCreator.setBlobAsBinaryStream(ps,3,blobIs,(int)blobIn.length());

}

}

);

blobIs.close();

clobReader.close();

lobHandlerDefaultLobHandler

setClobAsCharacterStreamCLOB

setBlobAsBinartStreamBLOB

LOBJdbcTempate DefaultLobHandler

Listl=jdbcTemplate.query("selectid,a_clob,a_blobfromlob_table",

newRowMapper(){

publicObjectmapRow(ResultSetrs,inti)throwsSQLException{

Mapresults=newHashMap();

StringclobText=lobHandler.getClobAsString(rs,"a_clob");

results.put("CLOB",clobText);

byte[]blobBytes=lobHandler.getBlobAsBytes(rs,"a_blob");

results.put("BLOB",blobBytes);

returnresults;

}

});

getClobAsStringCLOB

getBlobAsBytesBLOB

11.7.3.INSQL"select*fromT_ACTORwhereidin(1,2,3)" SQL java.util.ListlistSQL

INJDBC100INjava.util.ListIN"select*fromT_ACTORwhere(id,

last_name)in((1,'Johnson'),(2,'Harrop'))".

11.7.4.Spring SqlReturnType SqlTypeValue

OracleSTRUCT“ITEM_TYPE”SqlOutParameter

declareParameter(newSqlOutParameter("item",OracleTypes.STRUCT,"ITEM_TYPE",

newSqlReturnType(){

publicObjectgetTypeValue(CallableStatementcs,intcolIndx,intsqlType,StringtypeName)

throwsSQLException{

STRUCTstruct=(STRUCT)cs.getObject(colIndx);

Object[]attr=struct.getAttributes();

TestItemitem=newTestItem();

item.setId(((Number)attr[0]).longValue());

item.setDescription((String)attr[1]);

item.setExpirationDate((java.util.Date)attr[2]);

returnitem;

}

}));

Java SqlTypeValueTestItem SqlTypeValue" createTypeValue

StructDescriptorArrayDescriptor

SqlTypeValuevalue=newAbstractSqlTypeValue(){

protectedObjectcreateTypeValue(Connectionconn,intsqlType,StringtypeName)throwsSQLException{

StructDescriptoritemDescriptor=newStructDescriptor(typeName,conn);

Structitem=newSTRUCT(itemDescriptor,conn,

newObject[]{

testItem.getId(),

testItem.getDescription(),

newjava.sql.Date(testItem.getExpirationDate().getTime())

});

returnitem;

}

};

SqlTypeValueMap

12ORM

12.1.12.2.Hibernate

12.2.1.12.2.2.Spring SessionFactory

12.2.3.TheHibernateTemplate12.2.4.SpringDAO12.2.5.Hibernate3APIDAO12.2.6.12.2.7.12.2.8.12.2.9.vs12.2.10.Hibernate

12.3.JDO12.3.1.PersistenceManagerFactory12.3.2.JdoTemplateJdoDaoSupport12.3.3.JDOAPIDAO12.3.4.12.3.5.JdoDialect

12.4.OracleTopLink12.4.1.SessionFactory12.4.2.TopLinkTemplateandTopLinkDaoSupport12.4.3.TopLinkAPIDAO12.4.4.

12.5.iBATISSQLMaps12.5.1.SqlMapClient12.5.2. SqlMapClientTemplate SqlMapClientDaoSupport

12.5.3.iBATISAPIDAO12.6.JPA

12.6.1.SpringJPA12.6.2.JpaTemplate JpaDaoSupport

12.6.3.JPADAO12.6.4.

12.7.12.8.JpaDialect

12.1.Spring FrameworkDAO HibernateJDOOracle TopLinkiBATISSQLMappings JPAHibernateSpringIoCHibernateO/RSpringDAOSpringDAOHibernate/JDO/TopLinkAPIDAODAOIoCSpringO/RMappingSpringSpringO/RMappingSpringSpringO/RMappinglibraryJavaBeansSpringIoCSpringSpringFrameworkO/RMappingDAO

SpringIoC Hibernate SessionFactory JDBCDataSource

SpringO/RMappingcheckedruntimeDataAccessExceptioncatch/throwJDBCDBDialectJDBC

SpringapplicationcontextHibernate SessionFactoryJDBCDataSourceiBATISSQLMapsSpringHibernateHibernateHibernate SessionSpringtemplateJavaHibernateHibernateAPIDAOJTASpringHibernate

SpringO/RMappingAOPJavatemplaterollbackHibernate/JDOJTAServiceJDBCO/RBLOBO/RMappingORM

SpringPetClinicDAOapplicationcontextJDBCHibernateOracleTopLinkJPAPetClinicSpringwebHibernateTopLinkJPAJPetStoreiBATISSQLMapsSpringWebSpringWebMVCStrutsSpringSpringO/R Mapping JDOJPOX http://www.jpox.org/Kodo http://www.bea.com/kodo

12.2.HibernateHibernate3http://www.hibernate.org/HibernateSpringSpringO/RMappingDAOSpringO/RMappingO/RMappingSpring2.5Hibernate3.1Hibernate2.1Hibernate3.0

12.2.1.SpringIoCAOPuncheckedexceptionSpringDAOJDBCSQLException DataAccessExceptionSQLSpringJTAJDBCSpringHibernateJDO HibernateTemplate / JdoTemplateJdbcTemplateHibernateInterceptor/JdoInterceptorHibernate/JDOsingletonsSpringSpringXMLSpringJavaBeanapplicationContextSpringJavaBeanstemplatetemplatewebweb

12.2.2.Spring SessionFactory

SpringSpringbeanJDBC DataSourceHibernateSessionFactoryDAOJDBC DataSourceHibernate

<beans>

<beanid="myDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<propertyname="driverClassName"value="org.hsqldb.jdbcDriver"/>

<propertyname="url"value="jdbc:hsqldb:hsql://localhost:9001"/>

<propertyname="username"value="sa"/>

<propertyname="password"value=""/>

</bean>

<beanid="mySessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<propertyname="dataSource"ref="myDataSource"/>

<propertyname="mappingResources">

<list>

<value>product.hbm.xml</value>

</list>

</property>

<propertyname="hibernateProperties">

<value>

hibernate.dialect=org.hibernate.dialect.HSQLDialect

</value>

</property>

</bean>

</beans>

JakartaCommonsDBCP BasicDataSourceJNDIDataSource:

<beans>

<beanid="myDataSource"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="java:comp/env/jdbc/myds"/>

</bean>

</beans>

Spring JndiObjectFactoryBeanJNDIHibernate SessionFactoryEJB

12.2.3.TheHibernateTemplate HibernatesetSessionFactory(..)beansetter SpringDAODAO

<beans>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="sessionFactory"ref="mySessionFactory"/>

</bean>

</beans>

publicclassProductDaoImplimplementsProductDao{

privateHibernateTemplatehibernateTemplate;

publicvoidsetSessionFactory(SessionFactorysessionFactory){

this.hibernateTemplate=newHibernateTemplate(sessionFactory);

}

publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{

returnthis.hibernateTemplate.find("fromtest.Productproductwhereproduct.category=?",category);

}

}

HibernateTemplateHibernateSession SessionHibernateTemplate

publicclassProductDaoImplimplementsProductDao{

privateHibernateTemplatehibernateTemplate;

publicvoidsetSessionFactory(SessionFactorysessionFactory){

this.hibernateTemplate=newHibernateTemplate(sessionFactory);

}

publicCollectionloadProductsByCategory(finalStringcategory)throwsDataAccessException{

returnthis.hibernateTemplate.execute(newHibernateCallback(){

publicObjectdoInHibernate(Sessionsession){

Criteriacriteria=session.createCriteria(Product.class);

criteria.add(Expression.eq("category",category));

criteria.setMaxResults(6);

returncriteria.list();

}

};

}

}

Hibernate HibernateTemplateHibernate SessionfindloadsaveOrUpdatedeleteSpring HibernateDaoSupport setSessionFactory(..)

SessionFactory getSessionFactory() getHibernateTemplate() DAO:

publicclassProductDaoImplextendsHibernateDaoSupportimplementsProductDao{

publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{

returnthis.getHibernateTemplate().find(

"fromtest.Productproductwhereproduct.category=?",category);

}

}

12.2.4.SpringDAOSpring HibernateTemplateDAODataAccessException HibernateDaoSupport SessionSessionFactoryUtils ' false

Session

publicclassHibernateProductDaoextendsHibernateDaoSupportimplementsProductDao{

publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException,MyException{

Sessionsession=getSession(false);

try{

Queryquery=session.createQuery("fromtest.Productproductwhereproduct.category=?");

query.setString(0,category);

Listresult=query.list();

if(result==null){

thrownewMyException("Nosearchresults.");

}

returnresult;

}

catch(HibernateExceptionex){

throwconvertHibernateAccessException(ex);

}

}

}

Hibernate checkedexception HibernateTemplateuncheckedexception

12.2.5.Hibernate3APIDAOHibernate3“Session”Hibernate Session SpringHibernate SessionHibernateAPIDAO

publicclassProductDaoImplimplementsProductDao{

privateSessionFactorysessionFactory;

publicvoidsetSessionFactory(SessionFactorysessionFactory){

this.sessionFactory=sessionFactory;

}

publicCollectionloadProductsByCategory(Stringcategory){

returnthis.sessionFactory.getCurrentSession()

.createQuery("fromtest.Productproductwhereproduct.category=?")

.setParameter(0,category)

.list();

}

}

HibernateDAO SessionFactory DAOHibernateHibernateUtil DAOSpring HibernateTemplateSpringIoCUnitTest: setSessionFactory(..)Springbean

<beans>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="sessionFactory"ref="mySessionFactory"/>

</bean>

</beans>

DAOHibernateAPISpringDAO HibernateExceptionuncheckedexceptionHibernate DAOSpring LocalSessionFactoryBeanSpring HibernateSessionFactory.getCurrentSession()SpringHibernateTransactionManager Session JTASpring JtaTransactionManagerEJBCMTJTA SessionDAOHibernate3APISpring

12.2.6.setTransactionManager(..) bean setProductDao productDAO

Springapplicationcontext

<beans>

<beanid="myTxManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<propertyname="sessionFactory"ref="mySessionFactory"/>

</bean>

<beanid="myProductService"class="product.ProductServiceImpl">

<propertyname="transactionManager"ref="myTxManager"/>

<propertyname="productDao"ref="myProductDao"/>

</bean>

</beans>

publicclassProductServiceImplimplementsProductService{

privateTransactionTemplatetransactionTemplate;

privateProductDaoproductDao;

publicvoidsetTransactionManager(PlatformTransactionManagertransactionManager){

this.transactionTemplate=newTransactionTemplate(transactionManager);

}

publicvoidsetProductDao(ProductDaoproductDao){

this.productDao=productDao;

}

publicvoidincreasePriceOfAllProductsInCategory(finalStringcategory){

this.transactionTemplate.execute(newTransactionCallbackWithoutResult(){

publicvoiddoInTransactionWithoutResult(TransactionStatusstatus){

ListproductsToChange=this.productDao.loadProductsByCategory(category);

//dothepriceincrease...

}

}

);

}

}

12.2.7.

SpringSpringAOPTransactionInterceptor

<beans>

<beanid="myTxManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<propertyname="sessionFactory"ref="mySessionFactory"/>

</bean>

<beanid="myProductService"class="org.springframework.aop.framework.ProxyFactoryBean">

<propertyname="proxyInterfaces"value="product.ProductService"/>

<propertyname="target">

<beanclass="product.DefaultProductService">

<propertyname="productDao"ref="myProductDao"/>

</bean>

</property>

<propertyname="interceptorNames">

<list>

<value>myTxInterceptor</value><!--thetransactioninterceptor(configuredelsewhere)-->

</list>

</property>

</bean>

</beans>

publicclassProductServiceImplimplementsProductService{

privateProductDaoproductDao;

publicvoidsetProductDao(ProductDaoproductDao){

this.productDao=productDao;

}

//noticetheabsenceoftransactiondemarcationcodeinthismethod

//Spring'sdeclarativetransactioninfrastructurewillbedemarcatingtransactionsonyourbehalf

publicvoidincreasePriceOfAllProductsInCategory(finalStringcategory){

ListproductsToChange=this.productDao.loadProductsByCategory(category);

//...

}

}

Spring TransactionInterceptorcheckedexception

TransactionTemplateuncheckedexception TransactionTemplateuncheckedexception TransactionStatusrollback-onlyTransactionInterceptorrollback ProxyFactoryBean

9.5“”

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<!--SessionFactory,DataSource,etc.omitted-->

<beanid="myTxManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">

<propertyname="sessionFactory"ref="mySessionFactory"/>

</bean>

<aop:config>

<aop:pointcutid="productServiceMethods"expression="execution(*product.ProductService.*(..))"/>

<aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/>

</aop:config>

<tx:adviceid="txAdvice"transaction-manager="myTxManager">

<tx:attributes>

<tx:methodname="increasePrice*"propagation="REQUIRED"/>

<tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/>

<tx:methodname="*"propagation="SUPPORTS"read-only="true"/>

</tx:attributes>

</tx:advice>

<beanid="myProductService"class="product.SimpleProductService">

<propertyname="productDao"ref="myProductDao"/>

</bean>

</beans>

12.2.8.TransactionTemplate TransactionInterceptorPlatformTransactionManager HibernateHibernateTransactionManagerHibernate SessionFactoryThreadLocal Session JtaTransactionManagerJTAPlatformTransactionManagerHibernateJTAHibernateJTAAPIHibernate SessionFacotry JtaTransactionManagerLocalSessionFactoryBeanDAObean SessionFactoryJDBC JtaTransactionManagerDAOsessionfactories

<beans>

<beanid="myDataSource1"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiNamevalue="java:comp/env/jdbc/myds1"/>

</bean>

<beanid="myDataSource2"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="java:comp/env/jdbc/myds2"/>

</bean>

<beanid="mySessionFactory1"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<propertyname="dataSource"ref="myDataSource1"/>

<propertyname="mappingResources">

<list>

<value>product.hbm.xml</value>

</list>

</property>

<propertyname="hibernateProperties">

<value>

hibernate.dialect=org.hibernate.dialect.MySQLDialect

hibernate.show_sql=true

</value>

</property>

</bean>

<beanid="mySessionFactory2"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<propertyname="dataSource"ref="myDataSource2"/>

<propertyname="mappingResources">

<list>

<value>inventory.hbm.xml</value>

</list>

</property>

<propertyname="hibernateProperties">

<value>

hibernate.dialect=org.hibernate.dialect.OracleDialect

</value>

</property>

</bean>

<beanid="myTxManager"class="org.springframework.transaction.jta.JtaTransactionManager"/>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="sessionFactory"ref="mySessionFactory1"/>

</bean>

<beanid="myInventoryDao"class="product.InventoryDaoImpl">

<propertyname="sessionFactory"ref="mySessionFactory2"/>

</bean>

<!--thisshowstheSpring1.xstyleofdeclarativetransactionconfiguration-->

<!--itistotallysupported,100%legalinSpring2.x,butseealsoaboveforthesleeker,Spring2.0style-->

<beanid="myProductService"

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<propertyname="transactionManager"ref="myTxManager"/>

<propertyname="target">

<beanclass="product.ProductServiceImpl">

<propertyname="productDao"ref="myProductDao"/>

<propertyname="inventoryDao"ref="myInventoryDao"/>

</bean>

</property>

<propertyname="transactionAttributes">

<props>

<propkey="increasePrice*">PROPAGATION_REQUIRED</prop>

<propkey="someOtherBusinessMethod">PROPAGATION_REQUIRES_NEW</prop>

<propkey="*">PROPAGATION_SUPPORTS,readOnly</prop>

</props>

</property>

</bean>

</beans>

HibernateTransactionManager JtaTransactionManagerJVMHibernateJCAEJB DataSourceHibernateTransactionManagerJDBCHibernateConnectionHibernate/JDBCJTAHibernateJDBC DataSourceSessionFactoryLocalSessionFactoryBean “dataSource”HibernateTransactionManager“dataSource” DataSource

12.2.9.vsSpringJNDI SessionFactory SessionFactorySessionFactoryJNDI SessionFactory HibernateJCASessionFactoryJ2EESpringJTAJTAJ2EEJTAJTAJNDI DataSource

HibernateJCAHibernate TransactionManagerLookupJVMSpring SessionFactoryJDBC DataSourceJCAJCA SpringWebWebLogicExpressJCAJ2EEWebJTAJCAEJBTomcatResinJettyEJB SessionFactory Spring HibernateTransactionManagerJtaTransactionManagerJVMJCAHibernateJNDIEJB

12.2.10.Hibernate XADataSourceJTAWebLogicWebSphereHibernateJTAPlatformTransactionManager

java.sql.SQLException:Thetransactionisnolongeractive-status:'Committed'.

NofurtherJDBCaccessisallowedwithinthistransaction.

HibernateJTA PlatformTransactionManagerSpring

application contextJTA PlatformTransactionManager

JndiObjectFactoryBeanJNDISpring JtaTransactionManagerbean LocalSessionFactoryBean jtaTransactionManagerSpringHibernateJTA PlatformTransactionManager SpringJtaTransactionManagerHibernateTransactionManagerLookup

HibernateJTA PlatformTransactionManagerHibernateJTAPlatformTransactionManagerJTA

JTA

Spring JtaTransactionManager JTAJTA afterCompletion

SpringHibernateHibernate afterTransactionCompletionHibernateHibernateSession close()

ConnectionConnection.close()

HibernateJTA PlatformTransactionManagerJTA

JTA

Spring JtaTransactionManagerJTAJTA beforeCompletion

SpringHibernateJTATransactionSpringJTA

HibernateJTAtransactionJTA afterCompletion

12.3.JDOSpringJDO1.0/2.0APISpringHibernateorg.springframework.orm.jdo

12.3.1. PersistenceManagerFactory

Spring LocalPersistenceManagerFactoryBeanSpringapplicationcontextJDO PersistenceManagerFactory

<beans>

<beanid="myPmf"class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">

<propertyname="configLocation"value="classpath:kodo.properties"/>

</bean>

</beans>

PersistenceManagerFactory PersistenceManagerFactory JDOPersistenceManagerFactoryJavaBeansJDBC DataSourceSpringbean SpringJDBC DataSourceconnectionFactorybeanJDOJPOX http://www.jpox.org

<beans>

<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<propertyname="driverClassName"value="${jdbc.driverClassName}"/>

<propertyname="url"value="${jdbc.url}"/>

<propertyname="username"value="${jdbc.username}"/>

<propertyname="password"value="${jdbc.password}"/>

</bean>

<beanid="myPmf"class="org.jpox.PersistenceManagerFactoryImpl"destroy-method="close">

<propertyname="connectionFactory"ref="dataSource"/>

<propertyname="nontransactionalRead"value="true"/>

</bean>

</beans>

JDO PersistenceManagerFactoryJ2EEJNDI

JndiObjectFactoryBean PersistenceManagerFactoryEJBJNDIPersistenceManagerFactory

12.3.2.JdoTemplateJdoDaoSupportJDODAOIoC PersistenceManagerFactoryDAOPersistenceManagerFactoryJDOAPI Spring

<beans>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="persistenceManagerFactory"ref="myPmf"/>

</bean>

</beans>

publicclassProductDaoImplimplementsProductDao{

privateJdoTemplatejdoTemplate;

publicvoidsetPersistenceManagerFactory(PersistenceManagerFactorypmf){

this.jdoTemplate=newJdoTemplate(pmf);

}

publicCollectionloadProductsByCategory(finalStringcategory)throwsDataAccessException{

return(Collection)this.jdoTemplate.execute(newJdoCallback(){

publicObjectdoInJdo(PersistenceManagerpm)throwsJDOException{

Queryquery=pm.newQuery(Product.class,"category=pCategory");

query.declareParameters("StringpCategory");

Listresult=query.execute(category);

//dosomefurtherstuffwiththeresultlist

returnresult;

}

});

}

}

JDO JdoTemplate PersistenceManager

findloadmakePersistent delete JdoTemplate JdoDaoSupport setPersistenceManagerFactory(..)PersistenceManagerFactory getPersistenceManagerFactory()

getJdoTemplate() DAO

publicclassProductDaoImplextendsJdoDaoSupportimplementsProductDao{

publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{

returngetJdoTemplate().find(

Product.class,"category=pCategory","Stringcategory",newObject[]{category});

}

}

Spring JdoTemplateDAOJDOAPISpringDAOPersistenceManagerHibernatecheckedexceptions PersistenceManager

12.3.3.JDOAPIDAOJDOAPIDAO PersistenceManagerFactorySpring DAO

publicclassProductDaoImplimplementsProductDao{

privatePersistenceManagerFactorypersistenceManagerFactory;

publicvoidsetPersistenceManagerFactory(PersistenceManagerFactorypmf){

this.persistenceManagerFactory=pmf;

}

publicCollectionloadProductsByCategory(Stringcategory){

PersistenceManagerpm=this.persistenceManagerFactory.getPersistenceManager();

try{

Queryquery=pm.newQuery(Product.class,"category=pCategory");

query.declareParameters("StringpCategory");

returnquery.execute(category);

}

finally{

pm.close();

}

}

}

DAOIoCSpring JdoTemplateSpring

<beans>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="persistenceManagerFactory"ref="myPmf"/>

</bean>

</beans>

DAO PersistenceManagerSpringPersistenceManagerFactory TransactionAwarePersistenceManagerFactoryProxySpring DAO

<beans>

<beanid="myPmfProxy"

class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">

<propertyname="targetPersistenceManagerFactory"ref="myPmf"/>

</bean>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="persistenceManagerFactory"ref="myPmfProxy"/>

</bean>

</beans>

PersistenceManagerFactory.getPersistenceManager()

PersistenceManager PersistenceManager

PersistenceManagerclose()

publicclassProductDaoImplimplementsProductDao{

privatePersistenceManagerFactorypersistenceManagerFactory;

publicvoidsetPersistenceManagerFactory(PersistenceManagerFactorypmf){

this.persistenceManagerFactory=pmf;

}

publicCollectionloadProductsByCategory(Stringcategory){

PersistenceManagerpm=this.persistenceManagerFactory.getPersistenceManager();

Queryquery=pm.newQuery(Product.class,"category=pCategory");

query.declareParameters("StringpCategory");

returnquery.execute(category);

}

}

DAO TransactionAwarePersistenceManagerFactoryProxy

"allowCreate"

<beans>

<beanid="myPmfProxy"

class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">

<propertyname="targetPersistenceManagerFactory"ref="myPmf"/>

<propertyname="allowCreate"value="false"/>

</bean>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="persistenceManagerFactory"ref="myPmfProxy"/>

</bean>

</beans>

DAOJDOAPISpring JDODAO JDOExceptionuncheckedexceptionDAODAO DAOJDOAPISpring JDOExceptionSpring DataAccessException

12.3.4.ServiceSpring

<?xmlversion="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"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<beanid="myTxManager"class="org.springframework.orm.jdo.JdoTransactionManager">

<propertyname="persistenceManagerFactory"ref="myPmf"/>

</bean>

<beanid="myProductService"class="product.ProductServiceImpl">

<propertyname="productDao"ref="myProductDao"/>

</bean>

<tx:adviceid="txAdvice"transaction-manager="txManager">

<tx:attributes>

<tx:methodname="increasePrice*"propagation="REQUIRED"/>

<tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/>

<tx:methodname="*"propagation="SUPPORTS"read-only="true"/>

</tx:attributes>

</tx:advice>

<aop:config>

<aop:pointcutid="productServiceMethods"expression="execution(*product.ProductService.*(..))"/>

<aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/>

</aop:config>

</beans>

JDO HibernateJDOnon-transactionalflushJTA JTASpringSpring JtaTransactionManagerEJBCMTJTAJdoTransactionManagerJDOJDBC DataSourceJDBCJdoDialectJDBCConnectionJDBCJDO2.0JDO1.0JdoDialect JdoDialect

12.3.5.JdoDialectJdoTemplate interfacename JdoDialect“jdoDialect”bean

DAO PersistenceManagerFactory JdoDaoSupport"jdoTemplate" JdoDialectSpring

JDBCConnectionJDBCDAO

Spring

PersistenceManagerJDBC

JDOExceptionsSpring DataAccessExceptionsJDO1.0API JDO2.0Spring1.2JDO2.0APISpringJDO JdoDialectJavadoc

12.4.OracleTopLinkSpringSpring 1.2Oracle TopLinkhttp://www.oracle.com/technology/products/ias/toplinkSpringHibernateSpringTopLink9.0.4Spring1.2TopLink10.1.3Spring1.2betaorg.springframework.orm.toplinkTopLinkSpringOracleTopLink TopLinkJimClark

12.4.1.SessionFactoryTopLinkSessionFactory ServerSession

ClientSession SpringTopLink

Spring LocalSessionFactoryBean beanTopLinkTopLinksessionSpringJDBC DataSource

<beans>

<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<propertyname="driverClassName"value="${jdbc.driverClassName}"/>

<propertyname="url"value="${jdbc.url}"/>

<propertyname="username"value="${jdbc.username}"/>

<propertyname="password"value="${jdbc.password}"/>

</bean>

<beanid="mySessionFactory"class="org.springframework.orm.toplink.LocalSessionFactoryBean">

<propertyname="configLocation"value="toplink-sessions.xml"/>

<propertyname="dataSource"ref="dataSource"/>

</bean>

</beans>

<toplink-configuration>

<session>

<name>Session</name>

<project-xml>toplink-mappings.xml</project-xml>

<session-type>

<server-session/>

</session-type>

<enable-logging>true</enable-logging>

<logging-options/>

</session>

</toplink-configuration>

LocalSessionFactoryBeanTopLink ServerSession

Session—— ClientSession SessionSpringTopLinkLocalSessionFactoryBeanTopLink DatabaseSession

12.4.2.TopLinkTemplateandTopLinkDaoSupportTopLinkDAOIoC SessionFactorySetterDAOTopLinkAPISessionFactory SessionSpring TopLinkTemplate

<beans>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="sessionFactory"ref="mySessionFactory"/>

</bean>

</beans>

publicclassTopLinkProductDaoimplementsProductDao{

privateTopLinkTemplatetlTemplate;

publicvoidsetSessionFactory(SessionFactorysessionFactory){

this.tlTemplate=newTopLinkTemplate(sessionFactory);

}

publicCollectionloadProductsByCategory(finalStringcategory)throwsDataAccessException{

return(Collection)this.tlTemplate.execute(newTopLinkCallback(){

publicObjectdoInTopLink(Sessionsession)throwsTopLinkException{

ReadAllQueryfindOwnersQuery=newReadAllQuery(Product.class);

findOwnersQuery.addArgument("Category");

ExpressionBuilderbuilder=this.findOwnersQuery.getExpressionBuilder();

findOwnersQuery.setSelectionCriteria(

builder.get("category").like(builder.getParameter("Category")));

Vectorargs=newVector();

args.add(category);

Listresult=session.executeQuery(findOwnersQuery,args);

//dosomefurtherstuffwiththeresultlist

returnresult;

}

});

}

}

TopLink TopLinkTemplateexecuteQueryreadAllreadById merge TopLinkTemplateJdoTemplate SpringsetSessionFactory(..) SessionFactory getSessionFactory()

getTopLinkTemplate()DAO

publicclassProductDaoImplextendsTopLinkDaoSupportimplementsProductDao{

publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{

ReadAllQueryfindOwnersQuery=newReadAllQuery(Product.class);

findOwnersQuery.addArgument("Category");

ExpressionBuilderbuilder=this.findOwnersQuery.getExpressionBuilder();

findOwnersQuery.setSelectionCriteria(

builder.get("category").like(builder.getParameter("Category")));

returngetTopLinkTemplate().executeQuery(findOwnersQuery,newObject[]{category});

}

}

TopLinkDAOSpring TopLinkTemplateDAO TopLinkAPISpringDAOSessionHibernate checkedexceptionsSession

12.4.3.TopLinkAPIDAOTopLinkAPIDAO SessionSpringSessionFactorySpring TransactionAwareSessionAdapter Session

TopLink Session getActiveSession()ServerSession getActiveUnitOfWork()

null

DAO:

publicclassProductDaoImplimplementsProductDao{

privateSessionsession;

publicvoidsetSession(Sessionsession){

this.session=session;

}

publicCollectionloadProductsByCategory(Stringcategory){

ReadAllQueryfindOwnersQuery=newReadAllQuery(Product.class);

findOwnersQuery.addArgument("Category");

ExpressionBuilderbuilder=this.findOwnersQuery.getExpressionBuilder();

findOwnersQuery.setSelectionCriteria(

builder.get("category").like(builder.getParameter("Category")));

Vectorargs=newVector();

args.add(category);

returnsession.getActiveSession().executeQuery(findOwnersQuery,args);

}

}

DAOIoCSpring TopLinkTemplateapplicationcontextSpringTransactionAwareSessionAdapter SessionbeanDAO

<beans>

<beanid="mySessionAdapter"

class="org.springframework.orm.toplink.support.TransactionAwareSessionAdapter">

<propertyname="sessionFactory"ref="mySessionFactory"/>

</bean>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="session"ref="mySessionAdapter"/>

</bean>

</beans>

DAOTopLinkAPISpring TopLink

DAO TopLinkExceptionuncheckedexceptionDAOTopLinkDAO DAOTopLink getActiveSession()JTATopLinkSpring TransactionAwareSessionAdapterTopLink ServerSession

TopLink Session.getActiveSession()

Session.getActiveUnitOfWork() SpringTopLinkTransactionManager Session JTASpring JtaTransactionManagerEJBCMTJTADAOTopLinkAPISpringTopLinkException TopLinkExceptionSpring

12.4.4.ServiceSpring

<?xmlversion="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"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<beanid="myTxManager"class="org.springframework.orm.toplink.TopLinkTransactionManager">

<propertyname="sessionFactory"ref="mySessionFactory"/>

</bean>

<beanid="myProductService"class="product.ProductServiceImpl">

<propertyname="productDao"ref="myProductDao"/>

</bean>

<aop:config>

<aop:pointcutid="productServiceMethods"expression="execution(*product.ProductService.*(..))"/>

<aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/>

</aop:config>

<tx:adviceid="txAdvice"transaction-manager="myTxManager">

<tx:attributes>

<tx:methodname="increasePrice*"propagation="REQUIRED"/>

<tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/>

<tx:methodname="*"propagation="SUPPORTS"read-only="true"/>

</tx:attributes>

</tx:advice>

</beans>

TopLink UnitOfWork TopLinkTopLinknon-transactionalflush TopLinkJTASession UnitOfWork Spring TopLinkTransactionManager

Spring JtaTransactionManagerEJBCMTJTATopLinkDAO Session.getActiveUnitOfWork()SpringJTA UnitOfWorkTopLinkTransactionManagerTopLink JDBC DataSource

TopLinkJDBCJDBC Connection

12.5.iBATISSQLMapsSpringiBatisJDBCHibernateJDBCHibernateIocSpringiBATISJDBCDataSourceTransactionManager JtaTransactionManager

SpringiBatis1.x2.x.iBatis2.xSpringSpringModulesproject

12.5.1.SqlMapClientiBATIS2.xAccountSQLmap

<sqlMapnamespace="Account">

<resultMapid="result"class="examples.Account">

<resultproperty="name"column="NAME"columnIndex="1"/>

<resultproperty="email"column="EMAIL"columnIndex="2"/>

</resultMap>

<selectid="getAccountByEmail"resultMap="result">

selectACCOUNT.NAME,ACCOUNT.EMAIL

fromACCOUNT

whereACCOUNT.EMAIL=#value#

</select>

<insertid="insertAccount">

insertintoACCOUNT(NAME,EMAIL)values(#name#,#email#)

</insert>

</sqlMap>

iBATIS2

<sqlMapConfig>

<sqlMapresource="example/Account.xml"/>

</sqlMapConfig>

iBATISCLASSPATH Account.xmlCLASSPATHSpringcontainer SqlMapClientFactoryBeaniBATISSQLMap2.xJDBCDataSource SqlMapClientFactoryBean

<beans>

<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">

<propertyname="driverClassName"value="${jdbc.driverClassName}"/>

<propertyname="url"value="${jdbc.url}"/>

<propertyname="username"value="${jdbc.username}"/>

<propertyname="password"value="${jdbc.password}"/>

</bean>

<beanid="sqlMapClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">

<propertyname="configLocation"value="WEB-INF/sqlmap-config.xml"/>

<propertyname="dataSource"ref="dataSource"/>

</bean>

</beans>

12.5.2. SqlMapClientTemplateSqlMapClientDaoSupport

SqlMapClientDaoSupport SqlMapDaoSupportDAO

publicclassSqlMapAccountDaoextendsSqlMapClientDaoSupportimplementsAccountDao{

publicAccountgetAccount(Stringemail)throwsDataAccessException{

return(Account)getSqlMapClientTemplate().queryForObject("getAccountByEmail",email);

}

publicvoidinsertAccount(Accountaccount)throwsDataAccessException{

getSqlMapClientTemplate().update("insertAccount",account);

}

}

applicationcontext SqlMapAccountDao SqlMapClientDAOSqlMapClientTemplate

<beans>

<beanid="accountDao"class="example.SqlMapAccountDao">

<propertyname="sqlMapClient"ref="sqlMapClient"/>

</bean>

</beans>

SqlMapTemplate SqlMapClient SqlMapClientDaoSupport

SqlMapClientTemplateSqlMapClientTemplate execute SqlMapClientCallback

publicclassSqlMapAccountDaoextendsSqlMapClientDaoSupportimplementsAccountDao{

publicvoidinsertAccount(Accountaccount)throwsDataAccessException{

getSqlMapClientTemplate().execute(newSqlMapClientCallback(){

publicObjectdoInSqlMapClient(SqlMapExecutorexecutor)throwsSQLException{

executor.startBatch();

executor.update("insertAccount",account);

executor.update("insertAddress",account.getAddress());

executor.executeBatch();

}

});

}

}

SqlMapExecutorAPI DataAccessException

12.5.3.iBATISAPIDAOiBATISAPISpring SqlMapClient

publicclassSqlMapAccountDaoimplementsAccountDao{

privateSqlMapClientsqlMapClient;

publicvoidsetSqlMapClient(SqlMapClientsqlMapClient){

this.sqlMapClient=sqlMapClient;

}

publicAccountgetAccount(Stringemail){

try{

return(Account)this.sqlMapClient.queryForObject("getAccountByEmail",email);

}

catch(SQLExceptionex){

thrownewMyDaoException(ex);

}

}

publicvoidinsertAccount(Accountaccount)throwsDataAccessException{

try{

this.sqlMapClient.update("insertAccount",account);

}

catch(SQLExceptionex){

thrownewMyDaoException(ex);

}

}

}

iBATISAPI SQLException DAOapplicationcontextiBATISDAOIoC

<beans>

<beanid="accountDao"class="example.SqlMapAccountDao">

<propertyname="sqlMapClient"ref="sqlMapClient"/>

</bean>

</beans>

12.6.JPAorg.springframework.orm.jpaSpringJPAHibernateJDOPersistenceAPI

12.6.1.SpringJPASpringJPAJPAEntityManagerFactory

12.6.1.1.LocalEntityManagerFactoryBeanLocalEntityManagerFactoryBeanJPA EntityManager

PersistenceProviderJPA JavaSEpersistenceunit

<beans>

<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">

<propertyname="persistenceUnitName"value="myPersistenceUnit"/>

</bean>

</beans>

JPAJDBC DataSourceJVM

12.6.1.2.JNDI EntityManagerFactory

JNDI EntityManagerFactoryJavaEE5XML

<beans>

<jee:jndi-lookupid="entityManagerFactory"jndi-name="persistence/myPersistenceUnit"/>

</beans>

JavaEE5JavaEE META-INF/persistence.xmlJavaEEpersistence-unit-ref web.xml

JavaEEJNDIEntityManagerJTASpringJtaTransactionManager

JPAJVM(Hibernate)(ant)

JNDIbeanJavaEE5JPAJPA

12.6.1.3.LocalContainerEntityManagerFactoryBeanLocalContainerEntityManagerFactoryBeanJPAEntityManagerFactory

LocalContainerEntityManagerFactoryBeanPersistenceUnitInfo dataSourceLookup loadTimeWeaverJNDI

<beans>

<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<propertyname="dataSource"ref="someDataSource"/>

<propertyname="loadTimeWeaver">

<beanclass="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>

</property>

</bean>

</beans>

JPAJDBC DataSource ClassLoaderJavaEE5JPAJavaEE5LocalContainerEntityManagerFactoryBean“persistenceXmlLocation” “META-INF/my-persistence.xml”JavaEE5INF/persistence.xmlSpring JPARdsin3.1SpringJPAwebTomcatLoadTimeWeaver SpringJPAClassTransformer web/ Java5 ClassTransformers—— ——Spring LoadTimeWeaver ClassTransformerclassloaderTomcatSpringVMJPAWebLogicOC4JGlassFishResin

12.6.1.3.1.Tomcat5.0

ApacheTomcatClassLoader SpringTomcatInstrumentableClassLoader

org.springframework.instrument.classloading.tomcatTomcatWebappClassLoaderJPAClassTransformer“” JPAJPAtransformer TomcatInstrumentableClassLoaderweb

spring-tomcat-weaver.jar $CATALINA_HOME/server/lib$CATALINA_HOMETomcat

webapplicationcontextTomcat

<Contextpath="/myWebApp"docBase="/my/webApp/location">

<LoaderloaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>

</Context>

Tomcat5.0.x5.5.xcontextlocations($CATALINA_HOME/conf/server.xml)$CATALINA_HOME/conf/context.xmlweb Serverweb$CATALINA_HOME/conf/[enginename]/[hostname]/my-webapp-context.xmlweb your-webapp.war/META-INF/context.xmlweb-appJPA5.5.20XMLbug server.xml Loaderclassloaderclassloader

Tomcat 5.5.20 useSystemClassLoaderAsParentfalse

<Contextpath="/myWebApp"docBase="/my/webApp/location">

<LoaderloaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"

useSystemClassLoaderAsParent="false"/>

</Context>

spring-tomcat-weaver.jar$CATALINA_HOME/lib (where$CATALINA_HOMETomcatwebTomcatClassLoaderClassLoader

<Contextpath="/myWebApp"docBase="/my/webApp/location">

<LoaderloaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>

</Context>

Tomcat6.0.x(5.0.x/5.5.x)contextlocations($CATALINA_HOME/conf/server.xml)$CATALINA_HOME/conf/context.xmlweb Serverweb$CATALINA_HOME/conf/[enginename]/[hostname]/my-webapp-context.xmlweb your-webapp.war/META-INF/context.xmlweb-appJPATomcat5.0.x/5.5.x

Tomcat6.0.xTomcat LocalContainerEntityManagerFactoryBean LoadTimeWeaver

<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<propertyname="loadTimeWeaver">

<beanclass="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>

</property>

</bean>

JPATomcatJPA

TomcatTopLinkJPAtoplinkjar $CATALINA_HOME/shared/libwar

12.6.1.3.2.VM

LoadTimeWeaverJDKSpringagent.jarInstrumentationLoadTimeWeaver

<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<propertyname="loadTimeWeaver">

<beanclass="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>

</property>

</bean>

SpringJVM

-javaagent:/path/to/spring-agent.jar

12.6.1.3.3.

Spring2.5 context:load-time-weaver LoadTimeWeaver“”JPALocalContainerEntityManagerFactoryBeans

ebLogic,OC4J,GlassFish,Tomcat,Resin,VMagentbean

<context:load-time-weaver/>

<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

...

</bean>

6.8.4.5“Spring” TomcatVMWebLogic,OC4J,GlassFishResin

12.6.1.4.(classpathjar) SpringMETA-INF/persistence.xml)

<beanid="pum"class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">

<propertyname="persistenceXmlLocation">

<list>

<value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>

<value>classpath:/my/package/**/custom-persistence.xml</value>

<value>classpath*:META-INF/persistence.xml</value>

</list>

</property>

<propertyname="dataSources">

<map>

<entrykey="localDataSource"value-ref="local-db"/>

<entrykey="remoteDataSource"value-ref="remote-db"/>

</map>

</property>

<!--ifnodatasourceisspecified,usethisone-->

<propertyname="defaultDataSource"ref="remoteDataSource"/>

</bean>

<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

<propertyname="persistenceUnitManager"ref="pum"/>

</bean>

JPAprovider PersistenceUnitPostProcessor

persistenceUnitManager LocalContainerEntityManagerFactoryBean

12.6.2.JpaTemplate JpaDaoSupport

JPADAO EntityManagerFactory DAO EntityManagerFactory

JPAAPI Spring JpaTemplate

<beans>

<beanid="myProductDao"class="product.ProductDaoImpl">

<propertyname="entityManagerFactory"ref="entityManagerFactory"/>

</bean>

</beans>

publicclassJpaProductDaoimplementsProductDao{

privateJpaTemplatejpaTemplate;

publicvoidsetEntityManagerFactory(EntityManagerFactoryemf){

this.jpaTemplate=newJpaTemplate(emf);

}

publicCollectionloadProductsByCategory(finalStringcategory)throwsDataAccessException{

return(Collection)this.jpaTemplate.execute(newJpaCallback(){

publicObjectdoInJpa(EntityManagerem)throwsPersistenceException{

Queryquery=em.createQuery("fromProductaspwherep.category=:category");

query.setParameter("category",category);

Listresult=query.getResultList();

//dosomefurtherprocessingwiththeresultlist

returnresult;

}

});

}

}

JpaCallbackJPA JpaTemplate EntityManagerJpaTemplateTemplate JpaTemplatefind

loadmergeSpring JpaDaoSupport get/setEntityManagerFactorygetJpaTemplate()

publicclassProductDaoImplextendsJpaDaoSupportimplementsProductDao{

publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{

Map<String,String>params=newHashMap<String,String>();

params.put("category",category);

returngetJpaTemplate().findByNamedParams("fromProductaspwherep.category=:category",params);

}

}

Spring JpaTemplateJPAAPISpringDAOcheckedexceptions JpaDaoSupport JpaTemplateJdoTemplateHibernateTemplateJPA@PersistenceContext “EntityManager”SpringPersistenceAnnotationBeanPostProcessor

12.6.3.JPADAO

EntityManagerFactory EntityManagerJPAJNDI JPAJPA EntityManager

EntityManager

JPAAPISpringPersistenceAnnotationBeanPostProcessor Spring @PersistenceUnit

@PersistenceContextDAO

publicclassProductDaoImplimplementsProductDao{

privateEntityManagerFactoryemf;

@PersistenceUnit

publicvoidsetEntityManagerFactory(EntityManagerFactoryemf){

this.emf=emf;

}

publicCollectionloadProductsByCategory(Stringcategory){

EntityManagerem=this.emf.createEntityManager();

try{

Queryquery=em.createQuery("fromProductaspwherep.category=?1");

query.setParameter(1,category);

returnquery.getResultList();

}

finally{

if(em!=null){

em.close();

}

}

}

}

DAOSpringSpring JpaTemplate SpringapplicationcontextDAO EntityManagerFactory

<beans>

<!--beanpost-processorforJPAannotations-->

<beanclass="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>

<beanid="myProductDao"class="product.ProductDaoImpl"/>

</beans>

PersistenceAnnotationBeanPostProcessor Spring2.5context:annotation-configXML SpringCommonAnnotationBeanPostProcessor

<beans>

<!--post-processorsforallstandardconfigannotations-->

<context:annotation-config/>

(@PersistenceUnit@PersistenceContext)/”protected,private)

JEE5

<beanid="myProductDao"class="product.ProductDaoImpl"/>

</beans>

DAO EntityManager EntityManagerfactory

publicclassProductDaoImplimplementsProductDao{

@PersistenceContext

privateEntityManagerem;

publicCollectionloadProductsByCategory(Stringcategory){

Queryquery=em.createQuery("fromProductaspwherep.category=:category");

query.setParameter("category",category);

returnquery.getResultList();

}

}

@PersistenceContexttype PersistenceContextType.TRANSACTION

EntityManager” PersistenceContextType.EXTENDED“EntityManager”, SpringsingletonbeanEntityManager EntityManagerSpring EntityManagerEntityManagerFactory applicationcontextXMLDAOJPASpringJPASpringJPA

12.6.4.DAO PersistenceExceptionunchecked exception IllegalArgumentExceptionIllegalStateException DAOJPADAOJPA Spring

@Repository

publicclassProductDaoImplimplementsProductDao{

//classbodyhere...

}

<beans>

<!--Exceptiontranslationbeanpostprocessor-->

<beanclass="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

<beanid="myProductDao"class="product.ProductDaoImpl"/>

</beans>

PersistenceExceptionTranslator @RepositorybeanDAOJavaAPISpringIoC

12.7.ServiceSpring

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<beanid="myTxManager"class="org.springframework.orm.jpa.JpaTransactionManager">

<propertyname="entityManagerFactory"ref="myEmf"/>

</bean>

<beanid="myProductService"class="product.ProductServiceImpl">

<propertyname="productDao"ref="myProductDao"/>

</bean>

<aop:config>

<aop:pointcutid="productServiceMethods"expression="execution(*product.ProductService.*(..))"/>

<aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/>

</aop:config>

<tx:adviceid="txAdvice"transaction-manager="myTxManager">

<tx:attributes>

<tx:methodname="increasePrice*"propagation="REQUIRED"/>

<tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/>

<tx:methodname="*"propagation="SUPPORTS"read-only="true"/>

</tx:attributes>

</tx:advice>

</beans>

SpringJPAJpaTransactionManagerJPAJDBCDataSourceJDBCJpaDialectJDBCConnectionSpringToplinkHibernateJPADialectJpaDialect

12.8.JpaDialectJpaTemplateJpaTransactionManager

AbstractEntityManagerFactoryBean JpaDialect"jpaDialect"beanDAO EntityManagerFactory JpaDaoSupport"jpaTemplate" JpaDialectSpring

ConnectionJDBCDAO

PersistenceExceptionsSpring DataAccessExceptionsDefaultJpaDialectDialect

SpringJPA JpaDialectJavadoc

III.TheWebSprintFrameworkwebSpringFrameworkweb SpringWebMVCSpringFrameworkweb JSF

SpringMVC Portlet13 WebMVCframeworkWeb

14

15 Web

16 PortletMVC

13.WebMVCframeworkWeb13.1.

13.1.1.MVC13.1.2.SpringWebMVC

13.2.DispatcherServlet13.3.

13.3.1.AbstractController WebContentGenerator

13.3.2.13.3.3.MultiActionController13.3.4.

13.4.handlermapping13.4.1.BeanNameUrlHandlerMapping13.4.2.SimpleUrlHandlerMapping13.4.3.HandlerInterceptor

13.5.13.5.1.ViewResolver13.5.2.13.5.3.Rediret

13.6.13.6.1.AcceptHeaderLocaleResolver13.6.2.CookieLocaleResolver13.6.3.SessionLocaleResolver13.6.4.LocaleChangeInterceptor

13.7.13.7.1.13.7.2.13.7.3.

13.8.Springmultipartfileupload13.8.1.13.8.2.MultipartResolver13.8.3.

13.9.Spring13.9.1.13.9.2.form13.9.3.input13.9.4.checkbox13.9.5.checkboxes13.9.6.radiobutton13.9.7.radiobuttons13.9.8.password13.9.9.select

13.9.10.option13.9.11.options13.9.12.textarea13.9.13.hidden13.9.14.errors

13.10.13.11.conventionoverconfiguration

13.11.1. ControllerClassNameHandlerMapping

13.11.2. ModelMapModelAndView

13.11.3. RequestToViewNameTranslator

13.12.13.12.1.dispatcher13.12.2.@Controller13.12.3.@RequestMapping13.12.4.@RequestParam13.12.5.@ModelAttribute13.12.6.@SessionAttributes13.12.7.WebDataBinder

13.13.

14.14.1.14.2.JSPJSTL

14.2.1.14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTL14.2.3.

14.3.Tiles14.3.1.14.3.2.Tiles

14.4.VelocityFreeMarker14.4.1.14.4.2.Context14.4.3.14.4.4.14.4.5.

14.5.XSLT14.5.1.14.5.2.

14.6.PDF/Excel14.6.1.14.6.2.

14.7.JasperReports14.7.1.14.7.2.14.7.3. ModelAndView

14.7.4.14.7.5.Exporter

15.Web15.1.15.2.15.3.JavaServerFaces

15.3.1.DelegatingVariableResolver15.3.2.FacesContextUtils

15.4.Struts15.4.1.ContextLoaderPlugin15.4.2.ActionSupportClasses

15.5.Tapestry15.5.1.Springbeans

15.6.WebWork15.7.

16.PortletMVC16.1.

16.1.1.-MVCC16.1.2.-MVCV16.1.3.WebBean

16.2.DispatcherPortlet16.3.ViewRendererServlet16.4.

16.4.1.AbstractController PortletContentGenerator

16.4.2.16.4.3.Command16.4.4.PortletWrappingController

16.5.16.5.1.PortletModeHandlerMapping16.5.2.ParameterHandlerMapping16.5.3.PortletModeParameterHandlerMapping16.5.4. HandlerInterceptors16.5.5.HandlerInterceptorAdapter16.5.6.ParameterMappingInterceptor

16.6.16.7.Multipart

16.7.1. PortletMultipartResolver

16.7.2.16.8.16.9.Portlet

13WebMVCframeworkWeb

13.1.13.1.1.MVC13.1.2.SpringWebMVC

13.2.DispatcherServlet13.3.

13.3.1.AbstractController WebContentGenerator

13.3.2.13.3.3.MultiActionController13.3.4.

13.4.handlermapping13.4.1.BeanNameUrlHandlerMapping13.4.2.SimpleUrlHandlerMapping13.4.3.HandlerInterceptor

13.5.13.5.1.ViewResolver13.5.2.13.5.3.Rediret

13.6.13.6.1.AcceptHeaderLocaleResolver13.6.2.CookieLocaleResolver13.6.3.SessionLocaleResolver13.6.4.LocaleChangeInterceptor

13.7.13.7.1.13.7.2.13.7.3.

13.8.Springmultipartfileupload13.8.1.13.8.2.MultipartResolver13.8.3.

13.9.Spring13.9.1.13.9.2.form13.9.3.input13.9.4.checkbox13.9.5.checkboxes13.9.6.radiobutton13.9.7.radiobuttons

13.9.8.password13.9.9.select13.9.10.option13.9.11.options13.9.12.textarea13.9.13.hidden13.9.14.errors

13.10.13.11.conventionoverconfiguration

13.11.1. ControllerClassNameHandlerMapping

13.11.2. ModelMapModelAndView

13.11.3. RequestToViewNameTranslator

13.12.13.12.1.dispatcher13.12.2.@Controller13.12.3.@RequestMapping13.12.4.@RequestParam13.12.5.@ModelAttribute13.12.6.@SessionAttributes13.12.7.WebDataBinder

13.13.

“”SpringwebSpring“ OCP ”SpringWebMVCoverride) bydesign

SethLaddExpertSpringWebMVCandWebFlow117“ALookAtDesign”

Bob Martin, The Open-ClosedPrinciple(PDF)

SpringMVCfinaladviceAbstractController.handleRequest()

AOP finalAOP”

13.1.SpringwebDispatcherServlet DispatcherServlethandlerviewlocal themeSpringWeb

ModelAndViewhandleRequest(request,response)

Spring AbstractControllerAbstractCommandControllerSimpleFormControllerFormController

Spring2.5Java5controller13.12“”

SpringWebMVC- ActionActionForm

WebWorkSpring Controller

CommandObjectFormObjectModel WebWork WebWork Action

ViewWebWork Action

ActionbeanSpringresponse ModelAndViewnullModelAndView MapmodelmodelbeankeybeanformJavaBean valuebeanViewResolver MapmodelMVCM SpringJSPVelocityMapmodelJSPrequestattributeVelocitytemplatemodel

13.1.1.MVCweb

SpringwebMVCSpring webSpringSpringrootapplicationcontext StrutsWebWorkAction ServletContext

Spring“plugins” webrootapplicationcontextSpring

SpringWebFlowSpringWebFlowSWFWeb

SWFservletportletSpringMVCStrutsJSF SWFSWFSWF SpringWebFlow

librarySpringwebMVCSpringbean SpringStrutsWebWorkwebMVC beanSpring

13.1.2.SpringWebMVCSpringweb:

controllervalidatorcommand objectformobjectmodelobject ServletDispatcherServlet handlermappingviewresolver

JavaBeancontextwebvalidator simplecommandformwizardmulti-action Action/ActionForm

bindingvalidation

handlermappingviewresolutionSpringURL webMVCSpringmodelSpringweb Map/

themeJSPSpringJSTLVelocity

JSPSpringTagLibrarytheme

JSPSpring2.0JSP

SpringBeanHTTPRequestHTTPSessionSpringMVCSpingMVCWebApplicationContext 3.4.4“”

13.2.DispatcherServletwebMVCSpringwebMVCwebservletDispatcherServletSpringIoCSpringSpringWebMVCDispatcherServlet DispatcherServlet

Controller”web

SpringWebMVC

DispatcherServletServlet HttpServletServletDispatcherServletwebweb.xml DispatcherServlet web.xml

DispatcherServlet

<web-app>

<servlet>

<servlet-name>example</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>example</servlet-name>

<url-pattern>*.form</url-pattern>

</servlet-mapping>

</web-app>

.formexampleDispatcherServletSpringWebMVCDispatcherServletSpringWebMVCbean3.8“The ApplicationContext”Spring ApplicationContextscopewebMVC DispatcherServletWebApplicationContextcontextWebApplicationContextbeanbeanserlvetoverridebean

SpringWebMVCContext

DispatcherServletweb WEB-INF[servlet-name]-servlet.xml

beanglobalcopebeanweb.xmlDispatcherServlet

<web-app>

...

<servlet>

<servlet-name>golfing</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>golfing</servlet-name>

<url-pattern>*.do</url-pattern>

</servlet-mapping>

</web-app>

servlet /WEB-INF/golfing-servlet.xmlgolfing-servlet.xmlWebMVC beanweb.xmlservletWebApplicationContextweb ApplicationContext

theme 13.7 “” servletServletContext WebApplicationContextServletContext

RequestContextUtilsWebApplicationContext

SpringDispatcherServletbean beanSpringWebApplicationContextbeanbean DispatcherServletbeanSpring

13.1.WebApplicationContextbean

BeanControllers MVCC

Handlermapping pre-processor post-processorURL

Viewresolvers

Localeresolver

Themeresolver web

MultipartFileresolver HTML

(Handlerexceptionresolver(s))

DispatcherServlet DispatcherServlet

WebApplicationContextDispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE

localResolver

SpringMultipartResolver”

WebApplicationContext WebApplicationContext

SpringDispatcherServletServletAPIlast-modification-dateDispatcherServlethandlermapping

getLastModified(request)

SpringDispatcherServletweb.xmlcontext servlet

13.2.DispatcherServlet

contextClassWebApplicationContextservlet

XmlWebApplicationContext

contextConfigLocation contextClass

namespaceWebApplicationContext [server-name]-

servlet

13.3.MVCMVC C Springorg.springframework.mvc.Controller

publicinterfaceController{

/**

*ProcesstherequestandreturnaModelAndViewobjectwhichtheDispatcherServlet

*willrender.

*/

ModelAndViewhandleRequest(

HttpServletRequestrequest,

HttpServletResponseresponse)throwsException;

}

ControllerSpringMVCControllerSpringController

13.3.1.AbstractController WebContentGenerator

Spring AbstractControllerAbstractControllermimetype

13.3.AbstractController

supportedMethods GETPOST

requiresSession HTTPsessionsession

synchronizeOnSession controllerHTTPsession

cacheSeconds controller -1

useExpiresHeader ControllerHTTP1.0 Expiresheader true

useCacheHeader ControllerHTTP1.1 Cache-Controlheader true

AbstractController handleRequestInternal(HttpServletRequest,

HttpServletResponse) ModelAndView AbstractController

applicationContext.xml

packagesamples;

publicclassSampleControllerextendsAbstractController{

publicModelAndViewhandleRequestInternal(

HttpServletRequestrequest,

HttpServletResponseresponse)throwsException{

ModelAndViewmav=newModelAndView("hello");

mav.addObject("message","HelloWorld!");

returnmav;

}

}

<beanid="sampleController"class="samples.SampleController">

<propertyname="cacheSeconds"value="120"/>

</bean>

handlermapping 13.4“handlermapping” context controller2

13.3.2.AbstractControllerSpringMVCapplicationcontext JavaUrlFilenameViewControllerURLhttp://www.springframework.org/index.htmlindex

13.3.3.MultiActionControllerSpringMultiActionController StrutsStruts DispatchAction

MultiActionController org.springframework.web.mvc.multiactionMultiActionController

MultiActionController MultiActionController MethodNameResolver

delegate MethodNameResolver

setDelegate

MultiActionController MethodNameResolver

MultiActionController' methodNameResolver' MethodNameResolver

MultiActionController

//'anyMeaningfulName'

public[ModelAndView|Map|void]anyMeaningfulName(HttpServletRequest,HttpServletResponse[,HttpSession][,AnyObject])

MultiActionControllerJavadoc MultiActionControllerJavadocController

publicModelAndViewdisplayCatalog(HttpServletRequest,HttpServletResponse)

Login

publicModelAndViewlogin(HttpServletRequest,HttpServletResponse,Login)

session

publicModelAndViewviewCart(HttpServletRequest,HttpServletResponse,HttpSession)

Product sessionsessionfinalsession

publicModelAndViewupdateCart(HttpServletRequest,HttpServletResponse,HttpSession,Product)

voidresponse

publicvoidhome(HttpServletRequest,HttpServletResponse)

Mapmodel 13.11“conventionoverconfiguration”

publicMaplist(HttpServletRequest,HttpServletResponse)

MethodNameResolverSpring MethodNameResolverSpringInternalPathMethodNameResolver

InternalPathMethodNameResolver-http://www.sf.net/testing.view

testing(HttpServletRequest,HttpServletResponse)

ParameterMethodNameResolver-http://www.sf.net/index.view?method=testIt

testIt(HttpServletRequest,HttpServletResponse)) paramName

PropertiesMethodNameResolver-PropertiesURL/index/welcome.html=doIt /index/welcome.htmldoIt(HttpServletRequest, HttpServletResponse)

PropertiesMethodNameResolver Spring PathMatcherURL/**/welcom?.html

Exceptions HttpServletRequest

ExceptionSpring

publicModelAndViewprocessException(HttpServletRequest,HttpServletResponse,IllegalArgumentException)

MultiActionControllerParameterMethodNameResolver

<beanid="paramMultiController"

class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">

<propertyname="methodNameResolver">

<beanclass="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">

<propertyname="paramName"value="method"/>

</bean>

</property>

<propertyname="delegate">

<beanclass="samples.SampleDelegate"/>

</property>

</bean>

}

publicclassSampleDelegate{

publicModelAndViewretrieveIndex(HttpServletRequestreq,HttpServletResponseresp){

returnnewModelAndView("index","date",newLong(System.currentTimeMillis()));

}

}

PropertiesMethodNameResolverURL

<beanid="propsResolver"

class="org....mvc.multiaction.PropertiesMethodNameResolver">

<propertyname="mappings">

<value>

/index/welcome.html=retrieveIndex

/**/notwelcome.html=retrieveIndex

/*/user?.html=retrieveIndex

</value>

</property>

</bean>

<beanid="paramMultiController"class="org....mvc.multiaction.MultiActionController">

<propertyname="methodNameResolver"ref="propsResolver"/>

<propertyname="delegate">

<beanclass="samples.SampleDelegate"/>

</property>

</bean>

13.3.4.SpringcommandcontrollersSpringMVCStruts ActionFormSpring

AbstractCommandController

AbstractFormController AbstractFormController

SimpleFormControllerformcontrollerform

AbstractWizardFormController validatePage()processFinish()processCancel()contractor setPages()setCommandName()setPages()StringsetCommandName()StringAbstractFormController,JavaBeanbeansetCommandClass() formBackingObject()

AbstractWizardFormControlleroverride

Map getTargetPage() onBindAndValidate()

setAllowDirtyBack()setAllowDirtyForward() getTargetPage()

AbstractWizardFormControllerJavaDoc SpringjPetStoreorg.springframework.samples.jpetstore.web.spring.OrderFormController

13.4.handlermappingwebhandler SpringBeanNameUrlHandlerMapping HandlerMapping

HandlerMappingHandlerExecutionChain HandlerExecutionChain DispatcherServlet HandlerExecutionChain

DispatcherServletinterceptorSpring AbstractHandlerMapping

interceptors HandlerInterceptor 13.4.3 “

HandlerInterceptor”

defaultHandler

orderorder( org.springframework.core.Ordered)Spring

alwaysUseFullPathtrueSpringservletcontextservletcontext servletservlet-mappingalwaysUseFullPathtrue URL /testing/viewPage.html

/viewPage.html

urlDecodetrue2.5 false

lazyInitHandlerssingletonprototype)

org.springframework.web.servlet.handler.AbstractUrlHandlerMapping

13.4.1.BeanNameUrlHandlerMappingBeanNameUrlHandlerMappingHTTPbeanbeanwebFormControllerCommandControllerFormController 13.3.4“”Velocity BeanNameUrlHandlerMapping

http://samples.com/editaccount.formFormController

<beans>

<beanid="handlerMapping"class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>

<beanname="/editaccount.form"class="org.springframework.web.servlet.mvc.SimpleFormController">

<propertyname="formView"value="account"/>

<propertyname="successView"value="account-created"/>

<propertyname="commandName"value="account"/>

<propertyname="commandClass"value="samples.Account"/>

</bean>

<beans>

/editaccount.form FormController web.xmlservlet-mapping

<web-app>

...

<servlet>

<servlet-name>sample</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<!--mapsthesampledispatcherto*.form-->

<servlet-mapping>

<servlet-name>sample</servlet-name>

<url-pattern>*.form</url-pattern>

</servlet-mapping>

...

</web-app>

BeanNameUrlHandlerMappingwebDispatcherServletBeanNameUrlHandlerMapping

13.4.2.SimpleUrlHandlerMappingSimpleUrlHandlerMappingAntorg.springframework.util.PathMatcherJavaDoc

<web-app>

...

<servlet>

<servlet-name>sample</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<!--mapsthesampledispatcherto*.form-->

<servlet-mapping>

<servlet-name>sample</servlet-name>

<url-pattern>*.form</url-pattern>

</servlet-mapping>

<!--mapsthesampledispatcherto*.html-->

<servlet-mapping>

<servlet-name>sample</servlet-name>

<url-pattern>*.html</url-pattern>

</servlet-mapping>

...

</web-app>

web.xml.html.formsampleDispatcherServlet

<beans>

<!--no'id'required,HandlerMappingbeansareautomaticallydetectedbythe

<beanclass="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<propertyname="mappings">

<value>

/*/account.form=editAccountFormController

/*/editaccount.form=editAccountFormController

/ex/view*.html=helpController

/**/help.html=helpController

</value>

</property>

</bean>

<beanid="helpController"

class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>

<beanid="editAccountFormController"

class="org.springframework.web.servlet.mvc.SimpleFormController">

<propertyname="formView"value="account"/>

<propertyname="successView"value="account-created"/>

<propertyname="commandName"value="Account"/>

<propertyname="commandClass"value="samples.Account"/>

</bean>

<beans>

help.htmlhelpController helpControllerUrlFilenameViewController

13.3“” exview .htmleditAccountFormController

13.4.3. HandlerInterceptor

Springorg.springframework.web.servletHandlerInterceptor

preHandle(..)boolean true

96

<beans>

<beanid="handlerMapping"

class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<propertyname="interceptors">

<list>

<refbean="officeHoursInterceptor"/>

</list>

</property>

<propertyname="mappings">

<value>

/*.form=editAccountFormController

/*.view=editAccountFormController

</value>

</property>

</bean>

<beanid="officeHoursInterceptor"

class="samples.TimeBasedAccessInterceptor">

<propertyname="openingTime"value="9"/>

<propertyname="closingTime"value="18"/>

</bean>

<beans>

packagesamples;

publicclassTimeBasedAccessInterceptorextendsHandlerInterceptorAdapter{

privateintopeningTime;

privateintclosingTime;

publicvoidsetOpeningTime(intopeningTime){

this.openingTime=openingTime;

}

publicvoidsetClosingTime(intclosingTime){

this.closingTime=closingTime;

}

publicbooleanpreHandle(

HttpServletRequestrequest,

HttpServletResponseresponse,

Objecthandler)throwsException{

Calendarcal=Calendar.getInstance();

inthour=cal.get(HOUR_OF_DAY);

if(openingTime<=hour<closingTime){

returntrue;

}else{

response.sendRedirect("http://host.com/outsideOfficeHours.html");

returnfalse;

}

}

}

TimeBasedAccessInterceptor htmlSpringadapterHandlerInterceptorAdapterHandlerInterceptor

13.5.webMVC SpringViewResolverViewSpring ViewResolver

13.5.1. ViewResolver

13.3“” SpringWeb ModelAndView SprnigSpring

13.4.ViewResolver

AbstractCachingViewResolver

XmlViewResolverXmlViewResolver ViewResolverXMLXMLBeanFactoryDTD /WEB-INF/views.xml

ResourceBundleViewResolver

ResourceBundleViewResolver ViewResolverResourceBundlebean bundleclasspathviews.properties

UrlBasedViewResolverUrlBasedViewResolver ViewResolverURL

InternalResourceViewResolver

UrlBasedViewResolverInternalResourceViewServletJSPJstlViewTilesView setViewClassUrlBasedViewResolverJavadoc

VelocityViewResolver/FreeMarkerViewResolver

UrlBasedViewResolverVelocityViewVelocity FreeMarkerView

JSP UrlBasedViewResolverURLRequestDispatcher

<beanid="viewResolver"

class="org.springframework.web.servlet.view.UrlBasedViewResolver">

<propertyname="prefix"value="/WEB-INF/jsp/"/>

<propertyname="suffix"value=".jsp"/>

</bean>

test RequestDispatcherRequestDispatcher/WEB-INF/jsp/test.jsp

web ResourceBundleViewResolver

<beanid="viewResolver"

class="org.springframework.web.servlet.view.ResourceBundleViewResolver">

<propertyname="basename"value="views"/>

<propertyname="defaultParentView"value="parentView"/>

</bean>

ResourceBundleViewResolverbasenameResourceBundleResourceBundle [].class [].url URLparentview AbstractCachingViewResolver Velocity removeFromCache(StringviewName,Localeloc)

13.5.2.Spring InternalResourceViewResolver

InternalResourceViewResolver

<beanid="jspViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>

<propertyname="prefix"value="/WEB-INF/jsp/"/>

<propertyname="suffix"value=".jsp"/>

</bean>

<beanid="excelViewResolver"class="org.springframework.web.servlet.view.XmlViewResolver">

<propertyname="order"value="1"/>

<propertyname="location"value="/WEB-INF/views.xml"/>

</bean>

<!--inviews.xml-->

<beans>

<beanname="report"class="org.springframework.example.ReportExcelView"/>

</beans>

Spring Srpingnull

RequestDispatcherJSP InternalResourceViewResolver

InternalResourceViewResolver

13.5.3.Rediret JSPServlet/JSPInternalResourceViewServletAPI RequestDispatcher.forward(..)

RequestDispatcher.include() VelocityXSLTHTTPredirect HTTPPOST HTTPredirect

GET POST

13.5.3.1.RedirectViewSpringRedirectView DispatcherServletRedirectViewHttpServletResponse.sendRedirect() HTTPredirectHTTP stringHTTPStringStringRedirectView URLSpringIoC

13.5.3.2.redirect:RedirectView RedirectView redirect: redirect: UrlBasedViewResolverURLRedirectView redirect:/my/response/controller.html

context redirect:http://myhost.com/some/arbitrary/path.html

URL

13.5.3.3.forward:forward: UrlBasedViewResolver

RequestDispatcher.forward()forwardURLInternalResourceViewResolver/InternalResourceViewJSPServlet/JSPengineforward forwardforwardredirect:forward

13.6.SpringSpringwebMVC DispatcherServlet

DispatcherServlet RequestContext.getLocale()

13.4.3“ HandlerInterceptor” org.springframework.web.servlet.i18n Spring

13.6.1.AcceptHeaderLocaleResolveraccept-language HTTPHeader

13.6.2.CookieLocaleResolverCookie cookiecookieMaxAge

<beanid="localeResolver"class="org.springframework.web.servlet.i18n.CookieLocaleResolver">

<propertyname="cookieName"value="clientlanguage"/>

<!--inseconds.Ifsetto-1,thecookieisnotpersisted(deletedwhenbrowsershutsdown)-->

<propertyname="cookieMaxAge"value="100000">

</bean>

13.5.CookieLocaleResolver

cookieName classname+LOCALE cookie

cookieMaxAge Integer.MAX_INT cookie-1cookiecookie

cookiePath / cookie (cookiePath)cookie

13.6.3.SessionLocaleResolverSessionLocaleResolversession

13.6.4.LocaleChangeInterceptorLocaleChangeInterceptor 13.4“handlermapping”

LocaleResolversetLocale()

<beanid="localeChangeInterceptor"

class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">

<propertyname="paramName"value="siteLanguage"/>

</bean>

<beanid="localeResolver"

class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>

<beanid="urlMapping"

class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<propertyname="interceptors">

<list>

<refbean="localeChangeInterceptor"/>

</list>

</property>

<propertyname="mappings">

<value>/**/*.view=someController</value>

</property>

</bean>

*.view siteLanguage http://www.sf.net/home.view?

siteLanguage=nl

13.7.

13.7.1.SpingwebMVCtheme

13.7.2.web org.springframework.ui.context.ThemeSource

WebApplicationContextThemeSource ThemeSourceorg.springframework.ui.context.support.ResourceBundleThemeSourceclasspath /WEB-INF/classesResourceBundleThemeSourcebasenameprefix "themeSource"bean webapplicationcontextbeanResourceBundleThemeSource :

styleSheet=/themes/cool/style.css

background=/themes/cool/img/coolBg.jpg

themedelement JSP

<%@taglibprefix="spring"uri="http://www.springframework.org/tags"%>

<html>

<head>

<linkrel="stylesheet"href="<spring:themecode="styleSheet"/>"type="text/css"/>

</head>

<bodybackground="<spring:themecode="background"/>">

...

</body>

</html>

ResourceBundleThemeSourcecool.properties classpath /WEB-INF/classes

ResourceBundleThemeSourceJavaresourcebundle INF/classes/cool_nl.properties

ResourceBundleJavaDocResourceBundle.getBundle(StringbaseName,Localelocale)API baseName cool.properties/WEB-

INF/classes/com/aa/bb/cc baseNamecom.aa.bb.cc.coolcom.aa.bb.cc(basenameprefix) APIgetBundle(

ResourceBundleThemeSource

13.7.3. DispatcherServlet“themeResolver”bean LocaleResolver Spring

13.6.ThemeResolver

JavaFixedThemeResolver “defaultThemeName”

SessionThemeResolver HTTPsessionsessionsession

CookieThemeResolver cookie

SpringThemeChangeInterceptor

13.8.Springmultipartfileupload

13.8.1.Springweb MultipartResolver Spring MultipartResolverCommonsFileUploadhttp://jakarta.apache.org/commons/fileupload COSFileUpload(http://www.servlets.com/cos) SpringSpring Springweb

13.8.2. MultipartResolver

CommonsMultipartResolver

<beanid="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!--oneofthepropertiesavailable;themaximumfilesizeinbytes-->

<propertyname="maxUploadSize"value="100000"/>

</bean>

CosMultipartResolver

<beanid="multipartResolver"class="org.springframework.web.multipart.cos.CosMultipartResolver">

<!--oneofthepropertiesavailable;themaximumfilesizeinbytes-->

<propertyname="maxUploadSize"value="100000"/>

</bean>

classpathjar CommonsMultipartResolver

CosMultipartResolver cos.jar

Spring Spring DispatcherServlet

MultipartHttpServletRequest MultipartHttpServletRequest

13.8.3.MultipartResolver uploadfieldHTMLSpring

<html>

<head>

<title>Uploadafileplease</title>

</head>

<body>

<h1>Pleaseuploadafile</h1>

<formmethod="post"action="upload.form"enctype="multipart/form-data">

<inputtype="file"name="file"/>

<inputtype="submit"/>

</form>

</body>

</html>

input“file”bean

primitivetypebeanbean StringMultipartEditorbyte CustomDateEditor

HTMLURL

<beans>

<!--letsusetheCommons-basedimplementationoftheMultipartResolverinterface-->

<beanid="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>

<beanid="urlMapping"class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">

<propertyname="mappings">

<value>

/upload.form=fileUploadController

</value>

</property>

</bean>

<beanid="fileUploadController"class="examples.FileUploadController">

<propertyname="commandClass"value="examples.FileUploadBean"/>

<propertyname="formView"value="fileuploadform"/>

<propertyname="successView"value="confirmation"/>

</bean>

</beans>

bean

publicclassFileUploadControllerextendsSimpleFormController{

protectedModelAndViewonSubmit(

HttpServletRequestrequest,

HttpServletResponseresponse,

Objectcommand,

BindExceptionerrors)throwsServletException,IOException{

//castthebean

FileUploadBeanbean=(FileUploadBean)command;

let'sseeifthere'scontentthere

byte[]file=bean.getFile();

if(file==null){

//hmm,that'sstrange,theuserdidnotuploadanything

}

//well,let'sdonothingwiththebeanfornowandreturn

returnsuper.onSubmit(request,response,command,errors);

}

protectedvoidinitBinder(HttpServletRequestrequest,ServletRequestDataBinderbinder)

throwsServletException{

//toactuallybeabletoconvertMultipartinstancetobyte[]

//wehavetoregisteracustomeditor

binder.registerCustomEditor(byte[].class,newByteArrayMultipartFileEditor());

//nowSpringknowshowtohandlemultipartobjectandconvertthem

}

}

publicclassFileUploadBean{

privatebyte[]file;

publicvoidsetFile(byte[]file){

this.file=file;

}

publicbyte[]getFile(){

returnfile;

}

}

FileUploadBeanbyte[] Springmultipartbean

formbackingString

publicclassFileUploadControllerextendsSimpleFormController{

protectedModelAndViewonSubmit(

HttpServletRequestrequest,

HttpServletResponseresponse,

Objectcommand,

BindExceptionerrors)throwsServletException,IOException{

//castthebean

FileUploadBeanbean=(FileUploadBean)command;

let'sseeifthere'scontentthere

Stringfile=bean.getFile();

if(file==null){

//hmm,that'sstrange,theuserdidnotuploadanything

}

//well,let'sdonothingwiththebeanfornowandreturn

returnsuper.onSubmit(request,response,command,errors);

}

protectedvoidinitBinder(HttpServletRequestrequest,ServletRequestDataBinderbinder)

throwsServletException{

//toactuallybeabletoconvertMultipartinstancetoaString

//wehavetoregisteracustomeditor

binder.registerCustomEditor(String.class,newStringMultipartFileEditor());

//nowSpringknowshowtohandlemultipartobjectandconvertthem

}

}

publicclassFileUploadBean{

privateStringfile;

publicvoidsetFile(Stringfile){

this.file=file;

}

publicStringgetFile(){

returnfile;

}

}

formbacking MultipartFile

publicclassFileUploadControllerextendsSimpleFormController{

protectedModelAndViewonSubmit(

HttpServletRequestrequest,

HttpServletResponseresponse,

Objectcommand,

BindExceptionerrors)throwsServletException,IOException{

//castthebean

FileUploadBeanbean=(FileUploadBean)command;

let'sseeifthere'scontentthere

MultipartFilefile=bean.getFile();

if(file==null){

//hmm,that'sstrange,theuserdidnotuploadanything

}

//well,let'sdonothingwiththebeanfornowandreturn

returnsuper.onSubmit(request,response,command,errors);

}

}

publicclassFileUploadBean{

privateMultipartFilefile;

publicvoidsetFile(MultipartFilefile){

this.file=file;

}

publicMultipartFilegetFile(){

returnfile;

}

}

13.9.Spring2.0JSPSpringWebMVCSpringHTML4.01/XHTML1.0/SpringSpringWebMVC commandobjectreferencedataJSP HTML

13.9.1.Springspring.jar descriptor) spring-form.tld

JSP

<%@taglibprefix="form"uri="http://www.springframework.org/tags/form"%>

form

13.9.2.formHTML“form”bindingpath form

UserJavaBean firstNamelastNameobject) form.jsp

<form:form>

<table>

<tr>

<td>FirstName:</td>

<td><form:inputpath="firstName"/></td>

</tr>

<tr>

<td>LastName:</td>

<td><form:inputpath="lastName"/></td>

</tr>

<tr>

<tdcolspan="2">

<inputtype="submit"value="SaveChanges"/>

</td>

</tr>

</table>

</form:form>

firstNamelastNamePageContextHTMLform

<formmethod="POST">

<table>

<tr>

<td>FirstName:</td>

<td><inputname="firstName"type="text"value="Harry"/></td>

</tr>

<tr>

<td>LastName:</td>

<td><inputname="lastName"type="text"value="Potter"/></td>

</tr>

<tr>

<tdcolspan="2">

<inputtype="submit"value="SaveChanges"/>

</td>

</tr>

</table>

</form>

JSPformbacking“ command”

<form:formcommandName="user">

<table>

<tr>

<td>FirstName:</td>

<td><form:inputpath="firstName"/></td>

</tr>

<tr>

<td>LastName:</td>

<td><form:inputpath="lastName"/></td>

</tr>

<tr>

<tdcolspan="2">

<inputtype="submit"value="SaveChanges"/>

</td>

</tr>

</table>

</form:form>

13.9.3.input“text”HTML“input” 13.9.2“ form”

13.9.4.checkbox“checkbox”HTML“input”User Preferences

publicclassPreferences{

privatebooleanreceiveNewsletter;

privateString[]interests;

privateStringfavouriteWord;

publicbooleanisReceiveNewsletter(){

returnreceiveNewsletter;

}

publicvoidsetReceiveNewsletter(booleanreceiveNewsletter){

this.receiveNewsletter=receiveNewsletter;

}

publicString[]getInterests(){

returninterests;

}

publicvoidsetInterests(String[]interests){

this.interests=interests;

}

publicStringgetFavouriteWord(){

returnfavouriteWord;

}

publicvoidsetFavouriteWord(StringfavouriteWord){

this.favouriteWord=favouriteWord;

}

}

form.jsp

<form:form>

<table>

<tr>

<td>Subscribetonewsletter?:</td>

<%--Approach1:Propertyisoftypejava.lang.Boolean

<td><form:checkboxpath="preferences.receiveNewsletter"/></td>

</tr>

<tr>

<td>Interests:</td>

<td>

<%--Approach2:Propertyisofanarrayoroftype

Quidditch:<form:checkboxpath="preferences.interests"value="Quidditch"/>

Herbology:<form:checkboxpath="preferences.interests"value="Herbology"/>

DefenceAgainsttheDarkArts:<form:checkboxpath="preferences.interests"

value="DefenceAgainsttheDarkArts"/>

</td>

</tr>

<tr>

<td>FavouriteWord:</td>

<td>

<%--Approach3:Propertyisoftypejava.lang.Object

Magic:<form:checkboxpath="preferences.favouriteWord"value="Magic"/>

</td>

</tr>

</table>

</form:form>

checkboxcheckbox

java.lang.Boolean true input(checkbox) value

setValue(Object)

arrayjava.util.Collection setValue(Object)Collection

input(checkbox)

setValue(Object) input(checkbox)

HTMLcheckboxHTML

<tr>

<td>Interests:</td>

<td>

Quidditch:<inputname="preferences.interests"type="checkbox"value="Quidditch"/>

<inputtype="hidden"value="1"name="_preferences.interests"/>

Herbology:<inputname="preferences.interests"type="checkbox"value="Herbology"/>

<inputtype="hidden"value="1"name="_preferences.interests"/>

DefenceAgainsttheDarkArts:<inputname="preferences.interests"type="checkbox"

value="DefenceAgainsttheDarkArts"/>

<inputtype="hidden"value="1"name="_preferences.interests"/>

</td>

</tr>

checkboxfield HTMLcheckboxcheckboxSpringcheckbox"_"checkbox ”

13.9.5.checkboxes“checkbox”HTML“input”checkbox JSP JSP

<form:form>

<table>

<tr>

<td>Interests:</td>

<td>

<%--Propertyisofanarrayoroftypejava.util.Collection

<form:checkboxespath="preferences.interests"items="${interestList}"/>

</td>

</tr>

</table>

</form:form>

“interestList” List Mapmapmap“itemLabel”

13.9.6.radiobutton“radio”HTML“input”

<tr>

<td>Sex:</td>

<td>Male:<form:radiobuttonpath="sex"value="M"/><br/>

Female:<form:radiobuttonpath="sex"value="F"/></td>

</tr>

13.9.7.radiobuttons“radio”HTML“input”checkboxes radiobuttons

map map“itemValue”“itemLabel”

<tr>

<td>Sex:</td>

<td><form:radiobuttonspath="sex"items="${sexOptions}"/></td>

</tr>

13.9.8.password“password”HTML“input”

<tr>

<td>Password:</td>

<td>

<form:passwordpath="password"/>

</td>

</tr>

“ showPassword”true

<tr>

<td>Password:</td>

<td>

<form:passwordpath="password"value="^76525bvHGq"showPassword="true"/>

</td>

</tr>

13.9.9.selectHTML“select” option

User

<tr>

<td>Skills:</td>

<td><form:selectpath="skills"items="${skills}"/></td>

</tr>

User“Skills”HTML

<tr>

<td>Skills:</td>

<td><selectname="skills"multiple="true">

<optionvalue="Potions">Potions</option>

<optionvalue="Herbology"selected="selected">Herbology</option>

<optionvalue="Quidditch">Quidditch</option></select>

</td>

</tr>

13.9.10.optionHTML“option”“selected”

<tr>

<td>House:</td>

<td>

<form:selectpath="house">

<form:optionvalue="Gryffindor"/>

<form:optionvalue="Hufflepuff"/>

<form:optionvalue="Ravenclaw"/>

<form:optionvalue="Slytherin"/>

</form:select>

</td>

</tr>

UserGryffindorGryffindor·Hogwarts—— “House”HTML

<tr>

<td>House:</td>

<td>

<selectname="house">

<optionvalue="Gryffindor"selected="selected">Gryffindor</option>

<optionvalue="Hufflepuff">Hufflepuff</option>

<optionvalue="Ravenclaw">Ravenclaw</option>

<optionvalue="Slytherin">Slytherin</option>

</select>

</td>

</tr>

13.9.11.optionsHTML“option”“selected”

<tr>

<td>Country:</td>

<td>

<form:selectpath="country">

<form:optionvalue="-"label="--PleaseSelect"/>

<form:optionsitems="${countryList}"itemValue="code"itemLabel="name"/>

</form:select>

</td>

</tr>

User“Country”HTML

<tr>

<td>Country:</td>

<td>

<selectname="country">

<optionvalue="-">--PleaseSelect</option>

<optionvalue="AT">Austria</option>

<optionvalue="UK"selected="selected">UnitedKingdom</option>

<optionvalue="US">UnitedStates</option>

</select>

</td>

</tr>

optionoptionsHTML JSP“--PleaseSelect”

13.9.12.textareaHTML“textarea”

<tr>

<td>Notes:</td>

<td><form:textareapath="notes"rows="3"cols="20"/></td>

<td><form:errorspath="notes"/></td>

</tr>

13.9.13.hidden“hidden”HTML“input” HTMLinputinput

<form:hiddenpath="house"/>

“house”HTML

<inputname="house"type="hidden"value="Gryffindor"/>

13.9.14.errorsHTML“span”firstNamelastName UserUserValidator

publicclassUserValidatorimplementsValidator{

publicbooleansupports(Classcandidate){

returnUser.class.isAssignableFrom(candidate);

}

publicvoidvalidate(Objectobj,Errorserrors){

ValidationUtils.rejectIfEmptyOrWhitespace(errors,"firstName","required","Fieldisrequired.");

ValidationUtils.rejectIfEmptyOrWhitespace(errors,"lastName","required","Fieldisrequired.");

}

}

form.jsp

<form:form>

<table>

<tr>

<td>FirstName:</td>

<td><form:inputpath="firstName"/></td>

<%--ShowerrorsforfirstNamefield--%>

<td><form:errorspath="firstName"/></td>

</tr>

<tr>

<td>LastName:</td>

<td><form:inputpath="lastName"/></td>

<%--ShowerrorsforlastNamefield--%>

<td><form:errorspath="lastName"/></td>

</tr>

<tr>

<tdcolspan="3">

<inputtype="submit"value="SaveChanges"/>

</td>

</tr>

</table>

</form:form>

firstNamelastName HTML

<formmethod="POST">

<table>

<tr>

<td>FirstName:</td>

<td><inputname="firstName"type="text"value=""/></td>

<%--AssociatederrorstofirstNamefielddisplayed--%>

<td><spanname="firstName.errors">Fieldisrequired.</span></td>

</tr>

<tr>

<td>LastName:</td>

<td><inputname="lastName"type="text"value=""/></td>

<%--AssociatederrorstolastNamefielddisplayed--%>

<td><spanname="lastName.errors">Fieldisrequired.</span></td>

</tr>

<tr>

<tdcolspan="3">

<inputtype="submit"value="SaveChanges"/>

</td>

</tr>

</table>

</form>

errors

path="*"

path="lastName*"lastName

<form:form>

<form:errorspath="*"cssClass="errorBox"/>

<table>

<tr>

<td>FirstName:</td>

<td><form:inputpath="firstName"/></td>

<td><form:errorspath="firstName"/></td>

</tr>

<tr>

<td>LastName:</td>

<td><form:inputpath="lastName"/></td>

<td><form:errorspath="lastName"/></td>

</tr>

<tr>

<tdcolspan="3">

<inputtype="submit"value="SaveChanges"/>

</td>

</tr>

</table>

</form:form>

HTML

<formmethod="POST">

<spanname="*.errors"class="errorBox">Fieldisrequired.<br/>Fieldisrequired.</span>

<table>

<tr>

<td>FirstName:</td>

<td><inputname="firstName"type="text"value=""/></td>

<td><spanname="firstName.errors">Fieldisrequired.</span></td>

</tr>

<tr>

<td>LastName:</td>

<td><inputname="lastName"type="text"value=""/></td>

<td><spanname="lastName.errors">Fieldisrequired.</span></td>

</tr>

<tr>

<tdcolspan="3">

<inputtype="submit"value="SaveChanges"/>

</td>

</tr>

</form>

13.10. Spring HandlerExceptionResolvers

Web web.xmlexceptionmappings

HandlerExceptionResolver resolveExceptionExceptionHandler

ModelAndView SimpleMappingExceptionResolver

13.11.conventionoverconfiguration……SpringWebMVC

SpringWebMVC

13.11.1. ControllerClassNameHandlerMapping

ControllerClassNameHandlerMappingHandlerMapping URL

Controller

publicclassViewShoppingCartControllerimplementsController{

publicModelAndViewhandleRequest(HttpServletRequestrequest,HttpServletResponseresponse){

//theimplementationisnothugelyimportantforthisexample...

}

}

SpringWebMVC

<beanclass="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>

<beanid="viewShoppingCart"class="x.y.z.ViewShoppingCartController">

<!--injectdependenciesasrequired...-->

</bean>

ControllerClassNameHandlerMappinghandler ControllerbeanController

WelcomeController“ /welcome*”URL

HomeController“ /home*”URL

IndexController“ /index*”URL

RegisterController“ /register*”URL

DisplayShoppingCartController“ /displayshoppingcart*URL———— Controller

MultiActionControllerMultiActionController

AdminController“ /admin/*”URL

CatalogController“ /catalog/*”URLControllerxxxController ControllerClassNameHandlerMapping———— SimpleUrlHandlerMapping

ControllerClassNameHandlerMappingAbstractHandlerMappingHandlerMappingHandlerInterceptor

13.11.2. ModelMapModelAndView

ModelMapMap View

publicclassDisplayShoppingCartControllerimplementsController{

publicModelAndViewhandleRequest(HttpServletRequestrequest,HttpServletResponseresponse){

ListcartItems=//getaListofCartItemobjects

Useruser=//gettheUserdoingtheshopping

ModelAndViewmav=newModelAndView("displayShoppingCart");

mav.addObject(cartItems);<--lookma,noname,justtheobject

mav.addObject(user);<--andagainma!

returnmav;

}

}

ModelAndViewModelMapMap ModelMap

x.y.User“ user”

x.y.Registration“ registration”

SpringWebMVCListModelAndView“people”“ PrincipleofLeastSurprise ”

x.y.Foo“ foo”

java.util.HashMap“ hashMap”“ hashMap

nullIllegalArgumentException null

SetList

x.y.Userx.y.User[]“ userList”

x.y.Userx.y.Foo[]“ fooList”

x.y.Userjava.util.ArrayList

“ userList”

x.y.Foojava.util.HashSet

“ fooList”

java.util.ArrayList addObject(..)

13.11.3. RequestToViewNameTranslator

RequestToViewNameTranslatorDefaultRequestToViewNameTranslator

DefaultRequestToViewNameTranslatorURL

publicclassRegistrationControllerimplementsController{

publicModelAndViewhandleRequest(HttpServletRequestrequest,HttpServletResponseresponse){

//processtherequest...

ModelAndViewmav=newModelAndView();

//adddataasnecessarytothemodel...

returnmav;

//noticethatnoVieworlogicalviewnamehasbeenset

}

}

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"

"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

<!--thisbeanwiththewellknownnamegeneratesviewnamesforus-->

<beanid="viewNameTranslator"class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/>

<beanclass="x.y.RegistrationController">

<!--injectdependenciesasnecessary-->

</bean>

<!--mapsrequestURLstoControllernames-->

<beanclass="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>

<beanid="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<propertyname="prefix"value="/WEB-INF/jsp/"/>

<propertyname="suffix"value=".jsp"/>

</bean>

</beans>

handleRequest(..) ModelAndViewViewDefaultRequestToViewNameTranslator RegistrationController

ControllerClassNameHandlerMapping“ http://localhost/registration.html”URLDefaultRequestToViewNameTranslator“ registration”InternalResourceViewResolver bean“ /WEB-INF/jsp/registration.jsp”

DefaultRequestToViewNameTranslator beanDefaultRequestToViewNameTranslator SpringWebMVCDispatcherServlet

DefaultRequestToViewNameTranslatorbeanDefaultRequestToViewNameTranslatorJavadoc

13.12.XMLSpring2.5MVCSpring2.5MVC @RequestMapping@RequestParam@ModelAttributeServletMVCPortletMVCPortlet

SpringPetClinic WebPetClinicWebMVC imagedbmulti-action“ samples/imagedb” imagedb

13.12.1.dispatcherHandlerMapping/ HandlerAdapterdispatcher@RequestMapping DispatcherServletDispatcherPortlet

HandlerMappingsHandlerAdapters DefaultAnnotationHandlerMapping

AnnotationMethodHandlerAdapter——@RequestMapping

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<beanclass="org.springframework.web.servlet.mvc.DefaultAnnotationHandlerMapping"/>

<beanclass="org.springframework.web.servlet.mvc.AnnotationMethodHandlerAdapter"/>

...(controllerbeandefinitions)...

</beans>

DefaultAnnotationHandlerMapping/ AnnotationMethodHandlerAdapter

PathMatcherWebBindingInitializer

13.12.2. @Controller

@Controller ServletAPIServlet@Controller DispatcherbeandispatcherSpringbean XML

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:p="http://www.springframework.org/schema/p"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beans

http://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/context

http://www.springframework.org/schema/context/spring-context-2.5.xsd">

<context:component-scanbase-package="org.springframework.samples.petclinic.web"/>

...

</beans>

13.12.3. @RequestMapping

@RequestMapping“/editPet.do”URL“GET/POST”HTTP

@RequestMappingController@RequestMapping Controller SimpleFormController

PetClinic

@Controller

@RequestMapping("/editPet.do")

@SessionAttributes("pet")

publicclassEditPetForm{

privatefinalClinicclinic;

@Autowired

publicEditPetForm(Clinicclinic){

this.clinic=clinic;

}

@ModelAttribute("types")

publicCollection<PetType>populatePetTypes(){

returnthis.clinic.getPetTypes();

}

@RequestMapping(method=RequestMethod.GET)

publicStringsetupForm(@RequestParam("petId")intpetId,ModelMapmodel){

Petpet=this.clinic.loadPet(petId);

model.addAttribute("pet",pet);

return"petForm";

}

@RequestMapping(method=RequestMethod.POST)

publicStringprocessSubmit(@ModelAttribute("pet")Petpet,BindingResultresult,

SessionStatusstatus){

newPetValidator().validate(pet,result);

if(result.hasErrors()){

return"petForm";

}

else{

this.clinic.storePet(pet);

status.setComplete();

return"redirect:owner.do?ownerId="+pet.getOwner().getId();

}

}

}

multi-actionURLURL

@Controller

publicclassClinicController{

privatefinalClinicclinic;

@Autowired

publicClinicController(Clinicclinic){

this.clinic=clinic;

}

/**

*Customhandlerforthewelcomeview.

*NotethatthishandlerreliesontheRequestToViewNameTranslatorto

*determinethelogicalviewnamebasedontherequestURL:"/welcome.do"

*->"welcome".

*/

@RequestMapping("/welcome.do")

publicvoidwelcomeHandler(){

}

/**

*Customhandlerfordisplayingvets.

*Notethatthishandlerreturnsaplain{@linkModelMap}objectinsteadof

*aModelAndView,thusleveragingconvention-basedmodelattributenames.

*ItreliesontheRequestToViewNameTranslatortodeterminethelogical

*viewnamebasedontherequestURL:"/vets.do"->"vets".

*

*@returnaModelMapwiththemodelattributesfortheview

*/

@RequestMapping("/vets.do")

publicModelMapvetsHandler(){

returnnewModelMap(this.clinic.getVets());

}

/**

*Customhandlerfordisplayinganowner.

*Notethatthishandlerreturnsaplain{@linkModelMap}objectinsteadof

*aModelAndView,thusleveragingconvention-basedmodelattributenames.

*ItreliesontheRequestToViewNameTranslatortodeterminethelogical

*viewnamebasedontherequestURL:"/owner.do"->"owner".

*

*@paramownerIdtheIDoftheownertodisplay

*@returnaModelMapwiththemodelattributesfortheview

*/

@RequestMapping("/owner.do")

publicModelMapownerHandler(@RequestParam("ownerId")intownerId){

returnnewModelMap(this.clinic.loadOwner(ownerId));

}

}

@RequestMapping

/ServletAPIPortletAPI /ServletRequest/HttpServletRequestPortletRequest/ActionRequest/RenderRequest Portletaction/renderactionrenderrequestsServletAPIPortletAPIHttpSessionPortletSessionServlet AnnotationMethodHandlerAdapter

“synchronizeOnSession”“true”org.springframework.web.context.request.WebRequest

org.springframework.web.context.request.NativeWebRequest/Servlet/PortletAPIjava.util.Localelocalejava.io.InputStream/java.io.Reader Servlet/PortletAPIInputStream/Readerjava.io.OutputStream/java.io.Writer Servlet/PortletAPIOutputStream/Writer@RequestParamServlet/Portlet

java.util.Map/org.springframework.ui.Model/org.springframework.ui.ModelMapWeb/bean @InitBinder/HandlerAdapter——AnnotationMethodHandlerAdapter“ webBindingInitializer”“mypackage.OrderAddress”“orderAddress”ModelAttribute

org.springframework.validation.Errors/org.springframework.validation.BindingResult/org.springframework.web.bind.support.SessionStatus

@SessionAttributes

13.12.4. @RequestParam

@RequestParam

PetClinic

@Controller

@RequestMapping("/editPet.do")

@SessionAttributes("pet")

publicclassEditPetForm{

//...

@RequestMapping(method=RequestMethod.GET)

publicStringsetupForm(@RequestParam("petId")intpetId

Petpet=this.clinic.loadPet(petId);

model.addAttribute("pet",pet);

return"petForm";

}

//...

@RequestParamrequiredfalse @RequestParam(value="id",

required="false")

13.12.5. @ModelAttribute

@ModelAttribute @ModelAttribute

java.lang.Object

@ModelAttribute populatePetTypes()@ModelAttribute@RequestMapping

@Controller

@RequestMapping("/editPet.do")

@SessionAttributes("pet")

publicclassEditPetForm{

//...

@ModelAttribute("types")

publicCollection<PetType>populatePetTypes(){

returnthis.clinic.getPetTypes();

}

@RequestMapping(method=RequestMethod.POST)

publicStringprocessSubmit(@ModelAttribute("pet")Petpet

SessionStatusstatus){

newPetValidator().validate(pet,result);

if(result.hasErrors()){

return"petForm";

}

else{

this.clinic.storePet(pet);

status.setComplete();

return"redirect:owner.do?ownerId="+pet.getOwner().getId();

}

}

}

13.12.6. @SessionAttributes

@SessionAttributes beans

@Controller

@RequestMapping("/editPet.do")

@SessionAttributes("pet")

publicclassEditPetForm{

//...

}

13.12.7. WebDataBinder

SpringWebDataBinderPropertyEditors @InitBinder——WebBindingInitializer

13.12.7.1. @InitBinder

@InitBinderWeb @InitBinderWebDataBinder

init-binder@RequestMapping/ Init-binderWebDataBinderWebRequestjava.util.Locale

@InitBinder java.util.DateCustomDateEditor

@Controller

publicclassMyFormController{

@InitBinder

publicvoidinitBinder(WebDataBinderbinder){

SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-dd");

dateFormat.setLenient(false);

binder.registerCustomEditor(Date.class,newCustomDateEditor(dateFormat,false));

}

//...

}

13.12.7.2. WebBindingInitializer

WebBindingInitializer AnnotationMethodHandlerAdapter

PetClinicWebBindingInitializer——org.springframework.samples.petclinic.web.ClinicBindingInitializer

PetClinicPropertyEditors

<beanclass="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">

<propertyname="cacheSeconds"value="0"/>

<propertyname="webBindingInitializer">

<beanclass="org.springframework.samples.petclinic.web.ClinicBindingInitializer"/>

</property>

</bean>

13.13.SpringWebMVC

SpringSpringWebMVCSpringWebMVCSpring“ docs”SpringFramework

SethLadd“ ExpertSpringWebMVCandWebFlow”ApressSpringWebMVC

14

14.1.14.2.JSPJSTL

14.2.1.14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTL14.2.3.

14.3.Tiles14.3.1.14.3.2.Tiles

14.4.VelocityFreeMarker14.4.1.14.4.2.Context14.4.3.14.4.4.14.4.5.

14.5.XSLT14.5.1.14.5.2.

14.6.PDF/Excel14.6.1.14.6.2.

14.7.JasperReports14.7.1.14.7.2.14.7.3. ModelAndView

14.7.4.14.7.5.Exporter

14.1.SpringviewMVC VelocityXSLTJSP“” “mvc-viewresolver”viewMVC

14.2.JSPJSTLSpringJSPJSTLviewJSPJSTLJSP SpringJSP

14.2.1.SpringJSPResourceBundleViewResolver

<!--the

ResourceBundleViewResolver

-->

<beanid="viewResolver"class="org.springframework.web.servlet.view.ResourceBundleViewResolver">

<propertyname="basename"value="views"/>

</bean>

#Andasamplepropertiesfileisuses

(views.propertiesinWEB-INF/classes):

welcome.class=org.springframework.web.servlet.view.JstlView

welcome.url=/WEB-INF/jsp/welcome.jsp

productList.class=org.springframework.web.servlet.view.JstlView

productList.url=/WEB-INF/jsp/productlist.jsp

ResourceBundleViewResolverview1)class2)URLResourceBundleViewResolver

<beanid="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">

<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>

<propertyname="prefix"value="/WEB-INF/jsp/"/>

<propertyname="suffix"value=".jsp"/>

</bean>

JSP InternalResourceBundleViewResolver

14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTLJSTLview JstlViewJSTLi18N

14.2.3.SpringJSPSpringspring.jar(TLD)tagtag

14.3.TilesSpringwebTilesweb

Spring org.springframework.web.servlet.view.tiles2Tiles2TilesJava5+ org.springframework.web.servlet.view.tiles

Tiles1.x“StrutsTiles”Struts1.1+Java1.4

14.3.1.Tiles

Tilesversion2.0.4

CommonsBeanUtils

CommonsDigester

CommonsLogging

Spring

14.3.2.TilesTilesTiles

<beanid="tilesConfigurer"class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">

<propertyname="definitions">

<list>

<value>/WEB-INF/defs/general.xml</value>

<value>/WEB-INF/defs/widgets.xml</value>

<value>/WEB-INF/defs/administrator.xml</value>

<value>/WEB-INF/defs/customer.xml</value>

<value>/WEB-INF/defs/templates.xml</value>

</list>

</property>

</bean>

'WEB-INF/defs' WebApplicationContext

tilesviewsSpringweb viewsUrlBasedViewResolverResourceBundleViewResolver

14.3.2.1.UrlBasedViewResolver

UrlBasedViewResolverview viewClass

<beanid="viewResolver"class="org.springframework.web.servlet.view.UrlBasedViewResolver">

<propertyname="viewClass"value="org.springframework.web.servlet.view.tiles2.TilesView"/>

</bean>

14.3.2.2.ResourceBundleViewResolverResourceBundleViewResolver

<beanid="viewResolver"class="org.springframework.web.servlet.view.ResourceBundleViewResolver">

<propertyname="basename"value="views"/>

</bean>

...

welcomeView.class=org.springframework.web.servlet.view.tiles2.TilesView

welcomeView.url=welcome

(thisisthenameofaTilesdefinition)

vetsView.class=org.springframework.web.servlet.view.tiles2.TilesView

vetsView.url=vetsView

(again,thisisthenameofaTilesdefinition)

findOwnersForm.class=org.springframework.web.servlet.view.JstlView

findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp

...

ResourceBundleViewResolverviewTiles2 TilesViewJSTLJSPTiles1.x

14.3.2.3. SimpleSpringPreparerFactorySpringBeanPreparerFactory

SpringTiles2 PreparerFactoryTilespreparer SimpleSpringPreparerFactoryViewPreparerSpring

SpringBeanPostProcessorsSpring annotation-configViewPreparerTilespreparer

SpringBeanPreparerFactorypreparerDispatcherServletbeanSpringbean

<beanid="tilesConfigurer"class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">

<propertyname="definitions">

<list>

<value>/WEB-INF/defs/general.xml</value>

<value>/WEB-INF/defs/widgets.xml</value>

<value>/WEB-INF/defs/administrator.xml</value>

<value>/WEB-INF/defs/customer.xml</value>

<value>/WEB-INF/defs/templates.xml</value>

</list>

</property>

<!--resolvingpreparernamesasSpringbean

definitionnames-->

<propertyname="preparerFactoryClass"

value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory"/>

</bean>

14.4.VelocityFreeMarkerVelocityFreeMarkerviewSpringMVC

14.4.1.VelocityFreeMarker velocity-1.x.x.jarfreemarker-2.x.jarVelocitycommons-collections.jarjar WEB-INF/libJ2EEServerwebclasspath 'WEB-INF/lib' spring.jarSpringVelocityFreeMarkercommonscollections /lib/VelocitySpringdateToolAttributenumberToolAttribute velocity-tools-generic-1.x.jar

14.4.2.Context '*-servlet.xml'bean

<!--

beanVelocityVelocity

-->

<beanid="velocityConfig"class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">

<propertyname="resourceLoaderPath"value="/WEB-INF/velocity/"/>

</bean>

<!--

ResourceBundleXMLLocaleresourcebundle

-->

<beanid="viewResolver"class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">

<propertyname="cache"value="true"/>

<propertyname="prefix"value=""/>

<propertyname="suffix"value=".vm"/>

</bean>

<!--freemarkerconfig-->

<beanid="freemarkerConfig"class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">

<propertyname="templateLoaderPath"value="/WEB-INF/freemarker/"/>

</bean>

<!--

ResourceBundleXMLLocaleresourcebundle

-->

<beanid="viewResolver"class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">

<propertyname="cache"value="true"/>

<propertyname="prefix"value=""/>

<propertyname="suffix"value=".ftl"/>

</bean>

webapplicationcontext VelocityConfigurationFactoryBean

FreeMarkerConfigurationFactoryBean

14.4.3.*Configurerbean

ModelAndView“welcome”/WEB-INF/velocity/welcome.vm

14.4.4.Spring

14.4.4.1.velocity.propertiesVelocity

<beanid="velocityConfig"

class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">

<propertyname="configLocation

value="/WEB-INF/velocity.properties"/>

</bean>

Velocityconfigbeanvelocity“configLocation”

<beanid="velocityConfig"class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">

<propertyname="velocityProperties">

<props>

<propkey="resource.loader">file</prop>

<propkey="file.resource.loader.class">

org.apache.velocity.runtime.resource.loader.FileResourceLoader

</prop>

<propkey="file.resource.loader.path">${webapp.root}/WEB-INF/velocity</prop>

<propkey="file.resource.loader.cache">false</prop>

</props>

</property>

</bean>

SpringVelocity API Velocity

14.4.4.2.FreeMarkerFreeMarker'Settings''SharedVariables' FreeMarkerConfigurer

FreeMarkerConfiguration freemarkerSettings java.util.Properties

freemarkerVariables java.util.Map

<beanid="freemarkerConfig"class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">

<propertyname="templateLoaderPath"value="/WEB-INF/freemarker/"/>

<propertyname="freemarkerVariables">

<map>

<entrykey="xml_escape"value-ref="fmXmlEscape"/>

</map>

</property>

</bean>

<beanid="fmXmlEscape"class="freemarker.template.utility.XmlEscape"/>

settingsvariables ConfigurationFreeMarker

14.4.5.SpringJSP <spring:bind/>1.1SpringVelocityFreeMarker

14.4.5.1.spring.jar

Spring org.springframework.web.servlet.view.velocity spring.vmorg.springframework.web.servlet.view.freemarkerspring.ftl

14.4.5.2.Springhtmlvm/ftl JSP'commandName' personFormVpersonFormF

<!--velocity--><html>...

<formaction=""method="POST">Name:

#springBind("command.name")<inputtype="text"

name="${status.expression}"value="$!status.value"

/><br>#foreach($errorin

$status.errorMessages)<b>$error</b>

<br>#end<br>...<input

type="submit"value="submit"/></form>...

</html>

<!--FreeMarker'spring'

--><#import"spring.ftl"asspring/>

<html>...<formaction=""

method="POST">Name:<@spring.bind

"command.name"/><inputtype="text"

name="${spring.status.expression}"

value="${spring.status.value?default("")}"

/><br><#list

spring.status.errorMessagesaserror>

<b>${error}</b><br>

</#list><br>...<input

type="submit"value="submit"/></form>...

</html>

#springBind/<@spring.bind>'path''command'FormController “command.address.street”

web.xml defaultHtmlEscapeServletContext #springBindEscaped/<@spring.bindEscaped>HTML

14.4.5.3. HTMLspringVTLFTL

14.1.

macro VTLdefinition FTLdefinitionmessagecode

#springMessage($code) <@spring.messagecode/>

messageTextcodedefault

#springMessageText($code

$text)

<@spring.messageTextcode,

text/>

urlURLapplicationcontextroot

#springUrl($relativeUrl) <@spring.urlrelativeUrl/>

formInput #springFormInput($path

$attributes)

<@spring.formInputpath,

attributes,fieldType/>

formHiddenInput* #springFormHiddenInput($path

$attributes)

<@spring.formHiddenInput

path,attributes/>

formPasswordInput*

#springFormPasswordInput($path

$attributes)

<@spring.formPasswordInput

path,attributes/>

formTextarea #springFormTextarea($path

$attributes)

<@spring.formTextarea

path,attributes/>

formSingleSelect #springFormSingleSelect($path

$options$attributes)

<@spring.formSingleSelect

path,options,

attributes/>

formMultiSelect #springFormMultiSelect($path

$options$attributes)

<@spring.formMultiSelect

path,options,

attributes/>

formRadioButtons#springFormRadioButtons($path

$options$separator

$attributes)

<@spring.formRadioButtons

path,optionsseparator,

attributes/>

formCheckboxes#springFormCheckboxes($path

$options$separator

$attributes)

<@spring.formCheckboxes

path,options,separator,

attributes/>

showErrors #springShowErrors($separator

$classOrStyle)

<@spring.showErrors

separator,classOrStyle/>

*FTLFreeMarker formInput

'password'

path:command.name

MapmapkeysvaluesMapmapMapSortedMap TreeMapComparatorcommons-collectionsLinkedHashMapLinkedMap

radiobuttonscheckboxes"<br>"

HTMLtextarea'rows="5"'style="border:1pxsolidsilver"'classOrStyleshowErrorsCSSspan<b></b>

FTLVTL

14.4.5.3.1.

<!--NameVTL-->

...Name:#springFormInput("command.name"

"")<br>#springShowErrors("<br>"

"")<br>

formInputpathcommand.namepathshowErrorspath——fieldshowErrorsCSSFreeMarkerVelocityFTL

<@spring.formInput"command.name"/>

<@spring.showErrors"<br>"/>

nameSpringHTML

Name:<inputtype="text"name="name"value=""

><br><b>required</b>

<br><br>

textarea

14.4.5.3.2.

HTMLformSingleSelect

formMultiSelect

formRadioButtons

formCheckboxesMapFTLradioformbacking object'London''cityMap'

...Town:<@spring.formRadioButtons

"command.address.town",cityMap,""

/><br><br>

radio—— cityMap""cityMapkey-valueStringmapkeyvalueHTML

Town:<inputtype="radio"name="address.town"

value="London">London<inputtype="radio"

name="address.town"value="Paris"

checked="checked">Paris<input

type="radio"name="address.town"value="New

York">NewYork

map

protectedMapreferenceData(HttpServletRequest

request)throwsException{MapcityMap=new

LinkedHashMap();cityMap.put("LDN","London");

cityMap.put("PRS","Paris");cityMap.put("NYC",

"NewYork");

Mapm=newHashMap();m.put("cityMap",

cityMap);returnm;}

radio

Town:<inputtype="radio"name="address.town"

value="LDN">London<inputtype="radio"

name="address.town"value="PRS"

checked="checked">Paris<input

type="radio"name="address.town"value="NYC">

NewYork

14.4.5.4.HTMLXHTMLHTML 4.01Springweb.xmlHTMLXHTMLHTMLXHTMLmodel/contextxhtmlComplianttrue

##forVelocity..#set($springXhtmlCompliant=true)

<#--forFreeMarker--><#assign

xhtmlCompliant=trueinspring>

SpringXHTMLHTML

<#--HTML-->

<#assignhtmlEscape=trueinspring><#--

nextfieldwilluseHTMLescaping-->

<@spring.formInput"command.name"/>

<#assignhtmlEscape=falseinspring><#--

allfuturefieldswillbeboundwithHTMLescaping

off-->

14.5.XSLTXSLTXMLwebview XMLXMLXSLTXSLT

14.5.1.Spring ControllermodelmapXSLTMVCControllerXSLTXML

14.5.1.1.BeanSpringdispatcherservlet ViewResolver

<beanid="homeController"class="xslt.HomeController"/>

“”

14.5.1.2.MVCAbstractControllerhandler

protectedModelAndViewhandleRequestInternal(

HttpServletRequestrequest,

HttpServletResponseresponse)throwsException{

Mapmap=newHashMap();

ListwordList=newArrayList();

wordList.add("hello");

wordList.add("world");

map.put("wordList",wordList);

returnnewModelAndView("home",map);

}

XSLTSpring MVC XSLTXMLXML

14.5.1.3.XML

XML org.springframework.web.servlet.view.xslt.AbstractXsltView

createXsltSource(..)smodelMap

packagexslt;

//importsomittedforbrevity

publicclassHomePageextendsAbstractXsltView{

protectedSourcecreateXsltSource(Mapmodel,StringrootName,HttpServletRequest

request,HttpServletResponseresponse)throwsException{

Documentdocument=DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();

Elementroot=document.createElement(rootName);

Listwords=(List)model.get("wordList");

for(Iteratorit=words.iterator();it.hasNext();){

StringnextWord=(String)it.next();

ElementwordNode=document.createElement("word");

TexttextNode=document.createTextNode(nextWord);

wordNode.appendChild(textNode);

root.appendChild(wordNode);

}

returnnewDOMSource(root);

}

}

name/valuepairsname="myParam">defaultValue</xsl:param>getParameters() MapSpring1.1JSTLVelocityXSLT Springorg.springframework.web.servlet.view.xslt.FormatHelperJavadoc

14.5.1.4.“”views.propertiesxmlXMLVelocity

home.class=xslt.HomePage

home.stylesheetLocation=/WEB-INF/xsl/home.xslt

home.root=words

'.class' HomePageXMLHTML '.root'XML createXsltSource(..)

14.5.1.5.XSLT 'views.properties'

<?xmlversion="1.0"encoding="utf-8"?>

<xsl:stylesheetversion="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:outputmethod="html"omit-xml-declaration="yes"/>

<xsl:templatematch="/">

<html>

<head><title>Hello!</title></head>

<body>

<h1>MyFirstWords</h1>

<xsl:apply-templates/>

</body>

</html>

</xsl:template>

<xsl:templatematch="word">

<xsl:value-ofselect="."/><br/>

</xsl:template>

</xsl:stylesheet>

14.5.2.WARWAR

ProjectRoot|+-WebContent|+-WEB-INF|+-classes|

||+-xslt|||||+-HomePageController.class||+-

HomePage.class|||+-views.properties|+-lib|||

+-spring.jar|+-xsl|||+-home.xslt|+-

frontcontroller-servlet.xml

classpathXMLXSLTJDK1.4J2EE

14.6.PDF/Excel

14.6.1.HTML SpringPDFExcelExcel'poi'classpathPDFiText.jarSpring

14.6.2.XSLT XSLTcontrollerPDFExcelOpenOffice

14.6.2.1.view.propertiesxml

home.class=xslt.HomePage

home.stylesheetLocation=/WEB-INF/xsl/home.xslt

home.root=words

xl.class=excel.HomePage

pdf.class=pdf.HomePage

'url'

14.6.2.2.ControllercontrollerXSLT URLSpirng

14.6.2.3.ExcelXSLT Excelorg.springframework.web.servlet.view.document.AbstractExcelView

POIorg.springframework.web.servlet.view.document.AbstractJExcelView

JExcelApi buildExcelDocument

POIExcel

packageexcel;

//importsomittedforbrevity

publicclassHomePageextendsAbstractExcelView

{

protectedvoidbuildExcelDocument(Mapmodel,

HSSFWorkbookwb,HttpServletRequestreq,

HttpServletResponseresp)throwsException{

HSSFSheetsheet;HSSFRowsheetRow;HSSFCell

cell;

//Gotothefirstsheet//getSheetAt:onlyif

wbiscreatedfromanexistingdocument//sheet

=wb.getSheetAt(0);sheet=

wb.createSheet("Spring");

sheet.setDefaultColumnWidth((short)12);

//writeatextatA1cell=getCell(sheet,0,

0);setText(cell,"Spring-Exceltest");

Listwords=(List)model.get("wordList");for

(inti=0;i<words.size();i++){cell=

getCell(sheet,2+i,0);setText(cell,(String)

words.get(i));

}}}

JExcelApiExcel

packageexcel;

//importsomittedforbrevity

publicclassHomePageextendsAbstractExcelView

{

protectedvoidbuildExcelDocument(Mapmodel,

WritableWorkbookwb,HttpServletRequestrequest,

HttpServletResponseresponse)throwsException{

WritableSheetsheet=wb.createSheet("Spring");

sheet.addCell(newLabel(0,0,"Spring-Excel

test");

Listwords=(List)model.get("wordList");for

(inti=-;i<words.size();i++){

sheet.addCell(newLabel(2+i,0,

(String)words.get(i));}}}

APIJExcelApi JExcelApicontroller xl returnnewModelAndView("xl",map);

Excel

14.6.2.4.PDFPDForg.springframework.web.servlet.view.document.AbstractPdfView

buildPdfDocument()

packagepdf;

//importsomittedforbrevity

publicclassPDFPageextendsAbstractPdfView{

protectedvoidbuildPdfDocument(Mapmodel,

Documentdoc,PdfWriterwriter,

HttpServletRequestreq,HttpServletResponse

resp)throwsException{

Listwords=(List)model.get("wordList");

for(inti=0;i<words.size();i++)doc.add(

newParagraph((String)words.get(i)));

}}

controller pdf returnnewModelAndView("pdf",map);

PDF

14.7.JasperReportsJasperReports(http://jasperreports.sourceforge.net) XML4CSVExcelHTMLPDF

14.7.1.JasperReports0.6.1 JasperReports:

BeanShell

CommonsBeanUtils

CommonsCollections

CommonsDigester

CommonsLogging

iText

POIJasperReportsJAXP

14.7.2. ApplicationContextJasperReports ViewResolver

14.7.2.1. ViewResolver

ResourceBundleViewResolver

<beanid="viewResolver"class="org.springframework.web.servlet.view.ResourceBundleViewResolver">

<propertyname="basename"value="views"/>

</bean>

ResourceBundleViewResolverbasename

14.7.2.2. View

SpringJasperReportsJasperReports

14.2.JasperReportsViewClasses

JasperReportsCsvView CSV

JasperReportsHtmlView HTML

JasperReportsPdfView PDF

JasperReportsXlsView MicrosoftExcel

JasperReportsMultiFormatView 14.7.2.4“JasperReportsMultiFormatView”

simpleReport.class=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView

simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper

simpleReport JasperReportsPdfViewPDFurl

14.7.2.3.JasperReports .jrxml.jrxml .jasper SpringSpring

14.7.2.4. JasperReportsMultiFormatView

JasperReportsMultiFormatViewJasperReportsview-JasperReportsMultiFormatView

JasperReportsMultiFormatViewformatkeydiscriminatorkeyJasperReportsMultiFormatViewmappingkeyformatkeymappingkeymodelformatkeymappingkey

publicModelAndView

handleSimpleReportMulti(HttpServletRequestrequest,

HttpServletResponseresponse)throwsException{

Stringuri=request.getRequestURI();Stringformat

=uri.substring(uri.lastIndexOf(".")+1);

Mapmodel=getModel();model.put("format",format);

returnnewModelAndView("simpleReportMulti",model);

}

mappingkeyrequestURIformatkey format

key JasperReportsMultiFormatView formatKey

JasperReportsMultiFormatViewmappingkey

14.3.JasperReportsMultiFormatViewMappingKey

MappingKey ViewClasscsv JasperReportsCsvView

html JasperReportsHtmlView

pdf JasperReportsPdfView

xls JasperReportsXlsView

/foo/myReport.pdf JasperReportsPdfViewJasperReportsMultiFormatViewformatMappingsmappingkey

14.7.3. ModelAndView

Spring JasperReportsreportdatasourcereportparametersmodel Map

modelkey JRDataSourceCollectionmodel

privateMapgetModel(){Mapmodel=newHashMap();

CollectionbeanData=getBeanData();

model.put("myBeanData",beanData);returnmodel;}

JRDataSourceCollection reportDataKey

Collection JRBeanCollectionDataSource

privateMapgetModel(){Mapmodel=newHashMap();

CollectionbeanData=getBeanData();Collection

someData=getSomeData();model.put("myBeanData",

beanData);model.put("someData",someData);return

model;}

Collectionmodel

simpleReport.class=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView

simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper

simpleReport.reportDataKey=myBeanData

Spring JRDataSourceCollectionmodel

14.7.4.JasperReports

14.7.4.1.Spring

<parametername="ProductsSubReport"

class="net.sf.jasperreports.engine.JasperReport"/>

<subreport><reportElement

isPrintRepeatedValues="false"x="5"y="25"

width="325"height="20"

isRemoveLineWhenBlank="true"

backcolor="#ffcc99"/><subreportParameter

name="City">

<subreportParameterExpression><![CDATA[$F{city}]]></subreportParameterExpression>

</subreportParameter>

<dataSourceExpression><![CDATA[$P{SubReportData}]]></dataSourceExpression>

<subreportExpression

class="net.sf.jasperreports.engine.JasperReport">

<![CDATA[$P{ProductsSubReport}]]></subreportExpression>

</subreport>

ProductsSubReport net.sf.jasperreports.engine.JasperReportsJaspersubReportUrlsSpringJasperReports

<propertyname="subReportUrls">

<map><entrykey="ProductsSubReport"

value="/WEB-INF/reports/subReportChild.jrxml"/>

</map></property>

MapkeyURL SpringkeyJasperReports

14.7.4.2.SpringModelAndView subReportDataKeys

<propertyname="subReportDataKeys"

value="SubReportData"/>

key ModelAndViewkey

14.7.5.ExporterexporterPDF Springexportervalue

<beanid="htmlReport"

class="org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView">

<propertyname="url"

value="/WEB-INF/reports/simpleReport.jrxml"/>

<propertyname="exporterParameters"><map>

<entry

key="net.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER">

<value>FooterbySpring!

&lt;/td&gt;&lt;td

width="50%"&gt;&amp;nbsp;

&lt;/td&gt;&lt;/tr&gt;

&lt;/table&gt;&lt;/body&gt;&lt;/html&gt;

</value></entry></map>

</property></bean>

JasperReportsHtmlView exporternet.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER

HTML

15Web

15.1.15.2.15.3.JavaServerFaces

15.3.1.DelegatingVariableResolver15.3.2.FacesContextUtils

15.4.Struts15.4.1.ContextLoaderPlugin15.4.2.ActionSupportClasses

15.5.Tapestry15.5.1.Springbeans

15.6.WebWork15.7.

SpringWebFlowSpringWebFlowSWFWeb

SWFservletportletSpringMVCStrutsJSF SWFSWFSWF SpringWebFlow

15.1.Spring StrutsJSFTapestry WebWorkSpring Spring WebSpringWebSpringMVC WebStrutsSpringSpringSpringWebJavaJavaWeb...JavaWeb SpringWebWebStruts WebStruts Web 15.7“”

15.2.Web WebSpringSpringWebSpringMVCSpring“” Web... “businnescontext”context Web“presentationcontext” Spring“businessbeans”...Web web.xml ContextLoaderListener

<context-param/> SpringXML<listener/>

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

ListenersServletAPI2.3listenerServlet2.4 Servlet2.2 ContextLoaderServlet

<context-param/>

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>/WEB-INF/applicationContext*.xml</param-value>

</context-param>

contextConfigLocationcontext ContextLoaderListenerINF/applicationContext.xml contextSpringbeanWebApplicationContextWeb ServletContextJavaWebServletAPI ContextLoaderListener

ApplicationContext

WebApplicationContextctx=WebApplicationContextUtils.getWebApplicationContext(servletContext);

WebApplicationContextUtils ServletContextgetWebApplicationContext()

WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE NullPointerExceptions getRequiredWebApplicationContext()

ApplicationContext WebApplicationContext beanbeanbeanSpring

15.3.JavaServerFacesJavaServerFaces(JSF)WebDelegatingVariableResolver

15.3.1.DelegatingVariableResolverSpringJSFWeb DelegatingVariableResolver

Resolver faces-context.xml <faces-config/><application/> <variable-resolver/> SpringDelegatingVariableResolver

<faces-config>

<application>

<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>

<locale-config>

<default-locale>en</default-locale>

<supported-locale>en</supported-locale>

<supported-locale>es</supported-locale>

</locale-config>

<message-bundle>messages</message-bundle>

</application>

</faces-config>

DelegatingVariableResolverJSF Spring“businesscontext”WebApplicationContextJSFbeanJSFbean faces-config.xml #{userManager}

“businesscontext”bean

<managed-bean>

<managed-bean-name>userList</managed-bean-name>

<managed-bean-class>com.whatever.jsf.UserList</managed-bean-class>

<managed-bean-scope>request</managed-bean-scope>

<managed-property>

<property-name>userManager</property-name>

<value>#{userManager}</value>

</managed-property>

</managed-bean>

15.3.2.FacesContextUtils faces-config.xmlbean VariableResolver

FacesContextUtils WebApplicationContextUtils

ServletContext

ApplicationContextctx=FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());

DelegatingVariableResolverJSFSpring

15.4.StrutsStruts JavaWeb20016 JSP/ServletStrutsSpring

SpringActionbean ContextLoaderPluginSpringcontextSpring ActionSupport getWebApplicationContext()Springbean

15.4.1.ContextLoaderPluginContextLoaderPlugin Struts1.1+Struts ActionServletSpring context context WebApplicationContextContextLoaderListener contextServlet ActionServletweb.xml <servlet-name>action</servlet-name>/WEB-INF/action-servlet.xmlXML struts-config.xmlplug-ins

<plug-inclassName="org.springframework.web.struts.ContextLoaderPlugIn"/>

context‘ contextConfigLocation’

<plug-inclassName="org.springframework.web.struts.ContextLoaderPlugIn">

<set-propertyproperty="contextConfigLocation"

value="/WEB-INF/action-servlet.xml,/WEB-INF/applicationContext.xml"/>

</plug-in>

StrutsTestCaseListener plug-in bug “” struts-config.xmlSping ActionSpring(1.1.3)

Spring DelegatingRequestProcessorStruts RequestProcessor

<action-mapping> type DelegatingActionProxy

action-servlet.xmlAction struts-config.xmlservlet.xmlAction action-mapping“path”bean“name”

struts-config.xml

<actionpath="/users".../>

action-servlet.xmlActionbean“/users”

<beanname="/users".../>

15.4.1.1.DelegatingRequestProcessor struts-config.xml DelegatingRequestProcessor<controller>“processorClass” <action-mapping>

<controller>

<set-propertyproperty="processorClass"

value="org.springframework.web.struts.DelegatingRequestProcessor"/>

</controller>

ActionSpingcontext

<actionpath="/user"type="com.whatever.struts.UserAction"/>

<actionpath="/user"/>

Struts modulesbeanmodule Action<actionpath="/user"/>module“admin” <bean

name="/admin/user"/>bean

Struts Tiles <controller>DelegatingTilesRequestProcessor

15.4.1.2.DelegatingActionProxy RequestProcessor DelegatingRequestProcessor

DelegatingTilesRequestProcessor DelegatingActionProxy action-mapping

<actionpath="/user"type="org.springframework.web.struts.DelegatingActionProxy"

name="userForm"scope="request"validate="false"parameter="method">

<forwardname="list"path="/userList.jsp"/>

<forwardname="edit"path="/userForm.jsp"/>

</action>

action-servlet.xmlbean RequestProcessor

DelegatingActionProxy

ActionSpringcontextSpringbean Actionbean scope="prototype"

<beanname="/user"scope="prototype"autowire="byName"

class="org.example.web.UserAction"/>

15.4.2.ActionSupportClasses WebApplicationContextUtils ServletContextWebApplicationContext Spring ActionStrutsSpring ActionSupportActionSupport getWebApplicationContext()Action

publicclassUserActionextendsDispatchActionSupport{

publicActionForwardexecute(ActionMappingmapping,

ActionFormform,

HttpServletRequestrequest,

HttpServletResponseresponse)throwsException{

if(log.isDebugEnabled()){

log.debug("entering'delete'method...");

}

WebApplicationContextctx=getWebApplicationContext();

UserManagermgr=(UserManager)ctx.getBean("userManager");

//talktomanagerforbusinesslogic

returnmapping.findForward("success");

}

}

SpringStrutsAction-Spring SupportActionSupport,

DispatchActionSupport,

15.5.Tapestry Tapestry...“TapestryWebJava TapestryJavaServletAPI Servlet ”Spring Web Tapestry WebSpringJ2EE

TapestrySpring J2EETapestry UISpringTapestry []

“TapestryListener ”...TapestrySpring-TapestryTapestry SpringbeanTapestryTapestry HowardM.LewisShip

15.5.1.SpringbeansSpringXML

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"

"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

<!--theDataSource-->

<beanid="dataSource"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="java:DefaultDS"/>

</bean>

<beanid="hibSessionFactory"

class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">

<propertyname="dataSource"ref="dataSource"/>

</bean>

<beanid="transactionManager"

class="org.springframework.transaction.jta.JtaTransactionManager"/>

<beanid="mapper"

class="com.whatever.dataaccess.mapper.hibernate.MapperImpl">

<propertyname="sessionFactory"ref="hibSessionFactory"/>

</bean>

<!--(transactional)AuthenticationService-->

<beanid="authenticationService"

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<propertyname="transactionManager"ref="transactionManager"/>

<propertyname="target">

<beanclass="com.whatever.services.service.user.AuthenticationServiceImpl">

<propertyname="mapper"ref="mapper"/>

</bean>

</property>

<propertyname="proxyInterfacesOnly"value="true"/>

<propertyname="transactionAttributes">

<value>

*=PROPAGATION_REQUIRED

</value>

</property>

</bean>

<!--(transactional)UserService-->

<beanid="userService"

class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">

<propertyname="transactionManager"ref="transactionManager"/>

<propertyname="target">

<beanclass="com.whatever.services.service.user.UserServiceImpl">

<propertyname="mapper"ref="mapper"/>

</bean>

</property>

<propertyname="proxyInterfacesOnly"value="true"/>

<propertyname="transactionAttributes">

<value>

*=PROPAGATION_REQUIRED

</value>

</property>

</bean>

</beans>

Tapestrybean Spring TapestryauthenticationService userService bean

AuthenticationService UserServiceWeb SpringWebApplicationContextUtils.getApplicationContext(servletContext)applicationcontextservletContextJ2EEServlet UserService

WebApplicationContextappContext=WebApplicationContextUtils.getApplicationContext(

getRequestCycle().getRequestContext().getServlet().getServletContext());

UserServiceuserService=(UserService)appContext.getBean("userService");

...somecodewhichusesUserService

...Tapestry

Tapestry<4.0Tapestry4.0+BeansTapestry-Tapestry4.0+”

15.5.1.1.SpringBeansTapestryTapestry ServletContext ApplicationContextApplicationContext ServletContextWebApplicationContextUtils.getApplicationContext(servletContext)TapestryIEngine ApplicationContext

packagecom.whatever.web.xportal;

import...

publicclassMyEngineextendsorg.apache.tapestry.engine.BaseEngine{

publicstaticfinalStringAPPLICATION_CONTEXT_KEY="appContext";

/**

*@seeorg.apache.tapestry.engine.AbstractEngine#setupForRequest(org.apache.tapestry.request.RequestContext)

*/

protectedvoidsetupForRequest(RequestContextcontext){

super.setupForRequest(context);

//insertApplicationContextinglobal,ifnotthere

Mapglobal=(Map)getGlobal();

ApplicationContextac=(ApplicationContext)global.get(APPLICATION_CONTEXT_KEY);

if(ac==null){

ac=WebApplicationContextUtils.getWebApplicationContext(

context.getServlet().getServletContext()

);

global.put(APPLICATION_CONTEXT_KEY,ac);

}

}

}

Springapplicationcontext“appContext”TapestryTapestryIEngineTapestry

file:xportal.application:

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEapplicationPUBLIC

"-//ApacheSoftwareFoundation//TapestrySpecification3.0//EN"

"http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">

<application

name="WhateverxPortal"

engine-class="com.whatever.web.xportal.MyEngine">

</application>

15.5.1.2.*.page*.jwcproperty-specificationbeanbean

<property-specificationname="userService"

type="com.whatever.services.service.user.UserService">

global.appContext.getBean("userService")

</property-specification>

<property-specificationname="authenticationService"

type="com.whatever.services.service.user.AuthenticationService">

global.appContext.getBean("authenticationService")

</property-specification>

property-specificationOGNLcontextbean

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEpage-specificationPUBLIC

"-//ApacheSoftwareFoundation//TapestrySpecification3.0//EN"

"http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">

<page-specificationclass="com.whatever.web.xportal.pages.Login">

<property-specificationname="username"type="java.lang.String"/>

<property-specificationname="password"type="java.lang.String"/>

<property-specificationname="error"type="java.lang.String"/>

<property-specificationname="callback"type="org.apache.tapestry.callback.ICallback"persistent="yes"/>

<property-specificationname="userService"

type="com.whatever.services.service.user.UserService">

global.appContext.getBean("userService")

</property-specification>

<property-specificationname="authenticationService"

type="com.whatever.services.service.user.AuthenticationService">

global.appContext.getBean("authenticationService")

</property-specification>

<beanname="delegate"class="com.whatever.web.xportal.PortalValidationDelegate"/>

<beanname="validator"class="org.apache.tapestry.valid.StringValidator"lifecycle="page">

<set-propertyname="required"expression="true"/>

<set-propertyname="clientScriptingEnabled"expression="true"/>

</bean>

<componentid="inputUsername"type="ValidField">

<static-bindingname="displayName"value="Username"/>

<bindingname="value"expression="username"/>

<bindingname="validator"expression="beans.validator"/>

</component>

<componentid="inputPassword"type="ValidField">

<bindingname="value"expression="password"/>

<bindingname="validator"expression="beans.validator"/>

<static-bindingname="displayName"value="Password"/>

<bindingname="hidden"expression="true"/>

</component>

</page-specification>

15.5.1.3.Javagetter

//ourUserServiceimplementation;willcomefrompagedefinition

publicabstractUserServicegetUserService();

//ourAuthenticationServiceimplementation;willcomefrompagedefinition

publicabstractAuthenticationServicegetAuthenticationService();

Java

packagecom.whatever.web.xportal.pages;

/**

*Allowstheusertologin,byprovidingusernameandpassword.

*Aftersuccessfullyloggingin,acookieisplacedontheclientbrowser

*thatprovidesthedefaultusernameforfuturelogins(thecookie

*persistsforaweek).

*/

publicabstractclassLoginextendsBasePageimplementsErrorProperty,PageRenderListener{

/**thekeyunderwhichtheauthenticateduserobjectisstoredinthevisitas*/

publicstaticfinalStringUSER_KEY="user";

/**Thenameofthecookiethatidentifiesauser**/

privatestaticfinalStringCOOKIE_NAME=Login.class.getName()+".username";

privatefinalstaticintONE_WEEK=7*24*60*60;

publicabstractStringgetUsername();

publicabstractvoidsetUsername(Stringusername);

publicabstractStringgetPassword();

publicabstractvoidsetPassword(Stringpassword);

publicabstractICallbackgetCallback();

publicabstractvoidsetCallback(ICallbackvalue);

publicabstractUserServicegetUserService();

publicabstractAuthenticationServicegetAuthenticationService();

protectedIValidationDelegategetValidationDelegate(){

return(IValidationDelegate)getBeans().getBean("delegate");

}

protectedvoidsetErrorField(StringcomponentId,Stringmessage){

IFormComponentfield=(IFormComponent)getComponent(componentId);

IValidationDelegatedelegate=getValidationDelegate();

delegate.setFormComponent(field);

delegate.record(newValidatorException(message));

}

/**

*Attemptstologin.

*<p>

*Iftheusernameisnotknown,orthepasswordisinvalid,thenanerror

*messageisdisplayed.

**/

publicvoidattemptLogin(IRequestCyclecycle){

Stringpassword=getPassword();

//Doalittleextraworktoclearoutthepassword.

setPassword(null);

IValidationDelegatedelegate=getValidationDelegate();

delegate.setFormComponent((IFormComponent)getComponent("inputPassword"));

delegate.recordFieldInputValue(null);

//Anerror,fromavalidationfield,mayalreadyhaveoccurred.

if(delegate.getHasErrors()){

return;

}

try{

Useruser=getAuthenticationService().login(getUsername(),getPassword());

loginUser(user,cycle);

}

catch(FailedLoginExceptionex){

this.setError("Loginfailed:"+ex.getMessage());

return;

}

}

/**

*Setsupthe{@linkUser}astheloggedinuser,creates

*acookiefortheirusername(forsubsequentlogins),

*andredirectstotheappropriatepage,or

*aspecifiedpage).

**/

publicvoidloginUser(Useruser,IRequestCyclecycle){

Stringusername=user.getUsername();

//Getthevisitobject;thiswilllikelyforcethe

//creationofthevisitobjectandanHttpSession

Mapvisit=(Map)getVisit();

visit.put(USER_KEY,user);

//Afterloggingin,gototheMyLibrarypage,unlessotherwisespecified

ICallbackcallback=getCallback();

if(callback==null){

cycle.activate("Home");

}

else{

callback.performCallback(cycle);

}

IEngineengine=getEngine();

Cookiecookie=newCookie(COOKIE_NAME,username);

cookie.setPath(engine.getServletPath());

cookie.setMaxAge(ONE_WEEK);

//Recordtheuser'susernameinacookie

cycle.getRequestContext().addCookie(cookie);

engine.forgetPage(getPageName());

}

publicvoidpageBeginRender(PageEventevent){

if(getUsername()==null){

setUsername(getRequestCycle().getRequestContext().getCookieValue(COOKIE_NAME));

}

}

}

15.5.1.4.SpringBeansTapestry-Tapestry4.0+Tapestry4.0+SpringbeansTapestry Web WEB-INF/lib Spring SpringbeansTapestryJava5annotationSpring userService authenticationService

Login

packagecom.whatever.web.xportal.pages;

publicabstractclassLoginextendsBasePageimplementsErrorProperty,PageRenderListener{

@InjectObject("spring:userService")

publicabstractUserServicegetUserService();

@InjectObject("spring:authenticationService")

publicabstractAuthenticationServicegetAuthenticationService();

}

...HiveMind ServletContext SpringHiveMind

<?xmlversion="1.0"?>

<moduleid="com.javaforge.tapestry.spring"version="0.1.1">

<service-pointid="SpringApplicationInitializer"

interface="org.apache.tapestry.services.ApplicationInitializer"

visibility="private">

<invoke-factory>

<constructclass="com.javaforge.tapestry.spring.SpringApplicationInitializer">

<set-objectproperty="beanFactoryHolder"

value="service:hivemind.lib.DefaultSpringBeanFactoryHolder"/>

</construct>

</invoke-factory>

</service-point>

<!--HooktheSpringsetupintotheoverallapplicationinitialization.-->

<contribution

configuration-id="tapestry.init.ApplicationInitializers">

<commandid="spring-context"

object="service:SpringApplicationInitializer"/>

</contribution>

</module>

Java5annotationJava5annotationTapestry XML.page .jwc

<injectproperty="userService"object="spring:userService"/>

<injectproperty="authenticationService"object="spring:authenticationService"/>

SpringbeanTapestryTapestryJ2EE

15.6.WebWork WebWork...“WebWorkJavaWebJavaBean ”WebWorkWebWebWork IoC WebWorkAction“wiring”WebWork2.2WebWorkIoC IoCSpringWebWork2.2IoC SpringSpringWebWorkDRY-Don'tRepeatYourselfSpring-WebWorkWebWork WebWorkwiki Spring-WebWork

Spring-WebWorkWebWorkSpringSpring-WebWork

15.7.Web

TheStrutshomepage

TheJSFhomepage

TheTapestryhomepage

TheWebWorkhomepageWeb

TheStrutsTIprojectwiki

16PortletMVC

16.1.16.1.1.-MVCC16.1.2.-MVCV16.1.3.WebBean

16.2.DispatcherPortlet16.3.ViewRendererServlet16.4.

16.4.1.AbstractController PortletContentGenerator

16.4.2.16.4.3.Command16.4.4.PortletWrappingController

16.5.16.5.1.PortletModeHandlerMapping16.5.2.ParameterHandlerMapping16.5.3.PortletModeParameterHandlerMapping16.5.4. HandlerInterceptors16.5.5.HandlerInterceptorAdapter16.5.6.ParameterMappingInterceptor

16.6.16.7.Multipart

16.7.1. PortletMultipartResolver

16.7.2.16.8.16.9.Portlet

JSR-168JavaPortletPortletSUNJSR-168

SpringWebFlowSpringWebFlowSWFWeb

SWFservletportletSpringMVCStrutsJSF SWFSWFSWF SpringWebFlow

16.1.SpringServletWebJSR-168Portlet PortletMVCWebMVC 13 WebMVCframeworkWeb14

SpringMVCSpringPorletMVCJSR-168PortletPorletServletPortlet “”JSR-168 PortletMVCServlet- PortletSpringPortletMVCServletMVC PortletMVC ServletAbstractControllerhandleRequestInternal(..)PortletAbstractController

handleActionRequestInternal(..)

handleRenderRequestInternal(..)

DispatcherPortlet WebDispatcherServletPortletMVC-portal/portlet SpringSpring(DispatcherPortlet DispatcherServlet

16.1.1.-MVCC Controller

voidhandleActionRequest(request,response)

ModelAndViewhandleRenderRequest(request,response)

AbstractControllerSimpleFormController

16.1.2.-MVCVServlet ViewRendererServletServletServletPortlet JSPVelocity

16.1.3.WebBean

SpringPortletMVCWebBeanBeanHTTP HTTPWebApplicationContext 3.4.4“” Bean

SpringSpringPortletMVCSpringPortletMVCsamples/petportal'petportal'

16.2.DispatcherPortletPortletMVCWebMVCPortlet PorltetSpringDispatcherPortletSpring ApplicationContextDispatcherPortletPortlet Web portlet.xml

<portlet>

<portlet-name>sample</portlet-name>

<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>

<supports>

<mime-type>text/html</mime-type>

<portlet-mode>view</portlet-mode>

</supports>

<portlet-info>

<title>SamplePortlet</title>

</portlet-info>

</portlet>

DispatcherPortlet

PortletMVC DispatcherPortlet WebApplicationContext

WebApplicationContextBean PortletBeanBeanPortlet DispatcherPortletWeb WEB-INF [portlet-name]-portlet.xml

BeanDispatcherPortlet PortletSpringDispatcherPortletBean SpringBeanBeanWebApplicationContext Bean

16.1.WebApplicationContextBean

(16.5“” ) Portlet

(16.4“” )MVC Bean

(16.6“” )

(multipart) (16.7“Multipart” ) HTML

(16.8“” )

DispatcherPortlet DispatcherPortlet

PortletRequest.getLocale() Locale

ActionRequest“Multipart”

()

WebApplicationContext

WebApplicationContextportlet.xmlContextPortlet Spring DispatcherPortlet

16.2.DispatcherPortlet

contextClassWebApplicationContextPortletcontextXmlPortletApplicationContext

contextConfigLocationcontext( contextClass) context()beancontext

namespaceWebApplicationContext [portlet-name]-

portlet

viewRendererUrlViewRendererServletURL DispatcherPortlet

( 16.3“ ViewRendererServlet”)

16.3.ViewRendererServletPortletMVCWebMVCSpringWebMVC PortletResponse HttpServletRequest/HttpServletResponse View

render DispatcherPortletservlet ViewRendererServlet

DispatcherPortlet web.xmlweb ViewRendererServlet

<servlet>

<servlet-name>ViewRendererServlet</servlet-name>

<servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>ViewRendererServlet</servlet-name>

<url-pattern>/WEB-INF/servlet/view</url-pattern>

</servlet-mapping>

DispatcherPortlet

WebApplicationContext DispatcherServlet

WEB_APPLICATION_CONTEXT_ATTRIBUTEkey

ModelView ViewRendererServlet

PortletRequestDispatcher ViewRendererServlet/WEB-

INF/servlet/viewURLincludeViewRendererServlet Viewrender

DispatcherPortletviewRendererUrl ViewRendererServletURL

16.4.PortletMVCWebMVCPortletMVC org.springframework.web.portlet.mvc.Controller

publicinterfaceController{

/**

*ProcesstherenderrequestandreturnaModelAndViewobjectwhichthe

*DispatcherPortletwillrender.

*/

ModelAndViewhandleRenderRequest(RenderRequestrequest,RenderResponseresponse)

throwsException;

/**

*Processtheactionrequest.Thereisnothingtoreturn.

*/

voidhandleActionRequest(ActionRequestrequest,ActionResponseresponse)

throwsException;

}

Portlet ControllerPortlet PortletMVC-SpringWebMVC

16.4.1. AbstractControllerPortletContentGenerator

ControllerSpringPortlet ControllerAbstractControllerSpringApplicationContext

16.3.AbstractController

requireSession Controllersession SessionRequiredException

synchronizeSessionsessionhandleActionRequestInternal(..) session

renderWhenMinimized portlet truefalseportlet

cacheSeconds portlet -1

requireSession cacheSeconds AbstractController

PortletContentGeneratorAbstractControllerhandleActionRequestInternal(ActionRequest, ActionResponse)

handleRenderRequestInternal(RenderRequest,RenderResponse)

ModelAndView handleRenderRequestInternal

handleActionRequestInternal(..) handleRenderRequestInternal(..)PortletExceptionJSR-168API GenericPortletwebcontext

packagesamples;

importjavax.portlet.RenderRequest;

importjavax.portlet.RenderResponse;

importorg.springframework.web.portlet.mvc.AbstractController;

importorg.springframework.web.portlet.ModelAndView;

publicclassSampleControllerextendsAbstractController{

publicModelAndViewhandleRenderRequestInternal(

RenderRequestrequest,

RenderResponseresponse)throwsException{

ModelAndViewmav=newModelAndView("foo");

mav.addObject("message","HelloWorld!");

returnmav;

}

}

<beanid="sampleController"class="samples.SampleController">

<propertyname="cacheSeconds"value="120"/>

</bean>

webcontext

16.4.2.AbstractControllerSpringPortletMVCMVCParameterizableViewController webcontextPortletModeNameViewController PortletPortletView

PortletMode.VIEW“View”

16.4.3.CommandSpringPortletMVCSpringWebMVC commandcontrollersPortletRequest Command

AbstractCommandController-Command

AbstractFormController-AbstractFormController (

SimpleFormController- AbstractFormControllercommandSimpleFormController command

AbstractWizardFormController– AbstractFormController

command javadoc

16.4.4.PortletWrappingControllerportlet DispatcherPortletController

<beanid="wrappingController"

class="org.springframework.web.portlet.mvc.PortletWrappingController">

<propertyname="portletClass"value="sample.MyPortlet"/>

<propertyname="portletName"value="my-portlet"/>

<propertyname="initParameters">

<value>

config=/WEB-INF/my-portlet-config.xml

</value>

</property>

</bean>

portlet JSR-168MyFacesOpenSessionInViewInterceptor

16.5.portlet“”“” DispatcherPortlet DispatcherPortletHandlerMapping HandlerExecutionChainHandlerExecutionChain DispatcherPortletchain( )SpringWebMVCURLPortletURL portletSpringPortletMVC AbstractHandlerMapping

interceptors: HandlerInterceptor 16.5.4 “

HandlerInterceptors”

defaultHandler:

order:Springorder ( org.springframework.core.Ordered)

lazyInitHandlers:Lazy (prototypelazy)false

16.5.1.PortletModeHandlerMappingportlet'view','edit','help'

<beanid="portletModeHandlerMapping"

class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">

<propertyname="portletModeMap">

<map>

<entrykey="view"value-ref="viewHandler"/>

<entrykey="edit"value-ref="editHandler"/>

<entrykey="help"value-ref="helpHandler"/>

</map>

</property>

</bean>

16.5.2.ParameterHandlerMappingportlet keyParameterHandlerMapping 'action'

bean

<beanid="parameterHandlerMapping"

class="org.springframework.web.portlet.handler.ParameterHandlerMapping”>

<propertyname="parameterMap">

<map>

<entrykey="add"value-ref="addItemHandler"/>

<entrykey="edit"value-ref="editItemHandler"/>

<entrykey="delete"value-ref="deleteItemHandler"/>

</map>

</property>

</bean>

16.5.3.PortletModeParameterHandlerMapping PortletModeParameterHandlerMapping portlet“action” parameterNameportlet portletportletbean

<beanid="portletModeParameterHandlerMapping"

class="org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping">

<propertyname="portletModeParameterMap">

<map>

<entrykey="view"><!--'view'portletmode-->

<map>

<entrykey="add"value-ref="addItemHandler"/>

<entrykey="edit"value-ref="editItemHandler"/>

<entrykey="delete"value-ref="deleteItemHandler"/>

</map>

</entry>

<entrykey="edit"><!--'edit'portletmode-->

<map>

<entrykey="prefs"value-ref="prefsHandler"/>

<entrykey="resetPrefs"value-ref="resetPrefsHandler"/>

</map>

</entry>

</map>

</property>

</bean>

PortletModeHandlerMapping

16.5.4. HandlerInterceptorsSpring principalSpringorg.springframework.web.portlet HandlerInterceptor servlet(preHandle)( postHandle)( afterCompletion)preHandle true

postHandleRenderRequest ActionRequestRenderRequest preHandle

afterCompletion

16.5.5.HandlerInterceptorAdapterservletportlet HandlerInterceptor HandlerInterceptorAdapter

16.5.6.ParameterMappingInterceptorPortletParameterMappingInterceptor ParameterHandlerMapping

PortletModeParameterHandlerMappingRenderRequest ActionRequest preHandleActionResponsesetRenderParameter

16.6.SpringPortleMVCSprintWebMVCViewViewResolver

portletHTML JSP/JSTLVelocityFreeMakerXSLTportlet

portletHTTP(ActionResponsesendRedirect(..)portal)PortletMVCRedirectView'redirect:'

PortletMVC'forward:' portletURLURLURL

JSPSpringTaglibSpringtaglibServletportlet

16.7.MultipartSpringPortletMVCWebMVCmultipartportletPortletMultipartResolvermultipartorg.springframework.web.portlet.multipart SpringPortletMultipartResolver CommonsFileUploadSpringPortletmultipartmultipart webcontextmultipartDispatcherPortletmultipart multipartcontextPortletMultipartResolver multipart

PortletMultipartResolverbean id" PortletMultipartResolver" PortletMultipartResolver

DispatcherPortlet PortletMultipartResolvermultipart

16.7.1. PortletMultipartResolver

CommonsPortletMultipartResolver

<beanid="portletMultipartResolver"

class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver">

<!--byte-->

<propertyname="maxUploadSize"value="100000"/>

</bean>

multipartjar CommonsMultipartResolver

1.1 CommonsFileUploadJSR-168PortletMVCmultipart DispatcherPortlet

ActionRequest MultipartActionRequest MultipartActionRequest

multipartmultipartRenderRequestmultipart ActionRequest

16.7.2. PortletMultipartResolver SpringJSP/HTML

<h1>Pleaseuploadafile</h1>

<formmethod="post"action="<portlet:actionURL/>"enctype="multipart/form-data">

<inputtype="file"name="file"/>

<inputtype="submit"/>

</form>

bean“File” byte[](enctype="multipart/form-data"

() ByteArrayMultipartFileEditorbean

<beanid="portletMultipartResolver"

class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver"/>

<beanid="portletModeHandlerMapping"

class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">

<propertyname="portletModeMap">

<map>

<entrykey="view"value-ref="fileUploadController"/>

</map>

</property>

</bean>

<beanid="fileUploadController"class="examples.FileUploadController">

<propertyname="commandClass"value="examples.FileUploadBean"/>

<propertyname="formView"value="fileuploadform"/>

<propertyname="successView"value="confirmation"/>

</bean>

publicclassFileUploadControllerextendsSimpleFormController{

publicvoidonSubmitAction(

ActionRequestrequest,

ActionResponseresponse,

Objectcommand,

BindExceptionerrors)

throwsException{

//castthebean

FileUploadBeanbean=(FileUploadBean)command;

//let'sseeifthere'scontentthere

byte[]file=bean.getFile();

if(file==null){

//hmm,that'sstrange,theuserdidnotuploadanything

}

//dosomethingwiththefilehere

}

protectedvoidinitBinder(

PortletRequestrequest,PortletRequestDataBinderbinder)

throwsException{

//toactuallybeabletoconvertMultipartinstancetobyte[]

//wehavetoregisteracustomeditor

binder.registerCustomEditor(byte[].class,newByteArrayMultipartFileEditor());

//nowSpringknowshowtohandlemultipartobjectandconvert

}

}

publicclassFileUploadBean{

privatebyte[]file;

publicvoidsetFile(byte[]file){

this.file=file;

}

publicbyte[]getFile(){

returnfile;

}

}

FileUploadBean byte[]

publicclassFileUploadControllerextendsSimpleFormController{

publicvoidonSubmitAction(

ActionRequestrequest,

ActionResponseresponse,

Objectcommand,

BindExceptionerrors)throwsException{

//castthebean

FileUploadBeanbean=(FileUploadBean)command;

//let'sseeifthere'scontentthere

Stringfile=bean.getFile();

if(file==null){

//hmm,that'sstrange,theuserdidnotuploadanything

}

//dosomethingwiththefilehere

}

protectedvoidinitBinder(

PortletRequestrequest,PortletRequestDataBinderbinder)throwsException{

//toactuallybeabletoconvertMultipartinstancetoaString

//wehavetoregisteracustomeditor

binder.registerCustomEditor(String.class,

newStringMultipartFileEditor());

//nowSpringknowshowtohandlemultipartobjectsandconvert

}

}

publicclassFileUploadBean{

privateStringfile;

publicvoidsetFile(Stringfile){

this.file=file;

}

publicStringgetFile(){

returnfile;

}

}

MultipartFile

publicclassFileUploadControllerextendsSimpleFormController{

publicvoidonSubmitAction(

ActionRequestrequest,

ActionResponseresponse,

Objectcommand,

BindExceptionerrors)throwsException{

//castthebean

FileUploadBeanbean=(FileUploadBean)command;

//let'sseeifthere'scontentthere

MultipartFilefile=bean.getFile();

if(file==null){

//hmm,that'sstrange,theuserdidnotuploadanything

}

//dosomethingwiththefilehere

}

}

publicclassFileUploadBean{

privateMultipartFilefile;

publicvoidsetFile(MultipartFilefile){

this.file=file;

}

publicMultipartFilegetFile(){

returnfile;

}

}

16.8.WebMVCPortletMVC HandlerExceptionResolver PortletMVCSimpleMappingExceptionResolver

16.9.PortletSpringPortletMVCJSR-168Portletportal/portletservletWeb PortletservletWebPortletPortletServletContextServlet portlet.xml

JSR-168Portlet “”PortletPortletPortletPortlet web.xml PortletServletServletWebPortletServletPortletWebPortletPortletJSPTabportalPortlet ()portalPortlet web.xmlportal ViewRendererServletPortlet

IV.SpringFrameworkJ2EE

17 SpringWeb

18 EnterpriseJavaBeans(EJB)

19 JMS(JavaMessageService)

20 JMX

21 JCACCI

22 Spring

23 Spring(Scheduling)(ThreadPooling)

24

25

17.SpringWeb17.1.17.2.RMI

17.2.1.RmiServiceExporter17.2.2.

17.3.HessianBurlapHTTP17.3.1.Hessianco.DispatcherServlet17.3.2.HessianServiceExporterbean17.3.3.17.3.4.Burlap17.3.5.HessianBurlapHTTPBasic

17.4.HTTP17.4.1.Exposingtheserviceobject17.4.2.

17.5.WebServices17.5.1.JAX-RPCservletweb17.5.2.JAX-RPCweb17.5.3.JAX-RPCBean17.5.4.JAX-RPC17.5.5.JAX-WSservletweb17.5.6.JAX-WSweb17.5.7.SpringJAX-WSRI17.5.8.JAX-WSweb17.5.9.XFireWeb

17.6.JMS17.6.1.17.6.2.

17.7.17.8.

18.EnterpriseJavaBeans(EJB)18.1.18.2.EJB

18.2.1.18.2.2.SessionBean(SLSB)18.2.3.SLSB18.2.4.AccessingEJB2.xSLSBsversusEJB3SLSBs

18.3.SpringEJB18.3.1.EJB2.xbaseclasses18.3.2.EJB3

19.JMS(JavaMessageService)19.1.19.2.SpringJMS

19.2.1.JmsTemplate19.2.2.19.2.3.19.2.4.19.2.5.

19.3.19.3.1.19.3.2.SessionCallback ProducerCallback

19.4.19.4.1.19.4.2.-POJO19.4.3.SessionAwareMessageListener19.4.4.MessageListenerAdapter19.4.5.

19.5.JCA19.6.JMS

20.JMX20.1.20.2.BeanJMX

20.2.1.MBeanServer20.2.2.MBeanServer20.2.3.MBean20.2.4.MBean20.2.5.

20.3.Bean20.3.1.MBeanInfoAssembler20.3.2.20.3.3.JDK5.020.3.4.20.3.5.AutodetectCapableMBeanInfoAssembler20.3.6.Java20.3.7.MethodNameBasedMBeanInfoAssembler

20.4.BeanObjectName20.4.1. PropertiesProperties

20.4.2.MetadataNamingStrategy20.4.3.<context:mbean-export/>

20.5.JSR-16020.5.1.20.5.2.20.5.3.Burlap/Hessian/SOAPJMX

20.6.MBean20.7.

20.7.1.20.7.2.

20.8.

21.JCACCI21.1.21.2.CCI

21.2.1.21.2.2.SpringConnectionFactory21.2.3.CCI21.2.4.CCI

21.3.SpringCCI21.3.1.21.3.2.CciTemplate21.3.3.DAO21.3.4.21.3.5.21.3.6.CCIConnectionInteraction21.3.7.CciTemplate

21.4.CCI21.4.1.MappingRecordOperation21.4.2.MappingCommAreaOperation21.4.3.21.4.4.21.4.5.MappingRecordOperation21.4.6.MappingCommAreaOperation

21.5.

22.Spring22.1.22.2.Spring

22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator

22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.

23.Spring(Scheduling)(ThreadPooling)23.1.23.2.OpenSymphonyQuartz

23.2.1.JobDetailBean23.2.2. MethodInvokingJobDetailFactoryBean

23.2.3.triggersSchedulerFactoryBean23.3.JDKTimer

23.3.1.timers23.3.2. MethodInvokingTimerTaskFactoryBean

23.3.3. TimerFactoryBean

23.4.SpringTaskExecutor23.4.1.TaskExecutor23.4.2.TaskExecutor23.4.3.TaskExecutor

24.24.1.24.2.24.3.bean

24.3.1.24.3.2.JRubybeans24.3.3.Groovybeans24.3.4.BeanShellbeans

24.4.24.4.1.SpringMVC24.4.2.Validator

24.5.Bitsandbobs24.5.1.AOP-bean24.5.2.

24.6.

25.25.1.25.2.Spring25.3.

25.3.1.@Required

25.3.2.Spring@Annotations25.4.JakartaCommonsAttributes25.5.SpringAOP

25.5.1.25.5.2.

17SpringWeb

17.1.17.2.RMI

17.2.1.RmiServiceExporter17.2.2.

17.3.HessianBurlapHTTP17.3.1.Hessianco.DispatcherServlet17.3.2.HessianServiceExporterbean17.3.3.17.3.4.Burlap17.3.5.HessianBurlapHTTPBasic

17.4.HTTP17.4.1.Exposingtheserviceobject17.4.2.

17.5.WebServices17.5.1.JAX-RPCservletweb17.5.2.JAX-RPCweb17.5.3.JAX-RPCBean17.5.4.JAX-RPC17.5.5.JAX-WSservletweb17.5.6.JAX-WSweb17.5.7.SpringJAX-WSRI17.5.8.JAX-WSweb17.5.9.XFireWeb

17.6.JMS17.6.1.17.6.2.

17.7.17.8.

17.1.SpringSpringSpringPOJOSpring

RMI RmiProxyFactoryBean RmiServiceExporterSpringRMIjava.rmi.Remotejava.rmi.RemoteExceptionRMIJava

SpringHTTPSpringHTTPJavaJavaRMIHttpInvokerProxyFactoryBean HttpInvokerServiceExporter

Hessian HessianProxyFactoryBean HessianServiceExporter

CauchoHTTPBurlapBurlapCauchoXMLHessianSpringBurlapProxyFactoryBean BurlapServiceExporter

JAXRPCSpringJAX-RPCJ2EE1.4'swwebserviceAPIWebservicesJAX-WS.Spring(JavaEE5Java6JAX-RPC)WebServices

JMS.JmsInvokerServiceExporterJmsInvokerProxyFactoryBeanJMS.

Spring

publicclassAccountimplementsSerializable{

privateStringname;

publicStringgetName();

publicvoidsetName(Stringname){

this.name=name;

}

}

publicinterfaceAccountService{

publicvoidinsertAccount(Accountaccount);

publicListgetAccounts(Stringname);

}

publicinterfaceRemoteAccountServiceextendsRemote{

publicvoidinsertAccount(Accountaccount)throwsRemoteException;

publicListgetAccounts(Stringname)throwsRemoteException;

}

//

publicclassAccountServiceImplimplementsAccountService{

publicvoidinsertAccount(Accountacc){

//……

}

publicListgetAccounts(Stringname){

//……

}

}

RMIRMIHessian

17.2.RMISpringRMIRMISpringRMIEJBRMISpring

17.2.1. RmiServiceExporter

RmiServiceExporterAccountServiceRMI RmiProxyFactoryBeanRMIRMI RmiServiceExporterRMIRMISpring

<beanid="accountService"class="example.AccountServiceImpl">

<!--DAO-->

</bean>

RmiServiceExporter

<beanclass="org.springframework.remoting.rmi.RmiServiceExporter">

<!--bean-->

<propertyname="serviceName"value="AccountService"/>

<propertyname="service"ref="accountService"/>

<propertyname="serviceInterface"value="example.AccountService"/>

<!--1199-->

<propertyname="registryPort"value="1199"/>

</bean>

RMIRMI rmi://HOST:1199/AccountServiceURL

servicePort(0)..

17.2.2.AccountServiceaccount

publicclassSimpleObject{

privateAccountServiceaccountService;

publicvoidsetAccountService(AccountServiceaccountService){

this.accountService=accountService;

}

}

Spring

<beanclass="example.SimpleObject">

<propertyname="accountService"ref="accountService"/>

</bean>

<beanid="accountService"class="org.springframework.remoting.rmi.RmiProxyFactoryBean">

<propertyname="serviceUrl"value="rmi://HOST:1199/AccountService"/>

<propertyname="serviceInterface"value="example.AccountService"/>

</bean>

accountSpring RmiServiceExporteraccount RmiProxyFactoryBean

17.3.HessianBurlapHTTPHessianHTTPCaucho http://www.caucho.comHessian

17.3.1.Hessianco. DispatcherServlet

HessianServletHTTPSpringWebMVC DispatcherServletServletServlet web.xml

<servlet>

<servlet-name>remoting</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

<servlet-mapping>

<servlet-name>remoting</servlet-name>

<url-pattern>/remoting/*</url-pattern>

</servlet-mapping>

SpringDispatcherServlet 'WEB-INF''remoting-servlet.xml'(servlet)SpringSpring HttpRequestHandlerServlet 'WEB-

INF/applicationContext.xml'exporterservletexporterbeanservletexporterbean

17.3.2. HessianServiceExporterbean remoting-servlet.xml HessianServiceExporter

<beanid="accountService"class="example.AccountServiceImpl">

<!--anyadditionalproperties,maybeaDAO?-->

</bean>

<beanname="/AccountService"class="org.springframework.remoting.caucho.HessianServiceExporter">

<propertyname="service"ref="accountService"/>

<propertyname="serviceInterface"value="example.AccountService"/>

</bean>

BeanNameUrlHandlerMappingURLbeanURL

http://HOST:8080/remoting/AccountService, HessianServiceExporter( 'WEB-INF/applicationContext.xml'):

<beanname="accountExporter"class="org.springframework.remoting.caucho.HessianServiceExporter">

<propertyname="service"ref="accountService"/>

<propertyname="serviceInterface"value="example.AccountService"/>

</bean>

, 'web.xml'exporterservletexporterrequest/remoting/AccountServiceservletexporterbean

<servlet>

<servlet-name>accountExporter</servlet-name>

<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>accountExporter</servlet-name>

<url-pattern>/remoting/AccountService</url-pattern>

</servlet-mapping>

17.3.3.HessianProxyFactoryBeanRMIbeanbean SimpleObject

AccountServiceaccounts

<beanclass="example.SimpleObject">

<propertyname="accountService"ref="accountService"/>

</bean>

<beanid="accountService"class="org.springframework.remoting.caucho.HessianProxyFactoryBean">

<propertyname="serviceUrl"value="http://remotehost:8080/remoting/AccountService"/>

<propertyname="serviceInterface"value="example.AccountService"/>

</bean>

17.3.4.BurlapBurlapXMLHessianHessian Hessian Burlap

17.3.5.HessianBurlapHTTPBasicHessianBurlapHTTPBasicHTTPHTTPServer web.xml

Hessian/BurlapProxyFactoryBeanJDBC

<beanclass="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">

<propertyname="interceptors"ref="authorizationInterceptor"/>

</bean>

<beanid="authorizationInterceptor"

class="org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor">

<propertyname="authorizedRoles"value="administrator,operator"/>

</bean>

BeanNameUrlHandlerMappingbean

http://acegisecurity.sourceforge.netAcegiSecuritySystemforSpring

17.4.HTTPBurlapHessianSpringHTTPJavaHTTPHessianBurlapHTTP

SpringJ2SECommonsHttpClientHTTPjakarta.apache.org/commons/httpclient

17.4.1.Exposingtheserviceobject

17.4.1.ExposingtheserviceobjectHTTPHessianBurlapHessian HessianServiceExporterSpringHTTPorg.springframework.remoting.httpinvoker.HttpInvokerServiceExporter

SpringWebMVCDispatcherServletAccountService()dispatcher

<beanname="/AccountService"class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">

<propertyname="service"ref="accountService"/>

<propertyname="serviceInterface"value="example.AccountService"/>

</bean>

Hessianexporter DispatcherServlet

,( 'WEB-INF/applicationContext.xml')HttpInvokerServiceExporter:

<beanname="accountExporter"class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">

<propertyname="service"ref="accountService"/>

<propertyname="serviceInterface"value="example.AccountService"/>

</bean>

, 'web.xml'exporterservletexporterbean:

<servlet>

<servlet-name>accountExporter</servlet-name>

<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>

</servlet>

<servlet-mapping>

<servlet-name>accountExporter</servlet-name>

<url-pattern>/remoting/AccountService</url-pattern>

</servlet-mapping>

17.4.2.HessianBurlapSpringHTTPPOSTURL

<beanid="httpInvokerProxy"class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">

<propertyname="serviceUrl"value="http://remotehost:8080/remoting/AccountService"/>

<propertyname="serviceInterface"value="example.AccountService"/>

</bean>

HTTP HttpInvokerProxyJ2SEHTTPhttpInvokerRequestExecutorCommonsHttpClient

<propertyname="httpInvokerRequestExecutor">

<beanclass="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>

</property>

17.5.WebServicesSpringJavawebAPI:

JAX-RPCweb

JAX-RPCweb

JAX-WSweb

JAX-WSweb

2JavawebAPIs?JAX-RPC1.1J2EE1.4webAPIRPCJavaEE5JAX-WS2.0JAX-WS2.0annotationJAX-WS2.1Java6(SunJDK1.6.0_04SunJDK1.6.0JAX-WS2.0)JDKHTTPSpringJavawebAPIJDK1.4/J2EE1.4JAX-RPCJavaEE5/Java6JAX-WSJava5J2EE1.4JAX-WSproviderJ2EE

SpringCoreJAX-RPCandJAX-WSSpringportfolio SpringWebServicesweb-web XFireSpringSpringbeanweb

17.5.1.JAX-RPCservletwebSpringJAX-RPCservlet- ServletEndpointSupport. AccountService

Spring ServletEndpointSupport

/**

*JAX-RPCcompliantRemoteAccountServiceimplementationthatsimplydelegates

*totheAccountServiceimplementationintherootwebapplicationcontext.

*

*ThiswrapperclassisnecessarybecauseJAX-RPCrequiresworkingwithdedicated

*endpointclasses.Ifanexistingserviceneedstobeexported,awrapperthat

*extendsServletEndpointSupportforsimpleapplicationcontextaccessis

*thesimplestJAX-RPCcompliantway.

*

*Thisistheclassregisteredwiththeserver-sideJAX-RPCimplementation.

*InthecaseofAxis,thishappensin"server-config.wsdd"respectivelyvia

*deploymentcalls.Thewebserviceenginemanagesthelifecycleofinstances

*ofthisclass:ASpringapplicationcontextcanjustbeaccessedhere.

*/importorg.springframework.remoting.jaxrpc.ServletEndpointSupport;

publicclassAccountServiceEndpointextendsServletEndpointSupportimplementsRemoteAccountService{

privateAccountServicebiz;

protectedvoidonInit(){

this.biz=(AccountService)getWebApplicationContext().getBean("accountService");

}

publicvoidinsertAccount(Accountacc)throwsRemoteException{

biz.insertAccount(acc);

}

publicAccount[]getAccounts(Stringname)throwsRemoteException{

returnbiz.getAccounts(name);

}

}

AccountServletEndpointSpringwebSpringAxis AxisServlet

'web.xml' 'server-config.wsdd'JPetStore OrderServiceAxisWeb

17.5.2.JAX-RPCwebSpringbeanWeb LocalJaxRpcServiceFactoryBeanJaxRpcPortProxyFactoryBeanJAX-RPC AccountService

SpringWeb-Spring

<beanid="accountWebService"class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">

<propertyname="serviceInterface"value="example.RemoteAccountService"/>

<propertyname="wsdlDocumentUrl"value="http://localhost:8080/account/services/accountService?WSDL"/>

<propertyname="namespaceUri"value="http://localhost:8080/account/services/accountService"/>

<propertyname="serviceName"value="AccountService"/>

<propertyname="portName"value="AccountPort"/>

</bean>

serviceInterface wsdlDocumentUrlWSDLURL.SpringJAX-RPCnamespaceUri.wsdltargetNamespace serviceName.wsdlportName.wsdl

web RemoteAccountServicebeanSpring

<beanid="client"class="example.AccountClientImpl">

...

<propertyname="service"ref="accountWebService"/>

</bean>

RemoteExceptionweb

publicclassAccountClientImpl{

privateRemoteAccountServiceservice;

publicvoidsetService(RemoteAccountServiceservice){

this.service=service;

}

publicvoidfoo(){

try{

service.insertAccount(...);

}

catch(RemoteExceptionex){

//ouch

}

}

}

RemoteExceptionSpringRemoteExceptionRMI

<beanid="accountWebService"class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">

<propertyname="serviceInterface"value="example.AccountService"/>

<propertyname="portInterface"value="example.RemoteAccountService"/>

</bean>

serviceInterfaceRMIRMI portInterface java.rmi.RemoteException:

publicclassAccountClientImpl{

privateAccountServiceservice;

publicvoidsetService(AccountServiceservice){

this.service=service;

}

publicvoidfoo(){

service.insertAccount(...);

}

}

"portInterface""serviceInterface" JaxRpcPortProxyFactoryBeanJAX-RPC"",RMIJavaJavawebJaxRpcPortProxyFactoryBeanjavadoc

17.5.3.JAX-RPCBeanTAccountbean

'server-config.wsdd'AxisbeanAxisbeanbean:

publicclassAxisPortProxyFactoryBeanextendsJaxRpcPortProxyFactoryBean{

protectedvoidpostProcessJaxRpcService(Serviceservice){

TypeMappingRegistryregistry=service.getTypeMappingRegistry();

TypeMappingmapping=registry.createTypeMapping();

registerBeanMapping(mapping,Account.class,"Account");

registry.register("http://schemas.xmlsoap.org/soap/encoding/",mapping);

}

protectedvoidregisterBeanMapping(TypeMappingmapping,Classtype,Stringname){

QNameqName=newQName("http://localhost:8080/account/services/accountService",name);

mapping.register(type,qName,

newBeanSerializerFactory(type,qName),

newBeanDeserializerFactory(type,qName));

}

}

17.5.4.JAX-RPCjavax.rpc.xml.handler.Handler WebSOAP Handler

jaxrpc.jarjavax.rpc.xml.handler.GenericHandler

publicclassAccountHandlerextendsGenericHandler{

publicQName[]getHeaders(){

returnnull;

}

publicbooleanhandleRequest(MessageContextcontext){

SOAPMessageContextsmc=(SOAPMessageContext)context;

SOAPMessagemsg=smc.getMessage();

try{

SOAPEnvelopeenvelope=msg.getSOAPPart().getEnvelope();

SOAPHeaderheader=envelope.getHeader();

...

}

catch(SOAPExceptionex){

thrownewJAXRPCException(ex);

}

returntrue;

}

}

AccountHandlerJAX-RPC handleRequest(..)SpringSpring postProcessJaxRpcService(..)

publicclassAccountHandlerJaxRpcPortProxyFactoryBeanextendsJaxRpcPortProxyFactoryBean{

protectedvoidpostProcessJaxRpcService(Serviceservice){

QNameport=newQName(this.getNamespaceUri(),this.getPortName());

Listlist=service.getHandlerRegistry().getHandlerChain(port);

list.add(newHandlerInfo(AccountHandler.class,null,null));

logger.info("RegisteredJAX-RPCAccountHandleronport"+port);

}

}

Springbean:

<beanid="accountWebService"class="example.AccountHandlerJaxRpcPortProxyFactoryBean">

...

</bean>

17.5.5.JAX-WSservletwebSpringJAX-WS servlet - SpringBeanAutowiringSupportAccountService

Spring SpringBeanAutowiringSupportSpring2.5 @Autowired

Springbean

/**

*JAX-WScompliantAccountServiceimplementationthatsimplydelegates

*totheAccountServiceimplementationintherootwebapplicationcontext.

*

*ThiswrapperclassisnecessarybecauseJAX-WSrequiresworkingwithdedicated

*endpointclasses.Ifanexistingserviceneedstobeexported,awrapperthat

*extendsSpringBeanAutowiringSupportforsimpleSpringbeanautowiring(through

*the@Autowiredannotation)isthesimplestJAX-WScompliantway.

*

*Thisistheclassregisteredwiththeserver-sideJAX-WSimplementation.

*InthecaseofaJavaEE5server,thiswouldsimplybedefinedasaservlet

*inweb.xml,withtheserverdetectingthatthisisaJAX-WSendpointandreacting

*accordingly.TheservletnameusuallyneedstomatchthespecifiedWSservicename.

*

*Thewebserviceenginemanagesthelifecycleofinstancesofthisclass.

*Springbeanreferenceswilljustbewiredinhere.

*/importorg.springframework.web.context.support.SpringBeanAutowiringSupport;

@WebService(serviceName="AccountService")

publicclassAccountServiceEndpointextendsSpringBeanAutowiringSupport{

@Autowired

privateAccountServicebiz;

@WebMethod

publicvoidinsertAccount(Accountacc){

biz.insertAccount(acc);

}

@WebMethod

publicAccount[]getAccounts(Stringname){

returnbiz.getAccounts(name);

}

}

SpringSpring AccountServletEndpointwebJavaEE5JAX-WSservletJavaEE5web

17.5.6.JAX-WSwebSun JDK 1.6JAX-WS provider HTTPwebSpringSimpleJaxWsServiceExporterSpringl@WebServicebeanJAX-WSJDK1.6HTTPSpringbeanJAX-WSSpringSpring @Autowired

<beanclass="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">

<propertyname="baseAddress"value="http://localhost:9999/"/>

</bean>

<beanid="accountServiceEndpoint"class="example.AccountServiceEndpoint">

...

</bean>

...

AccountServiceEndpointSpring SpringBeanAutowiringSupport

Springbean-Spring

@WebService(serviceName="AccountService")

publicclassAccountServiceEndpoint{

@Autowired

privateAccountServicebiz;

@WebMethod

publicvoidinsertAccount(Accountacc){

biz.insertAccount(acc);

}

@WebMethod

publicAccount[]getAccounts(Stringname){

returnbiz.getAccounts(name);

}

}

17.5.7.SpringJAX-WSRISunJAX-WSRIGlassFish,SpringJAX-WSCommonsJAX-WSSpringbean-Servlet JavaEE5EEwebTomcatJAX-WSRIservletSpring web.xmlJAX-WSservletJavaEE5()servletSpringbean( @Autowired)https://jax-ws-commons.dev.java.net/spring/

17.5.8.JAX-WSwebJAX-RPCSpring2beanJAX-WS web LocalJaxWsServiceFactoryBean

JaxWsPortProxyFactoryBeanJAX-WS AccountService

<beanid="accountWebService"class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">

<propertyname="serviceInterface"value="example.AccountService"/>

<propertyname="wsdlDocumentUrl"value="http://localhost:8080/account/services/accountService?WSDL"/>

<propertyname="namespaceUri"value="http://localhost:8080/account/services/accountService"/>

<propertyname="serviceName"value="AccountService"/>

<propertyname="portName"value="AccountPort"/>

</bean>

serviceInterface wsdlDocumentUrlWSDLURL.SpringJAX-RPCnamespaceUri.wsdltargetNamespace serviceName.wsdlportName.wsdlweb AccountServicebeanSpring

<beanid="client"class="example.AccountClientImpl">

...

<propertyname="service"ref="accountWebService"/>

</bean>

web

publicclassAccountClientImpl{

privateAccountServiceservice;

publicvoidsetService(AccountServiceservice){

this.service=service;

}

publicvoidfoo(){

service.insertAccount(...);

}

}

: JAX-WS @WebService,@SOAPBindingJavaJAX-WSJAX-WS

17.5.9.XFireWebXFireCodehausSOAPXFireXFirecontextcontextRemoteExporterbean WebApplicationContext DispatcherServlet

WebApplicationContext

<servlet>

<servlet-name>xfire</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

</servlet>

XFirecontext ContextLoaderListener ContextLoaderServlet

contextConfigLocations

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>classpath:org/codehaus/xfire/spring/xfire.xml</param-value>

</context-param>

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

Servlet /*XFireServletbeanXFire 'xfire-servlet.xml'

<beans>

<beanname="/Echo"class="org.codehaus.xfire.spring.remoting.XFireExporter">

<propertyname="serviceInterface"value="org.codehaus.xfire.spring.Echo"/>

<propertyname="serviceBean">

<beanclass="org.codehaus.xfire.spring.EchoImpl"/>

</property>

<!--theXFirebeanisdefinedinthexfire.xmlfile-->

<propertyname="xfire"ref="xfire"/>

</bean>

</beans>

XFireWSDLXFireXFireSpring docs.codehaus.org/display/XFIRE/Spring

17.6.JMSJMSSpringJMS- SessionThefollowinginterfaceisusedonboththeserverandtheclientside.

packagecom.foo;

publicinterfaceCheckingAccountService{

publicvoidcancelAccount(LongaccountId);

}

packagecom.foo;

publicclassSimpleCheckingAccountServiceimplementsCheckingAccountService{

publicvoidcancelAccount(LongaccountId){

System.out.println("Cancellingaccount["+accountId+"]");

}

}

JMSbean

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<beanid="connectionFactory"class="org.apache.activemq.ActiveMQConnectionFactory">

<propertyname="brokerURL"value="tcp://ep-t43:61616"/>

</bean>

<beanid="queue"class="org.apache.activemq.command.ActiveMQQueue">

<constructor-argvalue="mmm"/>

</bean>

</beans>

17.6.1.JmsInvokerServiceExporter

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<beanid="checkingAccountService"

class="org.springframework.jms.remoting.JmsInvokerServiceExporter">

<propertyname="serviceInterface"value="com.foo.CheckingAccountService"/>

<propertyname="service">

<beanclass="com.foo.SimpleCheckingAccountService"/>

</property>

</bean>

<beanclass="org.springframework.jms.listener.SimpleMessageListenerContainer">

<propertyname="connectionFactory"ref="connectionFactory"/>

<propertyname="destination"ref="queue"/>

<propertyname="concurrentConsumers"value="3"/>

<propertyname="messageListener"ref="checkingAccountService"/>

</bean>

</beans>

packagecom.foo;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

publicclassServer{

publicstaticvoidmain(String[]args)throwsException{

newClassPathXmlApplicationContext(newString[]{"com/foo/server.xml","com/foo/jms.xml"});

}

}

17.6.2.(CheckingAccountService)beanJMS

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<beanid="checkingAccountService"

class="org.springframework.jms.remoting.JmsInvokerProxyFactoryBean">

<propertyname="serviceInterface"value="com.foo.CheckingAccountService"/>

<propertyname="connectionFactory"ref="connectionFactory"/>

<propertyname="queue"ref="queue"/>

</bean>

</beans>

packagecom.foo;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

publicclassClient{

publicstaticvoidmain(String[]args)throwsException{

ApplicationContextctx=newClassPathXmlApplicationContext(

newString[]{"com/foo/client.xml","com/foo/jms.xml"});

CheckingAccountServiceservice=(CheckingAccountService)ctx.getBean("checkingAccountService");

service.cancelAccount(newLong(10));

}

}

Lingo()“ ...POJOSpringJMS ”

17.7.InitializingBeanDisposableBean

17.8.

RMIHTTPHTTPRMIRMIRMI-JRMPJavaJava-to-JavaHTTPJavaSpringHTTPRMIHTTPHTTPJava-to-JavaSpringSpringRMIRMISpringJMSJMSbroker-JMSJMSJavaJMSXStreamRMIEJBRMIHTTPSpringSpring

18EnterpriseJavaBeans(EJB)

18.1.18.2.EJB

18.2.1.18.2.2.SessionBean(SLSB)18.2.3.SLSB18.2.4.AccessingEJB2.xSLSBsversusEJB3SLSBs

18.3.SpringEJB18.3.1.EJB2.xbaseclasses18.3.2.EJB3

18.1.SpringEJBSpringORMJDBCEJBEJBSpringEJBSpringEJBSpringEJBEJBEJBPOJO(Java)SpringEJBSpringSessionBean(SLSBs)

18.2.EJB

18.2.1.sessionbeanJNDI()EJBHome"create"()EJBEJBEJB(ServiceLocator)(BussinessDelegate)JNDI

EJB

EJBHomecreateEJBAPIEJB

EJBSpringSpringJNDI

18.2.2.SessionBean(SLSB)webEJBEJB(BusinessMethodsInterface)EJBEJBMyComponent

publicinterfaceMyComponent{

...

}

beanPOJO(Java)HomeBean SessionBean

MyComponentWebEJBJava MyComponentsetter

privateMyComponentmyComponent;

publicvoidsetMyComponent(MyComponentmyComponent){

this.myComponent=myComponent;

}

Spring() LocalStatelessSessionProxyFactoryBeanEJBmyComponent

<beanid="myComponent"

class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">

<propertyname="jndiName"value="myJndiComponent"/>

<propertyname="businessInterface"value="com.mycom.MyComponent"/>

</bean>

<beanid="myController"class="com.mycom.myController">

<propertyname="myComponent"ref="myComponent"/>

</bean>

SpringAOPAOPBean myComponentEJBEJBHomeJNDIEJBEJB classnameEJBThe myController bean definition sets the myComponent property of thecontrollerclasstotheEJBproxy.BeanmyController myComponentEJBSpring"jee" local-slsb

<jee:local-slsbid="myComponent"jndi-name="myJndiComponent"

business-interface="com.mycom.MyComponent"/>

<beanid="myController"class="com.mycom.myController">

<propertyname="myComponent"ref="myComponent"/>

</bean>

EJBWeb(EJB)EJBEJBPOJOBean myComponentJavaJNDIEJBEJBEJBEJBJNDIBean()Bean(XML ApplicationContext)EJBEJBJNDIinitEJBXMLSpringEJBAOP LocalSlsbInvokerInterceptor

18.2.3.SLSBEJBEJB SimpleRemoteStatelessSessionProxyFactoryBeanjee:remote-

slsbSpringSpringEJBSpringEJBEJBEJB RemoteExceptionEJBEJBSpringEJBEJB RemoteException

uncheckedexceptionRemoteAccessException RuntimeExceptionEJBEJB(POJO)

18.2.4.AccessingEJB2.xSLSBsversusEJB3SLSBs

SpringEJB2.XEJB3SessionbeanSpringEJBjee:remote-slsb EJB2.xhomeEJB3home:EJB3sessionbean JndiObjectFactoryBean/jee:jndi-lookupjee:local-slsb/jee:remote-slsbEJB

18.3.SpringEJB

18.3.1.EJB2.xbaseclassesSpringEJBEJBPOJOEJBSession BeanBeanAbstractStatelessSessionBeanAbstractStatefulSessionBean

AbstractMessageDrivenBean/AbstractJmsMessageDrivenBeanSessionbeanSessionBeanJava

publicinterfaceMyComponent{

publicvoidmyMethod(...);

...

}

Java

publicclassMyComponentImplimplementsMyComponent{

publicStringmyMethod(...){

...

}

...

}

SessionBean

publicclassMyFacadeEJBextendsAbstractStatelessSessionBean

implementsMyFacadeLocal{

privateMyComponentmyComp;

/**

*ObtainourPOJOserviceobjectfromtheBeanFactory/ApplicationContext

*@seeorg.springframework.ejb.support.AbstractStatelessSessionBean#onEjbCreate()

*/

protectedvoidonEjbCreate()throwsCreateException{

myComp=(MyComponent)getBeanFactory().getBean(

ServicesConstants.CONTEXT_MYCOMP_ID);

}

//forbusinessmethod,delegatetoPOJOserviceimpl.

publicStringmyFacadeMethod(...){

returnmyComp.myMethod(...);

}

...

}

SpringEJBSpringIoCEJB(POJO) BeanFactoryLocatorBeanFactoryLocatorContextJndiBeanFactoryLocatorJNDI

ApplicationContext(EJB java:comp/env/ejb/BeanFactoryPath

BeanFactoryApplicationContext setSessionContext()EJBsetBeanFactoryLocator()BeanFactoryLocatorJavaDocJavaDocSession Bean()EJB ejbPassivateejbActivate

unloadBeanFactory()loadBeanFactoryApplicationContextEJB ContextJndiBeanFactoryLocatorApplicationContextbeanbean(Hibernate SessionFactory)EJB ContextJndiBeanFactoryLocatorContextSingletonBeanFactoryLocatorEJBEJB

/**

*OverridedefaultBeanFactoryLocatorimplementation

*@seejavax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)

*/

publicvoidsetSessionContext(SessionContextsessionContext){

super.setSessionContext(sessionContext);

setBeanFactoryLocator(ContextSingletonBeanFactoryLocator.getInstance());

setBeanFactoryLocatorKey(ServicesConstants.PRIMARY_CONTEXT_ID);

}

beanRefContext.xmlbeanEJBbean()bean(businessApplicationContext.xmlPOJObean)

<beans>

<beanid="businessBeanFactory"class="org.springframework.context.support.ClassPathXmlApplicationContext">

<constructor-argvalue="businessApplicationContext.xml"/>

</bean>

</beans>

ServicesConstants.PRIMARY_CONTEXT_ID

publicstaticfinalStringServicesConstants.PRIMARY_CONTEXT_ID="businessBeanFactory";

BeanFactoryLocatorContextSingletonBeanFactoryLocatorJavadoc

18.3.2.EJB3EJB3 Session beanMessage-Driven Bean, SpringEJBorg.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor

Spring2.5 @AutowiredEJB @Interceptors

binding

@Stateless

@Interceptors(SpringBeanAutowiringInterceptor.class)

publicclassMyFacadeEJBimplementsMyFacadeLocal{

//automaticallyinjectedwithamatchingSpringbean

@Autowired

privateMyComponentmyComp;

//forbusinessmethod,delegatetoPOJOserviceimpl.

publicStringmyFacadeMethod(...){

returnmyComp.myMethod(...);

}

...

}

SpringBeanAutowiringInterceptorContextSingletonBeanFactoryLocatorbean beanRefContext.xml

beanRefContext.xml SpringBeanAutowiringInterceptor

getBeanFactoryLocatorKey

SpringBeanAutowiringInterceptor getBeanFactoryApplicationContext

19JMS(JavaMessageService)

19.1.19.2.SpringJMS

19.2.1.JmsTemplate19.2.2.19.2.3.19.2.4.19.2.5.

19.3.19.3.1.19.3.2.SessionCallback ProducerCallback

19.4.19.4.1.19.4.2.-POJO19.4.3.SessionAwareMessageListener19.4.4.MessageListenerAdapter19.4.5.

19.5.JCA19.6.JMS

JMS1.0.21.1JMS1.0.2/JMS1.0.2APIJMSAPIJMS1.1APIJMS1.1Session

JMS1.120024200311J2EE1.4J2EE1.3BEAWebLogic8.1IBMWebSphere5.1)JMS1.0.2

19.1.SpringJMSAPIJMSAPI1.0.21.1JMS JmsTemplateJavaEEBeanSpringPOJOMDPorg.springframework.jms.coreJMSJDBC JdbcTemplateJMSJMSSpringJMSJMSsessionorg.springframework.jms.supportJMSExceptionJMSExceptionjavax.jms.JMSExceptionUncategorizedJmsException

org.springframework.jms.support.converter MessageConverterJavaJMSorg.springframework.jms.support.destinationJMSJNDI

org.springframework.jms.connectionConnectionFactoryJMSSpring PlatformTransactionManager JmsTransactionManager

JMSSpring

19.2.SpringJMS

19.2.1.JmsTemplateJmsTemplate JmsTemplate JMS 1.1API JmsTemplate102 JMS1.0.2API JmsTemplate MessageCreatorJmsTemplateSessionJMSAPI SessionCallbackJMSsession ProducerCallbackSessionMessageProducerJMSAPIQOSQOS JmsTemplateQOSbean setReceiveTimeoutJMSConnectionFactoryQOS MessageProducer send(Destination

destination,Messagemessage)QOSJMSQOSJmsTemplate isExplicitQosEnabledtrueQOS

JmsTemplate JmsTemplateJmsTemplate ConnectionFactory

19.2.2.JmsTemplate ConnectionFactory ConnectionFactoryJMSJMSJMSSSLEJBJMSJMSrefEJB JmsTemplateConnectionFactorySpring ConnectionFactory SingleConnectionFactory

createConnection Connection close JmsTemplateSingleConnectionFactoryJNDI ConnectionFactory

19.2.3.JNDIJMSSpringJNDI JndiObjectFactoryBeanJMSJMS

JndiDestinationResolver JmsTemplateJndiDestinationResolverJNDI DynamicDestinationResolverJMSJMSJNDIAPI-JMS

TopicSession createTopic(StringtopicName) QueueSession

createQueue(StringqueueName) DynamicDestinationResolver

pubSubDomain JmsTemplateJMSfalse1.0.2JmsTemplate Queue Topic1.1JMS DestinationResolver

defaultDestination JmsTemplate

19.2.4.EJBJMSBeanMDBSpringPOJOMDPEJBSpringMDP 19.4.2“-POJO” JMSMDPMDPMDPJMSSpring AbstractMessageListenerContainer

19.2.4.1.SimpleMessageListenerContainerJMSsessionJMSJMSAPI

19.2.4.2.DefaultMessageListenerContainer SimpleMessageListenerContainerXAJtaTransactionManagerXAJMS

19.2.4.3.ServerSessionMessageListenerContainerJMSServerSessionPoolSPIJMSSession JMSServerSessionPoolSPI DefaultMessageListenerContainerSimpleMessageListenerContainer

19.2.5.Spring JmsTransactionManager JMS ConnectionFactory JMS 9

Spring JmsTransactionManager ConnectionFactoryConnection/Session JmsTemplateJavaEE SingleConnectionFactoryConnectionSessionSpringSingleConnectionFactoryJMSConnection Session,ActiveMQPooledConnectionFactoryJmsTemplate JtaTransactionManagerXAJMSConnectionFactory

JTAXAConnectionFactoryJ2EE/JMSJMSAPI Connection SessionJMSAPI SessionJMS JmsTemplate SessionTransacted

SessionAcknowledgeMode JmsTemplatePlatformTransactionManagerJMS Session

19.3.JmsTemplate javax.jms.DestinationJNDI1.0.2JMS

importjavax.jms.ConnectionFactory;

importjavax.jms.JMSException;

importjavax.jms.Message;

importjavax.jms.Queue;

importjavax.jms.Session;

importorg.springframework.jms.core.MessageCreator;

importorg.springframework.jms.core.JmsTemplate;

importorg.springframework.jms.core.JmsTemplate102;

publicclassJmsQueueSender{

privateJmsTemplatejmsTemplate;

privateQueuequeue;

publicvoidsetConnectionFactory(ConnectionFactorycf){

this.jmsTemplate=newJmsTemplate102(cf,false);

}

publicvoidsetQueue(Queuequeue){

this.queue=queue;

}

publicvoidsimpleSend(){

this.jmsTemplate.send(this.queue,newMessageCreator(){

publicMessagecreateMessage(Sessionsession)throwsJMSException{

returnsession.createTextMessage("helloqueueworld");

}

});

}

}

MessageCreator Session ConnectionFactory JmsTemplate

connectionFactory/queueBeanBeanFactoryJavaSpring JmsGatewaySupportJMSBeanJMS1.0.2 pubSubDomain

send(StringdestinationName,MessageCreatorcreator)JNDI destinationResolver JndiDestinationResolver JmsTemplate send(MessageCreatorc)

19.3.1.JmsTemplate Java JmsTemplate convertAndSend

receiveAndConvert MessageConverterJavaJMSSimpleMessageConverter String TextMessagebyte[] BytesMesssage

java.util.Map MapMessageJMSJMS MapMessageConverterJavaBean MapMessageXMLJAXBCastorXMLBeansXStream TextMessage

MessagePostProcessor java.util.Map

publicvoidsendWithConversion(){

Mapmap=newHashMap();

map.put("Name","Mark");

map.put("Age",newInteger(47));

jmsTemplate.convertAndSend("testQueue",map,newMessagePostProcessor(){

publicMessagepostProcessMessage(Messagemessage)throwsJMSException{

message.setIntProperty("AccountID",1234);

message.setJMSCorrelationID("123-00001");

returnmessage;

}

});

}

:

MapMessage={

Header={

...standardheaders...

CorrelationID={123-00001}

}

Properties={

AccountID={Integer:1234}

}

Fields={

Name={String:Mark}

Age={Integer:47}

}

}

19.3.2.SessionCallback ProducerCallback

sendJMS Session MessageProducer SessionCallbackProducerCallback JMS Session Session / MessageProducer

JmsTemplate execute()

19.4.

19.4.1.JMS receive(..) receiveTimeout

19.4.2.-POJOEJBBeanMDBPOJOMDPJMSMDPjavax.jms.MessageListener javax.jms.MessageListenerPOJO-MDP:

importjavax.jms.JMSException;

importjavax.jms.Message;

importjavax.jms.MessageListener;

importjavax.jms.TextMessage;

publicclassExampleListenerimplementsMessageListener{

publicvoidonMessage(Messagemessage){

if(messageinstanceofTextMessage){

try{

System.out.println(((TextMessage)message).getText());

}

catch(JMSExceptionex){

thrownewRuntimeException(ex);

}

}

else{

thrownewIllegalArgumentException("MessagemustbeoftypeTextMessage");

}

}

}

MessageListenerSping DefaultMessageListenerContainer

<!--thisistheMessageDrivenPOJO(MDP)-->

<beanid="messageListener"class="jmsexample.ExampleListener"/>

<!--andthisisthemessagelistenercontainer-->

<beanid="jmsContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer">

<propertyname="connectionFactory"ref="connectionFactory"/>

<propertyname="destination"ref="destination"/>

<propertyname="messageListener"ref="messageListener"/>

</bean>

SpringJavadoc

19.4.3.SessionAwareMessageListenerSessionAwareMessageListenerSpringJMSMessageListenerMessageJMSSession

packageorg.springframework.jms.listener;

publicinterfaceSessionAwareMessageListener{

voidonMessage(Messagemessage,Sessionsession)throwsJMSException

}

MDP onMessage(Message,Session) SessionMDPJMSMessageListener )SpringMDP MessageListenerSessionAwareMessageListener SessionAwareMessageListenerSpring SessionAwareMessageListener 'onMessage(..)' JMSException

JMS MessageListener SessionAwareMessageListener

19.4.4.MessageListenerAdapterMessageListenerAdapterSpringfinalclass MDP

JMS 1.0.2 API MessageListenerAdapterMessageListenerAdapter102

MessageListener SessionAwareMessageListenerMessageListenerAdapterMDP

publicinterfaceMessageDelegate{

voidhandleMessage(Stringmessage);

voidhandleMessage(Mapmessage);

voidhandleMessage(byte[]message);

voidhandleMessage(Serializablemessage);

}

publicclassDefaultMessageDelegateimplementsMessageDelegate{

//implementationelidedforclarity...

}

MessageDelegate DefaultMessageDelegate JMSPOJOMDP

<!--thisistheMessageDrivenPOJO(MDP)-->

<beanid="messageListener"class="org.springframework.jms.listener.adapter.MessageListenerAdapter">

<constructor-arg>

<beanclass="jmsexample.DefaultMessageDelegate"/>

</constructor-arg>

</bean>

<!--andthisisthemessagelistenercontainer...-->

<beanid="jmsContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer">

<propertyname="connectionFactory"ref="connectionFactory"/>

<propertyname="destination"ref="destination"/>

<propertyname="messageListener"ref="messageListener"/>

</bean>

JMSTextMessageMDP 'receive' MessageListenerAdapter'handleMessage' 'receive(..)'JMSTextMessage

publicinterfaceTextMessageDelegate{

voidreceive(TextMessagemessage);

}

publicclassDefaultTextMessageDelegateimplementsTextMessageDelegate{

//implementationelidedforclarity...

}

MessageListenerAdapter

<beanid="messageListener"class="org.springframework.jms.listener.adapter.MessageListenerAdapter">

<constructor-arg>

<beanclass="jmsexample.DefaultTextMessageDelegate"/>

</constructor-arg>

<propertyname="defaultListenerMethod"value="receive"/>

<!--wedon'twantautomaticmessagecontextextraction-->

<propertyname="messageConverter">

<null/>

</property>

</bean>

'messageListener' TextMessage JMS Message

IllegalStateExceptionMessageListenerAdapter

publicinterfaceResponsiveTextMessageDelegate{

//noticethereturntype...

Stringreceive(TextMessagemessage);

}

publicclassDefaultResponsiveTextMessageDelegateimplementsResponsiveTextMessageDelegate{

//implementationelidedforclarity...

}

DefaultResponsiveTextMessageDelegate MessageListenerAdapter 'receive(..)' TextMessage TextMessage Message

JMSReply-To MessageListenerAdapter InvalidDestinationException

19.4.5.

sessionTransactedJMSSessionAwareMessageListener

<beanid="jmsContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer">

<propertyname="connectionFactory"ref="connectionFactory"/>

<propertyname="destination"ref="destination"/>

<propertyname="messageListener"ref="messageListener"/>

<propertyname="sessionTransacted"value="true"/>

</bean>

DefaultMessageListenerContainerXA JtaTransactionManagerJ2EEJMSConnectionFactoryXAJTAJ2EEJNDIXA

<beanid="transactionManager"class="org.springframework.transaction.jta.JtaTransactionManager"/>

<beanid="jmsContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer">

<propertyname="connectionFactory"ref="connectionFactory"/>

<propertyname="destination"ref="destination"/>

<propertyname="messageListener"ref="messageListener"/>

<propertyname="transactionManager"ref="transactionManager"/>

</bean>

19.5.JCASpring2.5SpringJCA MessageListenerJmsMessageEndpointManager ResourceAdapter ActivationSpecSpring JmsActivationSpecConfig

<beanclass="org.springframework.jms.listener.endpoint.JmsMessageEndpointManager">

<propertyname="resourceAdapter"ref="resourceAdapter"/>

<propertyname="jmsActivationSpecConfig">

<beanclass="org.springframework.jms.listener.endpoint.JmsActivationSpecConfig">

<propertyname="destinationName"value="myQueue"/>

</bean>

</property>

<propertyname="messageListener"ref="myMessageListener"/>

</bean>

Spring ResourceAdapterFactoryBean ResourceAdapterWebLogicJNDI

<beanid="resourceAdapter"class="org.springframework.jca.support.ResourceAdapterFactoryBean">

<propertyname="resourceAdapter">

<beanclass="org.apache.activemq.ra.ActiveMQResourceAdapter">

<propertyname="serverUrl"value="tcp://localhost:61616"/>

</bean>

</property>

<propertyname="workManager">

<beanclass="org.springframework.jca.work.SimpleTaskWorkManager"/>

</property>

</bean>

JmsMessageEndpointManagerJmsActivationSpecConfigResourceAdapterFactoryBeanJavaDocSpringJMSJCAorg.springframework.jca.endpoint.GenericMessageEndpointManagerCCIMessageListenerActivationSpecJCAGenericMessageEndpointManagerJavaDocSpring

JCAEJB2.1Message-DrivenBeansEJB2.1MDB

JCASpringContextSpringJMS“”JMSJCAAPI

19.6.JMSSpring2.5XMLJMSJMSJMSSchema

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:jms="http://www.springframework.org/schema/jms"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/jmshttp://www.springframework.org/schema/jms/spring-jms-2.5.xsd"

<!--<bean/>definitionshere-->

</beans>

<listener-container/> <jca-listener-container/> <listener/>

<jms:listener-container>

<jms:listenerdestination="queue.orders"ref="orderService"method="placeOrder"/>

<jms:listenerdestination="queue.confirmations"ref="confirmationLogger"method="log"/>

</jms:listener-container>

19.4.4“ MessageListenerAdapter” MessageListenerAdapterlistener

19.1.JMSlistener

id BeanBean

destination DestinationResolver

ref Bean

method ref MessageListenerSpring SessionAwareMessageListener

response-destination "JMSReplyTo""destination-type"

subscription

selector

<listener-container/> JMSdestinationResolver

<jms:listener-containerconnection-factory="myConnectionFactory"

task-executor="myTaskExecutor"

destination-resolver="myDestinationResolver"

transaction-manager="myTransactionManager"

concurrency="10">

<jms:listenerdestination="queue.orders"ref="orderService"method="placeOrder"/>

<jms:listenerdestination="queue.confirmations"ref="confirmationLogger"method="log"/>

</jms:listener-container>

AbstractMessageListenerContainerJavadocJavadoc

19.2.JMS<listener-container/>

container-type defaultsimpledefault102 simple102 'default'

connection-factory JMSConnectionFactoryBeanBean 'connectionFactory'

task-executor JMSSpringTaskExecutor

destination-resolver DestinationResolverJMS Destinations

message-converter MessageConverterJMSMessages SimpleMessageConverter

destination-type JMS queuetopic durableTopic 'queue'

client-id JMSid

acknowledge JMS autoclientdups-ok transacted 'auto' 'transacted'

Session transaction-manager

transaction-manager SpringPlatformTransactionManager

concurrency Session

prefetch Session

“jms”SchemaJCA

<jms:jca-listener-containerresource-adapter="myResourceAdapter"

destination-resolver="myDestinationResolver"

transaction-manager="myTransactionManager"

concurrency="10">

<jms:listenerdestination="queue.orders"ref="myMessageListener"/>

</jms:jca-listener-container>

JCA

19.3.JMS<jca-listener-container/>

resource-adapter JCAResourceAdapterBeanBean 'resourceAdapter'

activation-spec-factory

JmsActivationSpecFactory JMS ActivationSpecDefaultJmsActivationSpecFactory

destination-resolver DestinationResolverJMS Destinations

message-converter MessageConverterJMSMessages SimpleMessageConverter

destination-type JMS queuetopic durableTopic 'queue'

client-id JMSid

acknowledge JMS autoclientdups-ok transacted 'auto' 'transacted'

Session transaction-manager

transaction-manager

SpringJtaTransactionManager javax.transaction.TransactionManagerXA “acknowledge”

concurrency Session

prefetch Session

20JMX

20.1.20.2.BeanJMX

20.2.1.MBeanServer20.2.2.MBeanServer20.2.3.MBean20.2.4.MBean20.2.5.

20.3.Bean20.3.1.MBeanInfoAssembler20.3.2.20.3.3.JDK5.020.3.4.20.3.5.AutodetectCapableMBeanInfoAssembler20.3.6.Java20.3.7.MethodNameBasedMBeanInfoAssembler

20.4.BeanObjectName20.4.1. PropertiesProperties

20.4.2.MetadataNamingStrategy20.4.3.<context:mbean-export/>

20.5.JSR-16020.5.1.20.5.2.20.5.3.Burlap/Hessian/SOAPJMX

20.6.MBean20.7.

20.7.1.20.7.2.

20.8.

JMXJMXJMXJMXJMX 20.8“”

20.1.SpringJMXSpringJMXSpringJMX

SpringBeanJMXMBean

Bean

JSR-160MBean

MBeanSpringJMX SpringJMXSpringJMX

20.2.BeanJMXSpringJMX MBeanExporterSpringBean JMX

packageorg.springframework.jmx;

publicclassJmxTestBeanimplementsIJmxTestBean{

privateStringname;

privateintage;

privatebooleanisSuperman;

publicintgetAge(){

returnage;

}

publicvoidsetAge(intage){

this.age=age;

}

publicvoidsetName(Stringname){

this.name=name;

}

publicStringgetName(){

returnname;

}

publicintadd(intx,inty){

returnx+y;

}

publicvoiddontExposeMe(){

thrownewRuntimeException();

}

}

BeanJMXMBean MBeanExporterBean

<beans>

<!--Bean -->

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter"

lazy-init="false">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean1"value-ref="testBean"/>

</map>

</property>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

</beans>

exporterBean beans MBeanExporterBeanJMX MBeanServer beans MapkeyBean ObjectName 20.4“Bean ObjectName

testBean bean:name=testBean1 ObjectNameMBean public public Object

20.2.1. MBeanServer

MBeanServerMBeanServerTomcatIBMWebSphere MBeanServer org.springframework.jmx.support.MBeanServerFactoryBeanMBeanExporter server MBeanExporterMBeanServerFactoryBean MBeanServer

<beans>

<beanid="mbeanServer"class="org.springframework.jmx.support.MBeanServerFactoryBean"/>

<!--

Bean

-->

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean1"value-ref="testBean"/>

</map>

</property>

<propertyname="server"ref="mbeanServer"/>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

</beans>

MBeanServerFactoryBean MBeanServerserver MBeanExporter

MBeanServer MBeanExporter MBeanServerJMX

20.2.2. MBeanServer

MBeanExporter MBeanServer MBeanServerMBeanExporter MBeanServer agentId

<beans>

<beanid="mbeanServer"class="org.springframework.jmx.support.MBeanServerFactoryBean">

<!---->

<propertyname="locateExistingServerIfPossible"value="true"/>

<!--agentId MBeanServer-->

<propertyname="agentId"value="<MBeanServerinstanceagentId>

</bean>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="server"ref="mbeanServer"/>

...

</bean>

</beans>

MBeanServerlookup agentId factory-method

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="server">

<!-- MBeanServerLocator-->

<beanclass="platform.package.MBeanServerLocator"factory-method="locateMBeanServer"/>

</property>

<!--Bean-->

</bean>

</beans>

20.2.3.MBean MBeanExporterBean MBeanExporter MBeanExporterBean MBeanServerBean

20.2.4.MBean MBeanExporterBeanMBean MBeanServerSpringautodetecttrue MBeanExporterMBean

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="autodetect"value="true"/>

</bean>

<beanname="spring:mbean=true"class="org.springframework.jmx.export.TestDynamicMBean"/>

spring:mbean=trueBeanJMXMBeanSpringObjectNameBean 20.4“Bean ObjectName”overridden

20.2.5.Spring MBeanExporter ObjectName'bean:name=testBean1'MBeanServerMBean ObjectName MBeanInstanceAlreadyExistsException

MBean SpringJMX

20.1.

REGISTRATION_FAIL_ON_EXISTING MBean ObjectNameSpring MBeanInstanceAlreadyExistsException MBean

REGISTRATION_IGNORE_EXISTING MBean ObjectName MBean MBean

REGISTRATION_REPLACE_EXISTING MBean ObjectName MBean MBeanObjectName MBean

MBeanRegistrationSupport MBeanExporter MBeanExporter registrationBehaviorName REGISTRATION_REPLACE_EXISTING

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean1"value-ref="testBean"/>

</map>

</property>

<propertyname="registrationBehaviorName"value="REGISTRATION_REPLACE_EXISTING"/>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

</beans>

20.3.BeanBeanBean publicJMXBeanJMXSpringJMXbean

20.3.1.MBeanInfoAssemblerMBeanExporter beanorg.springframework.jmx.export.assembler.MBeanInfoAssemblerBean

org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler

publicpublic Spring

20.3.2. MetadataMBeanInfoAssemblerBeanorg.springframework.jmx.export.metadata.JmxAttributeSourceSprinJMXCommons Attributesorg.springframework.jmx.export.metadata.AttributesJmxAttributeSource

JDK 5.0org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource

MetadataMBeanInfoAssembler CommonsAttributesBeanJMX ManagedResourceBean CommonsAttributesorg.springframework.jmx.metadata gettersetterCommonsAttributes JmxTestBean

packageorg.springframework.jmx;

/**

*@@org.springframework.jmx.export.metadata.ManagedResource

*(description="MyManagedBean",objectName="spring:bean=test",

*log=true,logFile="jmx.log",currencyTimeLimit=15,persistPolicy="OnUpdate",

*persistPeriod=200,persistLocation="foo",persistName="bar")

*/

publicclassJmxTestBeanimplementsIJmxTestBean{

privateStringname;

privateintage;

/**

*@@org.springframework.jmx.export.metadata.ManagedAttribute

*(description="TheAgeAttribute",currencyTimeLimit=15)

*/

publicintgetAge(){

returnage;

}

publicvoidsetAge(intage){

this.age=age;

}

/**

*@@org.springframework.jmx.export.metadata.ManagedAttribute

*(description="TheNameAttribute",currencyTimeLimit=20,

*defaultValue="bar",persistPolicy="OnUpdate")

*/

publicvoidsetName(Stringname){

this.name=name;

}

/**

*@@org.springframework.jmx.export.metadata.ManagedAttribute

*(defaultValue="foo",persistPeriod=300)

*/

publicStringgetName(){

returnname;

}

/**

*@@org.springframework.jmx.export.metadata.ManagedOperation

*(description="AddTwoNumbersTogether")

*/

publicintadd(intx,inty){

returnx+y;

}

publicvoiddontExposeMe(){

thrownewRuntimeException();

}

}

JmxTestBean ManagedResource ManagedResourceMBeanExporterMBean 20.3.4“” age name ManagedAttribute agegetter

add(int,int) ManagedOperation dontExposeMe()MetadataMBeanInfoAssembler add(int,int) MetadataMBeanInfoAssembler MBeanExporter

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean1"value-ref="testBean"/>

</map>

</property>

<propertyname="assembler"ref="assembler"/>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

<beanid="attributeSource"

class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource">

<propertyname="attributes">

<beanclass="org.springframework.metadata.commons.CommonsAttributes"/>

</property>

</bean>

<beanid="assembler"class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">

<propertyname="attributeSource"ref="attributeSource"/>

</bean>

</beans>

MetadataMBeanInfoAssemblerBean AttributesJmxAttributeSource

assembler MBeanExporterSpringMBean

20.3.3.JDK5.0JDK5.0SpringCommonsAttributeAnnotationsJmxAttributeSource MBeanInfoAssemblerJDK5.0Bean

packageorg.springframework.jmx;

importorg.springframework.jmx.export.annotation.ManagedResource;

importorg.springframework.jmx.export.annotation.ManagedOperation;

importorg.springframework.jmx.export.annotation.ManagedAttribute;

@ManagedResource(objectName="bean:name=testBean4",description="MyManagedBean",log=true,

logFile="jmx.log",currencyTimeLimit=15,persistPolicy="OnUpdate",persistPeriod=200,

persistLocation="foo",persistName="bar")

publicclassAnnotationTestBeanimplementsIJmxTestBean{

privateStringname;

privateintage;

@ManagedAttribute(description="TheAgeAttribute",currencyTimeLimit=15)

publicintgetAge(){

returnage;

}

publicvoidsetAge(intage){

this.age=age;

}

@ManagedAttribute(description="TheNameAttribute",

currencyTimeLimit=20,

defaultValue="bar",

persistPolicy="OnUpdate")

publicvoidsetName(Stringname){

this.name=name;

}

@ManagedAttribute(defaultValue="foo",persistPeriod=300)

publicStringgetName(){

returnname;

}

@ManagedOperation(description="Addtwonumbers")

@ManagedOperationParameters({

@ManagedOperationParameter(name="x",description="Thefirstnumber"),

@ManagedOperationParameter(name="y",description="Thesecondnumber")})

publicintadd(intx,inty){

returnx+y;

}

publicvoiddontExposeMe(){

thrownewRuntimeException();

}

}

JDK5.0CommonsAttributes

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="assembler"ref="assembler"/>

<propertyname="namingStrategy"ref="namingStrategy"/>

<propertyname="autodetect"value="true"/>

</bean>

<beanid="jmxAttributeSource"

class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>

<!---->

<beanid="assembler"

class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">

<propertyname="attributeSource"ref="jmxAttributeSource"/>

</bean>

<!-- ObjectName-->

<beanid="namingStrategy"

class="org.springframework.jmx.export.naming.MetadataNamingStrategy">

<propertyname="attributeSource"ref="jmxAttributeSource"/>

</bean>

<beanid="testBean"class="org.springframework.jmx.AnnotationTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

</beans>

20.3.4.SpringJMX

20.2.

CommonsAttributes JDK5.0 /JMX ManagedResource @ManagedResource Class

JMX ManagedOperation @ManagedOperation Method

gettersetterJMX

ManagedAttribute @ManagedAttribute

Method(onlygettersandsetters)

getterssetters

ManagedOperationParameter

@ManagedOperationParameter

@ManagedOperationParameters

Method

20.3.

ObjectNameMetadataNamingStrategy

ObjectNameManagedResource

ManagedResource

ManagedAttribute

ManagedOperation

ManagedOperationParameter

currencyTimeLimit

currencyTimeLimit currencyTimeLimit ManagedResourceManagedAttribute

defaultValue defaultValue ManagedAttribute

log log ManagedResource

logFile logFile ManagedResource

persistPolicy persistPolicy ManagedResource

persistPeriod persistPeriod ManagedResource

persistLocation persistLocation ManagedResource

persistName persistName ManagedResource

name ManagedOperationParameter

index ManagedOperationParameter

20.3.5.AutodetectCapableMBeanInfoAssemblerSpring AutodetectCapableMBeanInfoAssemblerMBeanInfoAssembler MBeanAutodetectCapableMBeanInfoAssembler MBeanExporterJMXBeanAutodetectCapableMBeanInfo MetadataMBeanInfoAssembler“”ManagedResourceBean bean ObjectName

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<!-- 'beans'-->

<propertyname="autodetect"value="true"/>

<propertyname="assembler"ref="assembler"/>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

<!--CommonsAttributes-basedmetadata-->

<beanid="attributeSource"

class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource">

<propertyname="attributes">

<beanclass="org.springframework.metadata.commons.CommonsAttributes"/>

</property>

</bean>

<!--JDK5+-->

<!--

<beanid="attributeSource"

class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>

-->

<beanid="assembler"class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">

<propertyname="attributeSource"ref="attributeSource"/>

</bean>

</beans>

MBeanExporterBean JmxTestBean ManagedResource

MetadataMBeanInfoAssembler Bean ObjectName” ObjectName

20.3.6.Java MetadataMBeanInfoAssemblerSpringInterfaceBasedMBeanInfoAssembler

MBean InterfaceBasedMBeanInfoAssembler

JmxTestBean

publicinterfaceIJmxTestBean{

publicintadd(intx,inty);

publiclongmyOperation();

publicintgetAge();

publicvoidsetAge(intage);

publicvoidsetName(Stringname);

publicStringgetName();

}

JMXMBeanSpringJMX

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean5"value-ref="testBean"/>

</map>

</property>

<propertyname="assembler">

<beanclass="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">

<propertyname="managedInterfaces">

<value>org.springframework.jmx.IJmxTestBean</value>

</property>

</bean>

</property>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

</beans>

Bean InterfaceBasedMBeanInfoAssembler IJmxTestBean

InterfaceBasedMBeanInfoAssemblerbeanJMXIJmxTestBeanbean Bean

InterfaceBasedMBeanInfoAssembler interfaceMappings Properties

Bean(;)Bean managedInterfaces interfaceMappings

InterfaceBasedMBeanInfoAssemblerBean

20.3.7. MethodNameBasedMBeanInfoAssembler

MethodNameBasedMBeanInfoAssemblerJMX

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean5"value-ref="testBean"/>

</map>

</property>

<propertyname="assembler">

<beanclass="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">

<propertyname="managedMethods">

<value>add,myOperation,getName,setName,getAge</value>

</property>

</bean>

</property>

</bean>

add myOperationJMX getName()setName(String) getAge()JMXJMXBean BeanmethodMappingsBean

20.4.Bean ObjectName

Bean MBeanExporter ObjectNamingStrategy ObjectNameKeyNamingStrategy beans Map ObjectName KeyNamingStrategy Properties ObjectName KeyNamingStrategySpringObjectNamingStrategy beanJVM ObjectNameIdentityNamingStrategy ObjectName MetadataNamingStrategy

20.4.1. PropertiesProperties

KeyNamingStrategy Properties ObjectNameBeanKeyNamingStrategybean Properties Bean ObjectName

KeyNamingStrategy

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="testBean"value-ref="testBean"/>

</map>

</property>

<propertyname="namingStrategy"ref="namingStrategy"/>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

<beanid="namingStrategy"class="org.springframework.jmx.export.naming.KeyNamingStrategy">

<propertyname="mappings">

<props>

<propkey="testBean">bean:name=testBean1</prop>

</props>

</property>

<propertyname="mappingLocations">

<value>names1.properties,names2.properties</value>

</property>

</bean

</beans>

KeyNamingStrategy Properties PropertiesmappingmappingLocations Properties testBean ObjectName bean:name=testBean1

PropertiesBean ObjectName

20.4.2. MetadataNamingStrategy

MetadataNamingStrategy Bean ManagedResource objectNameobjectName MetadataNamingStrategy

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="testBean"value-ref="testBean"/>

</map>

</property>

<propertyname="namingStrategy"ref="namingStrategy"/>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

<beanid="namingStrategy"class="org.springframework.jmx.export.naming.MetadataNamingStrategy">

<propertyname="attributeSource"ref="attributeSource"/>

</bean>

<beanid="attributeSource"

class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource"/>

</beans>

objectName ManagedResource ObjectName [fully-qualified-package-name]:type=[short-classname],name=[bean-name]Bean

ObjectName com.foo:type=MyClass,name=myBean

<beanid="myBean"class="com.foo.MyClass"/>

20.4.3.<context:mbean-export/>Java5 MBeanExporter AnnotationMBeanExporter

namingStrategy attributeSource

<context:mbean-export/>

MBean defaultDomain AnnotationMBeanExporter

ObjectNames MetadataNamingStrategy

<context:mbean-exportserver="myMBeanServer"default-domain="myDomain"/>

.

20.5.JSR-160SpringJMX org.springframework.jmx.support FactoryBean

20.5.1.SpringJMXJSR-160 JMXConnectorServer

<beanid="serverConnector"class="org.springframework.jmx.support.ConnectorServerFactoryBean"/>

ConnectorServerFactoryBean JMXConnectorServer"service:jmx:jmxmp://localhost:9875" serverConnectorBean9875JMXMP MBeanServer JSR160JMXMPJMXMX4JJ2SE5.0JMXMPURL MBeanServer JMXConnectorServer serviceUrl

<beanid="serverConnector"

class="org.springframework.jmx.support.ConnectorServerFactoryBean">

<propertyname="objectName"value="connector:name=rmi"/>

<propertyname="serviceUrl"

value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector"/>

</bean>

ObjectNameSpring ObjectName MBeanServer JMXConnectorServerFactoryBean

<beanid="serverConnector"

class="org.springframework.jmx.support.ConnectorServerFactoryBean">

<propertyname="objectName"value="connector:name=iiop"/>

<propertyname="serviceUrl"

value="service:jmx:iiop://localhost/jndi/iiop://localhost:900/myconnector"/>

<propertyname="threaded"value="true"/>

<propertyname="daemon"value="true"/>

<propertyname="environment">

<map>

<entrykey="someKey"value="someValue"/>

</map>

</property>

</bean>

RMItnameservrmiregistrySpring

<beanid="registry"class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">

<propertyname="port"value="1099"/>

</bean>

20.5.2. MBeanServerConnection JSR-160 MBeanServerMBeanServerConnectionFactoryBean

<beanid="clientConnector"class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">

<propertyname="serviceUrl"value="service:jmx:rmi://localhost:9875"/>

</bean>

20.5.3.Burlap/Hessian/SOAPJMXJSR-160RMIJSR-160IIOPJRMPJMXMPMX4J SOAPHessianHTTPSSLBurlap

<beanid="serverConnector"class="org.springframework.jmx.support.ConnectorServerFactoryBean">

<propertyname="objectName"value="connector:name=burlap"/>

<propertyname="serviceUrl"value="service:jmx:burlap://localhost:9874"/>

</bean>

MX4J3.0.0MX4J

20.6.MBeanSpringJMX MBeanServerMBeanMBeanServerMBean

<beanid="proxy"class="org.springframework.jmx.access.MBeanProxyFactoryBean">

<propertyname="objectName"value="bean:name=testBean"/>

<propertyname="proxyInterface"value="org.springframework.jmx.IJmxTestBean"/>

</bean>

ObjectName:bean:name=testBeanMBean MBean InterfaceBasedMBeanInfoAssembler

MBeanProxyFactoryBeanMBean MBeanServerConnectionMBeanServerMBean MBeanServer MBeanServerConnection

<beanid="clientConnector"

class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">

<propertyname="serviceUrl"value="service:jmx:rmi://remotehost:9875"/>

</bean>

<beanid="proxy"class="org.springframework.jmx.access.MBeanProxyFactoryBean">

<propertyname="objectName"value="bean:name=testBean"/>

<propertyname="proxyInterface"value="org.springframework.jmx.IJmxTestBean"/>

<propertyname="server"ref="clientConnector"/>

</bean>

MBeanServerConnectionFactoryBean MBeanServerConnection

MBeanServerConnection server MBeanProxyFactoryBeanMBeanServerConnection MBeanServer

20.7.SpringJMXJMX

20.7.1.SpringJMXMBean NotificationListenersSpringMBean MBean

packagecom.example;

importjavax.management.AttributeChangeNotification;

importjavax.management.Notification;

importjavax.management.NotificationFilter;

importjavax.management.NotificationListener;

publicclassConsoleLoggingNotificationListener

implementsNotificationListener,NotificationFilter{

publicvoidhandleNotification(Notificationnotification,Objecthandback){

System.out.println(notification);

System.out.println(handback);

}

publicbooleanisNotificationEnabled(Notificationnotification){

returnAttributeChangeNotification.class.isAssignableFrom(notification.getClass());

}

}

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean1"value-ref="testBean"/>

</map>

</property>

<propertyname="notificationListenerMappings">

<map>

<entrykey="bean:name=testBean1">

<beanclass="com.example.ConsoleLoggingNotificationListener"/>

</entry>

</map>

</property>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

</beans>

MBean bean:name=testBean1JMXNotificationnotificationListenerMappings ConsoleLoggingNotificationListener

ConsoleLoggingNotificationListener Notification

BeanBean

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean1"value-ref="testBean"/>

</map>

</property>

<propertyname="notificationListenerMappings">

<map>

<entrykey="testBean">

<beanclass="com.example.ConsoleLoggingNotificationListener"/>

</entry>

</map>

</property>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

</beans>

MBeanExporterBean NotificationListener'*'notificationListenerMappings

<propertyname="notificationListenerMappings">

<map>

<entrykey="*">

<beanclass="com.example.ConsoleLoggingNotificationListener"/>

</entry>

</map>

</property>

MBean notificationListeners

notificationListenerMappings NotificationListenerBean

…… NotificationListenerBean NotificationListenerMBeanServer ObjectName NotificationFilterJMX NotificationListenerBean

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean1"value-ref="testBean"/>

</map>

</property>

<propertyname="notificationListeners">

<list>

<beanclass="org.springframework.jmx.export.NotificationListenerBean">

<constructor-arg>

<beanclass="com.example.ConsoleLoggingNotificationListener"/>

</constructor-arg>

<propertyname="mappedObjectNames">

<list>

<value>bean:name=testBean1</value>

</list>

</property>

</bean>

</list>

</property>

</bean>

<beanid="testBean"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

</beans>

Notification NotificationFilter JMX1.2 'The JMX Notification Model'

<beans>

<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">

<propertyname="beans">

<map>

<entrykey="bean:name=testBean1"value-ref="testBean1"/>

<entrykey="bean:name=testBean2"value-ref="testBean2"/>

</map>

</property>

<propertyname="notificationListeners">

<list>

<beanclass="org.springframework.jmx.export.NotificationListenerBean">

<constructor-argref="customerNotificationListener"/>

<propertyname="mappedObjectNames">

<list>

<!--handlesnotificationsfromtwodistinctMBeans-->

<value>bean:name=testBean1</value>

<value>bean:name=testBean2</value>

</list>

</property>

<propertyname="handback">

<beanclass="java.lang.String">

<constructor-argvalue="Thiscouldbeanything..."/>

</bean>

</property>

<propertyname="notificationFilter"ref="customerNotificationListener"/>

</bean>

</list>

</property>

</bean>

<!-- NotificationListener NotificationFilter-->

<beanid="customerNotificationListener"class="com.example.ConsoleLoggingNotificationListener"/>

<beanid="testBean1"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="TEST"/>

<propertyname="age"value="100"/>

</bean>

<beanid="testBean2"class="org.springframework.jmx.JmxTestBean">

<propertyname="name"value="ANOTHERTEST"/>

<propertyname="age"value="200"/>

</bean>

</beans>

20.7.2.Spring

MBeanExporterSpringBean

SpringJMX NotificationPublisher

org.springframework.jmx.export.notification MBeanExporter

MBeanBean NotificationPublisherAware NotificationPublisher

NotificationPublisherAwaresetterBeanBean Notification NotificationPublisherJavadoc NotificationPublisherBean SpringJMXJMXNotificationPublisher Bean MBeanServer

NotificationPublisher NotificationPublisher Notification Notification NotificationNotificationPublisher

sendNotification(Notification)

JmxTestBean add(int,int) NotificationEvent

packageorg.springframework.jmx;

importorg.springframework.jmx.export.notification.NotificationPublisherAware;

importorg.springframework.jmx.export.notification.NotificationPublisher;

importjavax.management.Notification;

publicclassJmxTestBeanimplementsIJmxTestBean,NotificationPublisherAware{

privateStringname;

privateintage;

privatebooleanisSuperman;

privateNotificationPublisherpublisher;

//gettersetter

publicintadd(intx,inty){

intanswer=x+y;

this.publisher.sendNotification(newNotification("add",this,0));

returnanswer;

}

publicvoiddontExposeMe(){

thrownewRuntimeException();

}

publicvoidsetNotificationPublisher(NotificationPublishernotificationPublisher){

this.publisher=notificationPublisher;

}

}

NotificationPublisherSpringJMX SpringJMX……NotificationPublisherSpringJMX

21JCACCI

21.1.21.2.CCI

21.2.1.21.2.2.SpringConnectionFactory21.2.3.CCI21.2.4.CCI

21.3.SpringCCI21.3.1.21.3.2.CciTemplate21.3.3.DAO21.3.4.21.3.5.21.3.6.CCIConnectionInteraction21.3.7.CciTemplate

21.4.CCI21.4.1.MappingRecordOperation21.4.2.MappingCommAreaOperation21.4.3.21.4.4.21.4.5.MappingRecordOperation21.4.6.MappingCommAreaOperation

21.5.

21.1.J2EEJCAJavaConnectorArchitectureEISEnterpriseInformationSystem

SPIServiceproviderinterfacesconnectorproviderresourceadapter connectionpoolingmanagedmode connectornon-managedmodeCCICommonClientInterfaceEISAPI

SpringCCISpringCCISpring

CCIAPIJCAresourceadaptercontractsconnectionpoolingglobaltransactionssecurity Springconnector-specificAPI

21.2.CCI

21.2.1.JCACCI ConnectionFactoryJNDI ConnectionFactory

ra.xml SpringSpringnon-managedmodeFactoryBeanLocalConnectionFactoryBean)bean classpathRAR ra.xml RAR ConnectionFactory CCIAPISpringCCI

CciTemplate

non-managedmode J2EE

21.2.2.Spring ConnectionFactory

EISmanagedmodemodeSpringmanagedmodeJNDI ConnectionFactory

<beanid="eciConnectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="eis/cicseci"/>

</bean>

non-managedmodeSpring ConnectionFactory

LocalConnectionFactoryBean ManagedConnectionFactoryConnectionFactory

<beanid="eciManagedConnectionFactory"class="com.ibm.connector2.cics.ECIManagedConnectionFactory">

<propertyname="serverName"value="TXSERIES"/>

<propertyname="connectionURL"value="tcp://localhost/"/>

<propertyname="portNumber"value="2006"/>

</bean>

<beanid="eciConnectionFactory"class="org.springframework.jca.support.LocalConnectionFactoryBean">

<propertyname="managedConnectionFactory"ref="eciManagedConnectionFactory"/>

</bean>

ConnectionFactory JCASPI

21.2.3.CCIJCACCI ConnectionSpecEISConnectionSpecConnectionFactoryAdapter connectionSpecbeanCCI ConnectionFactoryCCI ConnectionSpec

mode ManagedConnectionFactory

publicinterfaceConnectionFactoryimplementsSerializable,Referenceable{

...

ConnectiongetConnection()throwsResourceException;

ConnectiongetConnection(ConnectionSpecconnectionSpec)throwsResourceException;

...

}

Spring ConnectionSpecConnectionFactoryAdapter ConnectionSpec, connectionSpec

ConnectionSpec

<beanid="managedConnectionFactory"

class="com.sun.connector.cciblackbox.CciLocalTxManagedConnectionFactory">

<propertyname="connectionURL"value="jdbc:hsqldb:hsql://localhost:9001"/>

<propertyname="driverName"value="org.hsqldb.jdbcDriver"/>

</bean>

<beanid="targetConnectionFactory"

class="org.springframework.jca.support.LocalConnectionFactoryBean">

<propertyname="managedConnectionFactory"ref="managedConnectionFactory"/>

</bean>

<beanid="connectionFactory"

class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">

<propertyname="targetConnectionFactory"ref="targetConnectionFactory"/>

<propertyname="connectionSpec">

<beanclass="com.sun.connector.cciblackbox.CciConnectionSpec">

<propertyname="user"value="sa"/>

<propertyname="password"value=""/>

</bean>

</property>

</bean>

21.2.4.CCICCISpring ConnectionFactorybean Connection

<beanid="eciManagedConnectionFactory"

class="com.ibm.connector2.cics.ECIManagedConnectionFactory">

<propertyname="serverName"value="TEST"/>

<propertyname="connectionURL"value="tcp://localhost/"/>

<propertyname="portNumber"value="2006"/>

</bean>

<beanid="targetEciConnectionFactory"

class="org.springframework.jca.support.LocalConnectionFactoryBean">

<propertyname="managedConnectionFactory"ref="eciManagedConnectionFactory"/>

</bean>

<beanid="eciConnectionFactory"

class="org.springframework.jca.cci.connection.SingleConnectionFactory">

<propertyname="targetConnectionFactory"ref="targetEciConnectionFactory"/>

</bean>

ConnectionFactory ConnectionSpec ConnectionSpec SingleConnectionFactoryConnectionSpecConnectionFactoryAdapter

21.3.SpringCCI

21.3.1.JCACCICCI Spring Record RecordCreator

publicinterfaceRecordCreator{

RecordcreateRecord(RecordFactoryrecordFactory)throwsResourceException,DataAccessException;

}

createRecord(..) RecordFactory RecordFactory IndexedRecord MappedRecordRecordFactoryindexed/mapped

publicclassMyRecordCreatorimplementsRecordCreator{

publicRecordcreateRecord(RecordFactoryrecordFactory)throwsResourceException{

IndexedRecordinput=recordFactory.createIndexedRecord("input");

input.add(newInteger(id));

returninput;

}

}

RecordEIS RecordExtractorSpring CciTemplate

Record

publicinterfaceRecordExtractor{

ObjectextractData(Recordrecord)throwsResourceException,SQLException,DataAccessException;

}

RecordExtractor

publicclassMyRecordExtractorimplementsRecordExtractor{

publicObjectextractData(Recordrecord)throwsResourceException{

CommAreaRecordcommAreaRecord=(CommAreaRecord)record;

Stringstr=newString(commAreaRecord.toByteArray());

Stringfield1=string.substring(0,6);

Stringfield2=string.substring(6,1);

returnnewOutputObject(Long.parseLong(field1),field2);

}

}

21.3.2.CciTemplateCciTemplateCCI org.springframework.jca.cci.core CCIJCACCIEISCCI Interaction execute

publicinterfacejavax.resource.cci.Interaction{

...

booleanexecute(InteractionSpecspec,Recordinput,Recordoutput)throwsResourceException;

Recordexecute(InteractionSpecspec,Recordinput)throwsResourceException;

...

}

CciTemplateinteraction execute

CciTemplate.execute(..)

RecordCCI CCI

RecordCreator RecordExtractor

Interaction

publicclassCciTemplateimplementsCciOperations{

publicRecordexecute(InteractionSpecspec,RecordinputRecord)

throwsDataAccessException{...}

publicvoidexecute(InteractionSpecspec,RecordinputRecord,RecordoutputRecord)

throwsDataAccessException{...}

}

publicclassCciTemplateimplementsCciOperations{

publicRecordexecute(InteractionSpecspec,RecordCreatorinputCreator)

throwsDataAccessException{...}

publicObjectexecute(InteractionSpecspec,RecordinputRecord,RecordExtractoroutputExtractor)

throwsDataAccessException{...}

publicObjectexecute(InteractionSpecspec,RecordCreatorcreator,RecordExtractorextractor)

throwsDataAccessException{...}

}

outputRecordCreator CCI Record execute Record createIndexRecord(..) createMappedRecord(..) CciTemplateRecordCreator IndexRecord MappedRecordDAOCciTemplate.execute(..)

publicclassCciTemplateimplementsCciOperations{

publicIndexedRecordcreateIndexedRecord(Stringname)throwsDataAccessException{...}

publicMappedRecordcreateMappedRecord(Stringname)throwsDataAccessException{...}

}

21.3.3.DAOSpringCCIDAO ConnectionFactory CciTemplate

CciDaoSupport setConnectionFactory setCciTemplateConnectionFactory CciTemplate

publicabstractclassCciDaoSupport{

publicvoidsetConnectionFactory(ConnectionFactoryconnectionFactory){...}

publicConnectionFactorygetConnectionFactory(){...}

publicvoidsetCciTemplate(CciTemplatecciTemplate){...}

publicCciTemplategetCciTemplate(){...}

}

21.3.4. Interaction.execute(..) outputRecordCreator JCAJCAconnector RecordCreator RecordCreator 21.3.1“”

outputRecordCreator CciTemplate

cciTemplate.setOutputRecordCreator(newEciOutputRecordCreator());

CciTemplatebeanoutputRecordCreatorSpring

<beanid="eciOutputRecordCreator"class="eci.EciOutputRecordCreator"/>

<beanid="cciTemplate"class="org.springframework.jca.cci.core.CciTemplate">

<propertyname="connectionFactory"ref="eciConnectionFactory"/>

<propertyname="outputRecordCreator"ref="eciOutputRecordCreator"/>

</bean>

CciTemplate

21.3.5. CciTemplateCCI Interaction

21.1.UsageofInteractionexecutemethods

CciTemplatemethodsignature

CciTemplateoutputRecordCreator

property

executemethodcalledontheCCI

InteractionRecord

execute(InteractionSpec, notsetRecord

execute(InteractionSpec,

Record) Record)

Recordexecute(InteractionSpec,

Record)set

booleanexecute(InteractionSpec,

Record,Record)

voidexecute(InteractionSpec,Record,Record) notset voidexecute(InteractionSpec,

Record,Record)

voidexecute(InteractionSpec,Record,Record) set voidexecute(InteractionSpec,

Record,Record)

Recordexecute(InteractionSpec,

RecordCreator)notset

Recordexecute(InteractionSpec,

Record)

Recordexecute(InteractionSpec,

RecordCreator)set voidexecute(InteractionSpec,

Record,Record)

Recordexecute(InteractionSpec,Record,RecordExtractor)

notsetRecord

execute(InteractionSpec,Record)

Recordexecute(InteractionSpec,Record,RecordExtractor)

set voidexecute(InteractionSpec,Record,Record)

Recordexecute(InteractionSpec,

RecordCreator,RecordExtractor)

notsetRecord

execute(InteractionSpec,Record)

Recordexecute(InteractionSpec,

RecordCreator,RecordExtractor)

set voidexecute(InteractionSpec,Record,Record)

21.3.6.CCI ConnectionInteraction

JdbcTemplate JmsTemplate CciTemplateCCIConnectionCallbackCCIConnection ConnectionFactory RecordFactoryindexed/mappedrecords

publicinterfaceConnectionCallback{

ObjectdoInConnection(Connectionconnection,ConnectionFactoryconnectionFactory)

throwsResourceException,SQLException,DataAccessException;

}

InteractionCallbackCCI Interaction CCI

ConnectionFactory

publicinterfaceInteractionCallback{

ObjectdoInInteraction(Interactioninteraction,ConnectionFactoryconnectionFactory)

throwsResourceException,SQLException,DataAccessException;

}

InteractionSpectemplate

21.3.7.CciTemplate CciTemplateIBMCICSECIECICICS.CCI InteractionSpecCICS

ECIInteractionSpecinteractionSpec=newECIInteractionSpec();

interactionSpec.setFunctionName("MYPROG");

interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);

SpringCCICCI Records

publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{

publicOutputObjectgetData(InputObjectinput){

ECIInteractionSpecinteractionSpec=...;

OutputObjectoutput=(ObjectOutput)getCciTemplate().execute(interactionSpec,

newRecordCreator(){

publicRecordcreateRecord(RecordFactoryrecordFactory)throwsResourceException{

returnnewCommAreaRecord(input.toString().getBytes());

}

},

newRecordExtractor(){

publicObjectextractData(Recordrecord)throwsResourceException{

CommAreaRecordcommAreaRecord=(CommAreaRecord)record;

Stringstr=newString(commAreaRecord.toByteArray());

Stringfield1=string.substring(0,6);

Stringfield2=string.substring(6,1);

returnnewOutputObject(Long.parseLong(field1),field2);

}

});

returnoutput;

}

}

callbacksCCI

publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{

publicOutputObjectgetData(InputObjectinput){

ObjectOutputoutput=(ObjectOutput)getCciTemplate().execute(

newConnectionCallback(){

publicObjectdoInConnection(Connectionconnection,ConnectionFactoryfactory)

throwsResourceException{

//dosomething...

}

});

}

returnoutput;

}

}

getCciTemplate().execute ConnectionCallback Connection CciTemplate callback

callback InteractionCallback Interaction

publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{

publicStringgetData(Stringinput){

ECIInteractionSpecinteractionSpec=...;

Stringoutput=(String)getCciTemplate().execute(interactionSpec,

newInteractionCallback(){

publicObjectdoInInteraction(Interactioninteraction,ConnectionFactoryfactory)

throwsResourceException{

Recordinput=newCommAreaRecord(inputString.getBytes());

Recordoutput=newCommAreaRecord();

interaction.execute(holder.getInteractionSpec(),input,output);

returnnewString(output.toByteArray());

}

});

returnoutput;

}

}

non-managedspringbeans

<beanid="managedConnectionFactory"class="com.ibm.connector2.cics.ECIManagedConnectionFactory">

<propertyname="serverName"value="TXSERIES"/>

<propertyname="connectionURL"value="local:"/>

<propertyname="userName"value="CICSUSER"/>

<propertyname="password"value="CICS"/>

</bean>

<beanid="connectionFactory"class="org.springframework.jca.support.LocalConnectionFactoryBean">

<propertyname="managedConnectionFactory"ref="managedConnectionFactory"/>

</bean>

<beanid="component"class="mypackage.MyDaoImpl">

<propertyname="connectionFactory"ref="connectionFactory"/>

</bean>

managedmodeJ2EE

<beanid="connectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="eis/cicseci"/>

</bean>

<beanid="component"class="MyDaoImpl">

<propertyname="connectionFactory"ref="connectionFactory"/>

</bean>

21.4.CCIorg.springframework.jca.cci.objectEIS CCIAPI recordrecord: CciTemplate RecordCreator/RecordExtractorSpringCCI

21.4.1.MappingRecordOperationMappingRecordOperation CciTemplate pre-configured

createInputRecord(..)Record

extractOutputData(..) Record

publicabstractclassMappingRecordOperationextendsEisOperation{

...

protectedabstractRecordcreateInputRecord(RecordFactoryrecordFactory,ObjectinputObject)

throwsResourceException,DataAccessException{...}

protectedabstractObjectextractOutputData(RecordoutputRecord)

throwsResourceException,SQLException,DataAccessException{...}

...

}

EISexecuteapplication-level

publicabstractclassMappingRecordOperationextendsEisOperation{

...

publicObjectexecute(ObjectinputObject)throwsDataAccessException{

...

}

CciTemplate execute InteractionSpec InteractionSpec InteractionSpec

InteractionSpecspec=...;

MyMappingRecordOperationeisOperation=newMyMappingRecordOperation(getConnectionFactory(),spec);

...

21.4.2.MappingCommAreaOperationCOMMAREAEISMappingCommAreaOperation MappingRecordOperationCOMMAREA CommAreaRecordrecord COMMAREACOMMAREA

publicabstractclassMappingCommAreaOperationextendsMappingRecordOperation{

...

protectedabstractbyte[]objectToBytes(ObjectinObject)

throwsIOException,DataAccessException;

protectedabstractObjectbytesToObject(byte[]bytes)

throwsIOException,DataAccessException;

...

}

21.4.3. MappingRecordOperation CciTemplate CciTemplaterecord setOutputRecordCreator(..)

21.4.4. CciTemplate

21.2.UsageofInteractionexecutemethods

MappingRecordOperation

methodsignatureMappingRecordOperation

outputRecordCreator

property

executemethodcalledontheCCI

Interaction

Objectexecute(Object) notsetRecord

execute(InteractionSpec,Record)

Objectexecute(Object) setboolean

execute(InteractionSpec,Record,Record)

21.4.5.MappingRecordOperation

BlackboxCCI MappingRecordOperation

SUNJ2EESDK1.3CCI InteractionSpecSQL CCIrecordCCI

publicclassPersonMappingOperationextendsMappingRecordOperation{

publicPersonMappingOperation(ConnectionFactoryconnectionFactory){

setConnectionFactory(connectionFactory);

CciInteractionSpecinteractionSpec=newCciConnectionSpec();

interactionSpec.setSql("select*frompersonwhereperson_id=?");

setInteractionSpec(interactionSpec);

}

protectedRecordcreateInputRecord(RecordFactoryrecordFactory,ObjectinputObject)

throwsResourceException{

Integerid=(Integer)inputObject;

IndexedRecordinput=recordFactory.createIndexedRecord("input");

input.add(newInteger(id));

returninput;

}

protectedObjectextractOutputData(RecordoutputRecord)

throwsResourceException,SQLException{

ResultSetrs=(ResultSet)outputRecord;

Personperson=null;

if(rs.next()){

Personperson=newPerson();

person.setId(rs.getInt("person_id"));

person.setLastName(rs.getString("person_last_name"));

person.setFirstName(rs.getString("person_first_name"));

}

returnperson;

}

}

person

publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{

publicPersongetPerson(intid){

PersonMappingOperationquery=newPersonMappingOperation(getConnectionFactory());

Personperson=(Person)query.execute(newInteger(id));

returnperson;

}

}

Springbeansnon-managedmode

<beanid="managedConnectionFactory"

class="com.sun.connector.cciblackbox.CciLocalTxManagedConnectionFactory">

<propertyname="connectionURL"value="jdbc:hsqldb:hsql://localhost:9001"/>

<propertyname="driverName"value="org.hsqldb.jdbcDriver"/>

</bean>

<beanid="targetConnectionFactory"

class="org.springframework.jca.support.LocalConnectionFactoryBean">

<propertyname="managedConnectionFactory"ref="managedConnectionFactory"/>

</bean>

<beanid="connectionFactory"

class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">

<propertyname="targetConnectionFactory"ref="targetConnectionFactory"/>

<propertyname="connectionSpec">

<beanclass="com.sun.connector.cciblackbox.CciConnectionSpec">

<propertyname="user"value="sa"/>

<propertyname="password"value=""/>

</bean>

</property>

</bean>

<beanid="component"class="MyDaoImpl">

<propertyname="connectionFactory"ref="connectionFactory"/>

</bean>

managedmodeJ2EE)

<beanid="targetConnectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="eis/blackbox"/>

</bean>

<beanid="connectionFactory"

class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">

<propertyname="targetConnectionFactory"ref="targetConnectionFactory"/>

<propertyname="connectionSpec">

<beanclass="com.sun.connector.cciblackbox.CciConnectionSpec">

<propertyname="user"value="sa"/>

<propertyname="password"value=""/>

</bean>

</property>

</bean>

<beanid="component"class="MyDaoImpl">

<propertyname="connectionFactory"ref="connectionFactory"/>

</bean>

21.4.6.MappingCommAreaOperation MappingCommAreaOperationIBMECIECICICSCCI InteractionSpecCICS

publicabstractclassEciMappingOperationextendsMappingCommAreaOperation{

publicEciMappingOperation(ConnectionFactoryconnectionFactory,StringprogramName){

setConnectionFactory(connectionFactory);

ECIInteractionSpecinteractionSpec=newECIInteractionSpec(),

interactionSpec.setFunctionName(programName);

interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);

interactionSpec.setCommareaLength(30);

setInteractionSpec(interactionSpec);

setOutputRecordCreator(newEciOutputRecordCreator());

}

privatestaticclassEciOutputRecordCreatorimplementsRecordCreator{

publicRecordcreateRecord(RecordFactoryrecordFactory)throwsResourceException{

returnnewCommAreaRecord();

}

}

}

The abstract EciMappingOperation class can then be subclassed tospecifymappingsbetweencustomobjectsandRecords.

EciMappingOperation Records

publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{

publicOutputObjectgetData(Integerid){

EciMappingOperationquery=newEciMappingOperation(getConnectionFactory(),"MYPROG"){

protectedabstractbyte[]objectToBytes(ObjectinObject)throwsIOException{

Integerid=(Integer)inObject;

returnString.valueOf(id);

}

protectedabstractObjectbytesToObject(byte[]bytes)throwsIOException;

Stringstr=newString(bytes);

Stringfield1=str.substring(0,6);

Stringfield2=str.substring(6,1);

Stringfield3=str.substring(7,1);

returnnewOutputObject(field1,field2,field3);

}

});

return(OutputObject)query.execute(newInteger(id));

}

}

Springbeansnon-managedmode

<beanid="managedConnectionFactory"class="com.ibm.connector2.cics.ECIManagedConnectionFactory">

<propertyname="serverName"value="TXSERIES"/>

<propertyname="connectionURL"value="local:"/>

<propertyname="userName"value="CICSUSER"/>

<propertyname="password"value="CICS"/>

</bean>

<beanid="connectionFactory"class="org.springframework.jca.support.LocalConnectionFactoryBean">

<propertyname="managedConnectionFactory"ref="managedConnectionFactory"/>

</bean>

<beanid="component"class="MyDaoImpl">

<propertyname="connectionFactory"ref="connectionFactory"/>

</bean>

managedmodeJ2EE

<beanid="connectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="eis/cicseci"/>

</bean>

<beanid="component"class="MyDaoImpl">

<propertyname="connectionFactory"ref="connectionFactory"/>

</bean>

21.5.JCAresourceadapters ra.xmlCICSECIIMS

<connector>

<resourceadapter>

<!--<transaction-support>NoTransaction</transaction-support>-->

<!--<transaction-support>LocalTransaction</transaction-support>-->

<transaction-support>XATransaction</transaction-support>

<resourceadapter>

<connector>

Spring JtaTransactionManager

CCIConnectionFactory SpringCCI JDBCDataSourceTransactionManagerCCIAPICciLocalTransactionManager CCI SpringPlatformTransactionManager

<beanid="eciConnectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="eis/cicseci"/>

</bean>

<beanid="eciTransactionManager"

class="org.springframework.jca.cci.connection.CciLocalTransactionManager">

<propertyname="connectionFactory"ref="eciConnectionFactory"/>

</bean>

Spring Spring PlatformTransactionManager

JtaTransactionManager CciLocalTransactionManagerSpring 9

22Spring

22.1.22.2.Spring

22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator

22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.

jarclasspathSpringFramework

JavaMailmail.jar

JAFactivation.jar

SpringFrameworkSpring-with-dependenciesrelease()

22.1.SpringSpringorg.springframework.mailMailSenderSimpleMailMessagefrom, to,cc,subject,text MailExceptioncheckedExceptionJavadocsJavaMail,MIME,Spring MailSender

,

org.springframework.mail.javamail.JavaMailSenderSpringorg.springframework.mail.javamail.MimeMessagePreparator,JavaMailMIME

22.2.SpringOrderManager:

publicinterfaceOrderManager{

voidplaceOrder(Orderorder);

}

email,

22.2.1.MailSender SimpleMailMessage

importorg.springframework.mail.MailException;

importorg.springframework.mail.MailSender;

importorg.springframework.mail.SimpleMailMessage;

publicclassSimpleOrderManagerimplementsOrderManager{

privateMailSendermailSender;

privateSimpleMailMessagetemplateMessage;

publicvoidsetMailSender(MailSendermailSender){

this.mailSender=mailSender;

}

publicvoidsetTemplateMessage(SimpleMailMessagetemplateMessage){

this.templateMessage=templateMessage;

}

publicvoidplaceOrder(Orderorder){

//Dothebusinesscalculations...

//Callthecollaboratorstopersisttheorder...

//Createathreadsafe"copy"ofthetemplatemessageandcustomizeit

SimpleMailMessagemsg=newSimpleMailMessage(this.templateMessage);

msg.setTo(order.getCustomer().getEmailAddress());

msg.setText(

"Dear"+order.getCustomer().getFirstName()

+order.getCustomer().getLastName()

+",thankyouforplacingorder.Yourordernumberis"

+order.getOrderNumber());

try{

this.mailSender.send(msg);

}

catch(MailExceptionex){

//simplylogitandgoon...

System.err.println(ex.getMessage());

}

}

}

bean:

<beanid="mailSender"class="org.springframework.mail.javamail.JavaMailSenderImpl">

<propertyname="host"value="mail.mycompany.com"/>

</bean>

<!--thisisatemplatemessagethatwecanpre-loadwithdefaultstate-->

<beanid="templateMessage"class="org.springframework.mail.SimpleMailMessage">

<propertyname="from"value="customerservice@mycompany.com"/>

<propertyname="subject"value="Yourorder"/>

</bean>

<beanid="orderManager"class="com.mycompany.businessapp.support.SimpleOrderManager">

<propertyname="mailSender"ref="mailSender"/>

<propertyname="templateMessage"ref="templateMessage"/>

</bean>

22.2.2. JavaMailSender MimeMessagePreparator

OrderManager, MimeMessagePreparator mailSender

JavaMailSenderJavaMail MimeMessage

importjavax.mail.Message;

importjavax.mail.MessagingException;

importjavax.mail.internet.InternetAddress;

importjavax.mail.internet.MimeMessage;

importjavax.mail.internet.MimeMessage;

importorg.springframework.mail.MailException;

importorg.springframework.mail.javamail.JavaMailSender;

importorg.springframework.mail.javamail.MimeMessagePreparator;

publicclassSimpleOrderManagerimplementsOrderManager{

privateJavaMailSendermailSender;

publicvoidsetMailSender(JavaMailSendermailSender){

this.mailSender=mailSender;

}

publicvoidplaceOrder(finalOrderorder){

//Dothebusinesscalculations...

//Callthecollaboratorstopersisttheorder...

MimeMessagePreparatorpreparator=newMimeMessagePreparator(){

publicvoidprepare(MimeMessagemimeMessage)throwsException{

mimeMessage.setRecipient(Message.RecipientType.TO,

newInternetAddress(order.getCustomer().getEmailAddress()));

mimeMessage.setFrom(newInternetAddress("mail@mycompany.com"));

mimeMessage.setText(

"Dear"+order.getCustomer().getFirstName()+""

+order.getCustomer().getLastName()

+",thankyouforplacingorder.Yourordernumberis"

+order.getOrderNumber());

}

};

try{

this.mailSender.send(preparator);

}

catch(MailExceptionex){

//simplylogitandgoon...

System.err.println(ex.getMessage());

}

}

}

SpringAOP OrderManagerjoinpointSpring FrameworkMailSenderJavaMailJason Hunter MailMessage

com.oreilly.servletJavadocs

22.3. MimeMessageHelper

org.springframework.mail.javamail.MimeMessageHelperJavaMailJavaMailAPI MimeMessageHelperMimeMessage

//ofcourseyouwoulduseDIinanyreal-worldcases

JavaMailSenderImplsender=newJavaMailSenderImpl();

sender.setHost("mail.host.com");

MimeMessagemessage=sender.createMimeMessage();

MimeMessageHelperhelper=newMimeMessageHelper(message);

helper.setTo("test@host.com");

helper.setText("Thankyouforordering!");

sender.send(message);

22.3.1.(inlineresources)Multipartemail(inlineresources)

22.3.1.1.MimeMessageHelperemailJPEG

JavaMailSenderImplsender=newJavaMailSenderImpl();

sender.setHost("mail.host.com");

MimeMessagemessage=sender.createMimeMessage();

//usethetrueflagtoindicateyouneedamultipartmessage

MimeMessageHelperhelper=newMimeMessageHelper(message,true);

helper.setTo("test@host.com");

helper.setText("Checkoutthisimage!");

//let'sattachtheinfamouswindowsSamplefile(thistimecopiedtoc:/)

FileSystemResourcefile=newFileSystemResource(newFile("c:/Sample.jpg"));

helper.addAttachment("CoolImage.jpg",file);

sender.send(message);

22.3.1.2.MimeMessageHelperemail

JavaMailSenderImplsender=newJavaMailSenderImpl();

sender.setHost("mail.host.com");

MimeMessagemessage=sender.createMimeMessage();

//usethetrueflagtoindicateyouneedamultipartmessage

MimeMessageHelperhelper=newMimeMessageHelper(message,true);

helper.setTo("test@host.com");

//usethetrueflagtoindicatethetextincludedisHTML

helper.setText("<html><body><imgsrc='cid:identifier1234'></body></html>",true);

//let'sincludetheinfamouswindowsSamplefile(thistimecopiedtoc:/)

FileSystemResourceres=newFileSystemResource(newFile("c:/Sample.jpg"));

helper.addInline("identifier1234",res);

sender.send(message);

Content-ID( identifier1234)mime

22.3.2.message.setText(..) API

,JavaHTML

Java……FreeMarkerVelocityVelocity

22.3.2.1.VelocityVelocityVelocityclasspath VelocityVelocityHTML

#inthecom/foo/package

<html>

<body>

<h3>Hi${user.userName},welcometotheChippingSodburyOn-the-Hillmessageboards!</h3>

<div>

Youremailaddressis<ahref="mailto:${user.emailAddress}">${user.emailAddress}</a>.

</div>

</body>

</html>

SpringXMLVelocity

packagecom.foo;

importorg.apache.velocity.app.VelocityEngine;

importorg.springframework.mail.javamail.JavaMailSender;

importorg.springframework.mail.javamail.MimeMessageHelper;

importorg.springframework.mail.javamail.MimeMessagePreparator;

importorg.springframework.ui.velocity.VelocityEngineUtils;

importjavax.mail.internet.MimeMessage;

importjava.util.HashMap;

importjava.util.Map;

publicclassSimpleRegistrationServiceimplementsRegistrationService{

privateJavaMailSendermailSender;

privateVelocityEnginevelocityEngine;

publicvoidsetMailSender(JavaMailSendermailSender){

this.mailSender=mailSender;

}

publicvoidsetVelocityEngine(VelocityEnginevelocityEngine){

this.velocityEngine=velocityEngine;

}

publicvoidregister(Useruser){

//Dotheregistrationlogic...

sendConfirmationEmail(user);

}

privatevoidsendConfirmationEmail(finalUseruser){

MimeMessagePreparatorpreparator=newMimeMessagePreparator(){

publicvoidprepare(MimeMessagemimeMessage)throwsException{

MimeMessageHelpermessage=newMimeMessageHelper(mimeMessage);

message.setTo(user.getEmailAddress());

message.setFrom("webmaster@csonth.gov.uk");//couldbeparameterized...

Mapmodel=newHashMap();

model.put("user",user);

Stringtext=VelocityEngineUtils.mergeTemplateIntoString(

velocityEngine,"com/dns/registration-confirmation.vm",model);

message.setText(text,true);

}

};

this.mailSender.send(preparator);

}

}

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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.5.xsd">

<beanid="mailSender"class="org.springframework.mail.javamail.JavaMailSenderImpl">

<propertyname="host"value="mail.csonth.gov.uk"/>

</bean>

<beanid="registrationService"class="com.foo.SimpleRegistrationService">

<propertyname="mailSender"ref="mailSender"/>

<propertyname="velocityEngine"ref="velocityEngine"/>

</bean>

<beanid="velocityEngine"class="org.springframework.ui.velocity.VelocityEngineFactoryBean">

<propertyname="velocityProperties">

<value>

resource.loader=class

class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader

</value>

</property>

</bean>

</beans>

23Spring(Scheduling)(ThreadPooling)

23.1.23.2.OpenSymphonyQuartz

23.2.1.JobDetailBean23.2.2. MethodInvokingJobDetailFactoryBean

23.2.3.triggersSchedulerFactoryBean23.3.JDKTimer

23.3.1.timers23.3.2. MethodInvokingTimerTaskFactoryBean

23.3.3. TimerFactoryBean

23.4.SpringTaskExecutor23.4.1.TaskExecutor23.4.2.TaskExecutor23.4.3.TaskExecutor

23.1.SpringSpringJDK1.3 TimerQuartzScheduler(http://www.opensymphony.com/quartz/) FactoryBeanTimerTrigger

QuartzScheduler Timer MethodInvokingFactoryBeanSpringJava1.3,1.4,5JEE

23.2.OpenSymphonyQuartzQuartz Trigger,JobJobDetailQuartz http://www.opensymphony.com/quartz

SpringSpringuartz

23.2.1.JobDetailBeanJobDetailSpring JobDetailBeanJobDetail

<beanname="exampleJob"class="org.springframework.scheduling.quartz.JobDetailBean">

<propertyname="jobClass"value="example.ExampleJob"/>

<propertyname="jobDataAsMap">

<map>

<entrykey="timeout"value="5"/>

</map>

</property>

</bean>

Jobdetailbeanjob( ExampleJob) jobdatamaptimeoutJobdatamapJobExecutionContext) JobDetailBeanjobdatamapjobExampleJob timeout JobDetailBean

packageexample;

publicclassExampleJobextendsQuartzJobBean{

privateinttimeout;

/**

*SettercalledaftertheExampleJobisinstantiated

*withthevaluefromtheJobDetailBean(5)

*/

publicvoidsetTimeout(inttimeout){

this.timeout=timeout;

}

protectedvoidexecuteInternal(JobExecutionContextctx)throwsJobExecutionException{

//dotheactualwork

}

}

Jobdetailbeannamegroup,jobjobjobdetailbean exampleJob

23.2.2. MethodInvokingJobDetailFactoryBean

, MethodInvokingJobDetailFactoryBean

<beanid="jobDetail"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

<propertyname="targetObject"ref="exampleBusinessObject"/>

<propertyname="targetMethod"value="doIt"/>

</bean>

exampleBusinessObjectdoIt

publicclassExampleBusinessObject{

//propertiesandcollaborators

publicvoiddoIt(){

//dotheactualwork

}

}

<beanid="exampleBusinessObject"class="examples.ExampleBusinessObject"/>

MethodInvokingJobDetailFactoryBeanjob,QuartzJobsjobs JobDetail

Stateful jobjobjobs,concurrentfalse

<beanid="jobDetail"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">

<propertyname="targetObject"ref="exampleBusinessObject"/>

<propertyname="targetMethod"value="doIt"/>

<propertyname="concurrent"value="false"/>

</bean>

jobs

23.2.3.triggers SchedulerFactoryBean

jobdetails,jobsbeantriggersSpringtriggers CronTriggerBeanSimpleTriggerBean

TriggersSpring SchedulerFactoryBeantriggers SchedulerFactoryBean

triggers

<beanid="simpleTrigger"class="org.springframework.scheduling.quartz.SimpleTriggerBean">

<!--seetheexampleofmethodinvokingjobabove-->

<propertyname="jobDetail"ref="jobDetail"/>

<!--10seconds-->

<propertyname="startDelay"value="10000"/>

<!--repeatevery50seconds-->

<propertyname="repeatInterval"value="50000"/>

</bean>

<beanid="cronTrigger"class="org.springframework.scheduling.quartz.CronTriggerBean">

<propertyname="jobDetail"ref="exampleJob"/>

<!--runeverymorningat6AM-->

<propertyname="cronExpression"value="006**?"/>

</bean>

triggers10506

<beanclass="org.springframework.scheduling.quartz.SchedulerFactoryBean">

<propertyname="triggers">

<list>

<refbean="cronTrigger"/>

<refbean="simpleTrigger"/>

</list>

</property>

</bean>

SchedulerFactoryBeanjobdetailsCalendars,QuartzJavaDOC(http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html

23.3.JDKTimerJDKTimertimertimertimers

23.3.1.timersTimerTasktimertasksQuartzjobs:

publicclassCheckEmailAddressesextendsTimerTask{

privateListemailAddresses;

publicvoidsetEmailAddresses(ListemailAddresses){

this.emailAddresses=emailAddresses;

}

publicvoidrun(){

//iterateoverallemailaddressesandarchivethem

}

}

:

<beanid="checkEmail"class="examples.CheckEmailAddress">

<propertyname="emailAddresses">

<list>

<value>test@springframework.org</value>

<value>foo@bar.com</value>

<value>john@doe.net</value>

</list>

</property>

</bean>

<beanid="scheduledTask"class="org.springframework.scheduling.timer.ScheduledTimerTask">

<!--wait10secondsbeforestartingrepeatedexecution-->

<propertyname="delay"value="10000"/>

<!--runevery50seconds-->

<propertyname="period"value="50000"/>

<propertyname="timerTask"ref="checkEmail"/>

</bean>

period0

23.3.2. MethodInvokingTimerTaskFactoryBean

Quartz Timer:

<beanid="doIt"class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">

<propertyname="targetObject"ref="exampleBusinessObject"/>

<propertyname="targetMethod"value="doIt"/>

</bean>

exampleBusinessObjectdoIt():

publicclassBusinessObject{

//propertiesandcollaborators

publicvoiddoIt(){

//dotheactualwork

}

}

ScheduledTimerTasktimerTaskdoItbeandoIt

23.3.3. TimerFactoryBean

TimerFactoryBeanQuartzSchedulerFactoryBean TimerFactoryBean

Timer

<beanid="timerFactory"class="org.springframework.scheduling.timer.TimerFactoryBean">

<propertyname="scheduledTimerTasks">

<list>

<!--seetheexampleabove-->

<refbean="scheduledTask"/>

</list>

</property>

</bean>

java.util.concurrent

DougLeaDawidKurzyniecjava.util.concurrent

23.4.SpringTaskExecutorSpring2.0(Executor)ExecutorJava5 SpringJava1.31.41.3,1.4,5,JavaEE

23.4.1.TaskExecutorSpring TaskExecutorjava.util.concurrent.Executor Java5execute(Runnabletask)

TaskExecutorSpring ApplicationEventMulticaster

AbstractMessageListenerContainerQuartzTaskExecutor bean

23.4.2.TaskExecutorSpring TaskExecutor

SimpleAsyncTaskExecutor

SyncTaskExecutortestcaseConcurrentTaskExecutorJava5 java.util.concurrent.Executor, ThreadPoolTaskExecutor

Executorbean ConcurrentTaskExecutor,ThreadPoolTaskExecutor ConcurrentTaskExecutor

SimpleThreadPoolTaskExecutorQuartz SimpleThreadPoolSpringQuartzQuartz

ThreadPoolTaskExecutorJava5beanproperties

java.util.concurrent.ThreadPoolExecutorTaskExecutor

ScheduledThreadPoolExecutor,ConcurrentTaskExecutor

CommonJBEAIBMJavaEEBEAIBM

TimerTaskExecutor

TimerTask SyncTaskExecutor

WorkManagerTaskExecutor

CommonJWorkManagerSpringcontextCommonJWorkManagerSimpleThreadPoolTaskExecutor

WorkManagerWorkManager

23.4.3. TaskExecutor

Spring TaskExecutorJavaBeansbean, ThreadPoolTaskExecutor

importorg.springframework.core.task.TaskExecutor;

publicclassTaskExecutorExample{

privateclassMessagePrinterTaskimplementsRunnable{

privateStringmessage;

publicMessagePrinterTask(Stringmessage){

this.message=message;

}

publicvoidrun(){

System.out.println(message);

}

}

privateTaskExecutortaskExecutor;

publicTaskExecutorExample(TaskExecutortaskExecutor){

this.taskExecutor=taskExecutor;

}

publicvoidprintMessages(){

for(inti=0;i<25;i++){

taskExecutor.execute(newMessagePrinterTask("Message"+i));

}

}

}

Runnable TaskExecutor

TaskExecutorbeanproperties

<beanid="taskExecutor"class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">

<propertyname="corePoolSize"value="5"/>

<propertyname="maxPoolSize"value="10"/>

<propertyname="queueCapacity"value="25"/>

</bean>

<beanid="taskExecutorExample"class="TaskExecutorExample">

<constructor-argref="taskExecutor"/>

</bean>

24

24.1.24.2.24.3.bean

24.3.1.24.3.2.JRubybeans24.3.3.Groovybeans24.3.4.BeanShellbeans

24.4.24.4.1.SpringMVC24.4.2.Validator

24.5.Bitsandbobs24.5.1.AOP-bean24.5.2.

24.6.

aJava cSpringSpring

24.1.Spring2.0SpringJRubySpringSpring

JRuby

Groovy

BeanShell24.4“” Spring

Spring2.0Spring 1.2.x

24.2.SpringbeanbeanGroovySpringGroovybean MessengerJava MessengerGroovy

packageorg.springframework.scripting;

publicinterfaceMessenger{

StringgetMessage();

}

Messenger

packageorg.springframework.scripting;

publicclassDefaultBookingServiceimplementsBookingService{

privateMessengermessenger;

publicvoidsetMessenger(Messengermessenger){

this.messenger=messenger;

}

publicvoidprocessBooking(){

//usetheinjectedMessengerobject...

}

}

GroovyMessenger

//fromthefile'Messenger.groovy'

packageorg.springframework.scripting.groovy;

//importtheMessengerinterface(writteninJava)thatistobeimplemented

importorg.springframework.scripting.Messenger

//definetheimplementationinGroovy

classGroovyMessengerimplementsMessenger{

Stringmessage

}

beanGroovy MessengerDefaultBookingService

dynamic-language-backedbeanSpringXMLXMLSchemaSpring ApplicationContextIoCSpring BeanFactory

dynamic-language-backedbeanSpringXMLSchema A,XMLSchema-basedconfiguration

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:lang="http://www.springframework.org/schema/lang"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd">

<!--thisisthebeandefinitionfortheGroovy-backedMessenger

<lang:groovyid="messenger"script-source="classpath:Messenger.groovy">

<lang:propertyname="message"value="ICanDoTheFrug"/>

</lang:groovy>

<!--anotherwisenormalbeanthatwillbeinjectedbytheGroovy-backed

<beanid="bookingService"class="x.y.DefaultBookingService">

<propertyname="messenger"ref="messenger"/>

</bean>

</beans>

bookingServicebean DefaultBookingService messenger

MessengerJavaGroovyXML

XMLSchemaSpring2.0XMLSchemaSpringXMLDTDXMLSchema <lang:language/>

SpringXMLSchemaSpring

24.3.beanSpringSpringbeanGroovyGroovy

24.3.1.dynamic-language-backedbean

:)

XML <lang:language/>dynamic-language-backedbeanSpringAPI---beanbean

Spring

24.3.1.1.<lang:language/>dynamic-language-backedbeanbeanJavabeanJavabeandynamic language-backed bean<lang:language/>

<lang:language/>

<lang:jruby/>JRuby

<lang:groovy/>Groovy

<lang:bsh/>BeanShellbean

24.3.1.2.RefreshablebeanSpring 'refreshablebean'refreshablebeandynamic-language-backedbeandynamic-language-backedbeanSpringbeanbeanwebdynamic-language-backedbean

offrefreshablebeanrefreshablebeanbean SpringXMLrefreshablebean

<beans>

<!--thisbeanisnow'refreshable'duetothepresenceofthe'refresh-check-delay'attribute-->

<lang:groovyid="messenger"

refresh-check-delay="5000"<!--switchesrefreshingonwith5secondsbetweenchecks-->

script-source="classpath:Messenger.groovy">

<lang:propertyname="message"value="ICanDoTheFrug"/>

</lang:groovy>

<beanid="bookingService"class="x.y.DefaultBookingService">

<propertyname="messenger"ref="messenger"/>

</bean>

</beans>

'messenger'bean'refresh-check-delay'beanbean

refreshable 'jumping-through-hoops-to-pause-the-execution'System.in.read()dynamic-language-backedbean

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

importorg.springframework.scripting.Messenger;

publicfinalclassBoot{

publicstaticvoidmain(finalString[]args)throwsException{

ApplicationContextctx=newClassPathXmlApplicationContext("beans.xml");

Messengermessenger=(Messenger)ctx.getBean("messenger");

System.out.println(messenger.getMessage());

//pauseexecutionwhileIgooffandmakechangestothesourcefile...

System.in.read();

System.out.println(messenger.getMessage());

}

}

MessengergetMessage()message Messenger.groovy

packageorg.springframework.scripting

classGroovyMessengerimplementsMessenger{

privateStringmessage="Bingo"

publicStringgetMessage(){

//changetheimplementationtosurroundthemessageinquotes

return"'"+this.message+"'"

}

publicvoidsetMessage(Stringmessage){

this.message=message

}

}

ICanDoTheFrugdynamic-language-backedgetMessage()'ICanDoTheFrug'

'refresh-check-delay'beanbeanrefreshablebean <lang:inline-script/> 24.3.1.3“”

24.3.1.3.Springbean <lang:inline-script/>

<lang:groovyid="messenger">

<lang:inline-script>

packageorg.springframework.scripting.groovy;

importorg.springframework.scripting.Messenger

classGroovyMessengerimplementsMessenger{

Stringmessage

}

</lang:inline-script>

<lang:propertyname="message"value="ICanDoTheFrug"/>

</lang:groovy>

Spring <lang:inline-script/>

Validator 24.4.2“Validator”

JRubybeanSpringXML

<lang:jrubyid="messenger"script-interfaces="org.springframework.scripting.Messenger">

<lang:inline-script>

require'java'

include_class'org.springframework.scripting.Messenger'

classRubyMessenger&lt;Messenger

defsetMessage(message)

@@message=message

end

defgetMessage

@@message

end

end

</lang:inline-script>

<lang:propertyname="message"value="HelloWorld!"/>

</lang:jruby>

24.3.1.4.dynamic-language-backedbeanSpringdynamic-language-backedbeandynamic-language-backedbean 100

//fromthefile'Messenger.groovy'

packageorg.springframework.scripting.groovy;

importorg.springframework.scripting.Messenger

classGroovyMessengerimplementsMessenger{

GroovyMessenger(){}

JRubySpringJRubyclasspathSpringJRuby

jruby.jar

cglib-nodep-2.1_3.jar

//thisconstructorisnotavailableforConstructorInjection

GroovyMessenger(Stringmessage){

this.message=message;

}

Stringmessage

StringanotherMessage

}

<lang:groovyid="badMessenger"

script-source="classpath:Messenger.groovy">

<!--thisnextconstructorargumentwill*not*beinjectedintothe

<!--infact,thisisn'tevenallowedaccordingtotheschema-->

<constructor-argvalue="Thiswill*not*work"/>

<!--onlypropertyvaluesareinjectedintothedynamic-language-backedobject-->

<lang:propertyname="anotherMessage"value="Passedstraightthroughtothedynamic-language-backedobject"/>

</lang>

setter

24.3.2.JRubybeansJRuby...“JRubyRubyJava ”SpringSpringJRubybeanJRubyRubySpringJRuby <lang:ruby>'script-

interfaces'SpringJDKJRubybean,JRubybeanJRuby Messenger

packageorg.springframework.scripting;

publicinterfaceMessenger{

StringgetMessage();

}

require'java'

classRubyMessenger

includeorg.springframework.scripting.Messenger

defsetMessage(message)

@@message=message

end

defgetMessage

@@message

end

end

#thislastlineisnotessential(butseebelow)

RubyMessenger.new

SpringXML RubyMessenger(JRubybean)

<lang:jrubyid="messageService"

script-interfaces="org.springframework.scripting.Messenger"

script-source="classpath:RubyMessenger.rb">

<lang:propertyname="message"value="HelloWorld!"/>

</lang:jruby>

JRuby 'RubyMessenger.new'SpringJRubyJRubyJRubydynamic-language-backedbeanJRuby

require'java'

include_class'org.springframework.scripting.Messenger'

#classdefinitionsameasabove...

#instantiateandreturnanewinstanceoftheRubyMessengerclass

RubyMessenger.new

GroovySpringGroovyclasspathjar

groovy-1.0.jar

asm-2.2.2.jar

antlr-2.7.6.jar

SpringJRubyJRubySpringJRubyJRuby ScriptCompilationExceptionSpringdynamic-language-backedbean,:org.springframework.scripting.ScriptCompilationException:

CompilationofJRubyscriptreturned''

JRuby-dynamic-language-backedbean()JRuby(Spring)24.4“” JRubybean.

24.3.3.GroovybeansGroovy...“GroovyJava2PythonRubySmalltalkJavaJavaGroovy-dynamic-language-backedbean (Spring)

Groovy1.4JDK

packageorg.springframework.scripting;

publicinterfaceCalculator{

intadd(intx,inty);

}

Groovy Calculator

//fromthefile'calculator.groovy'

packageorg.springframework.scripting.groovy

classGroovyCalculatorimplementsCalculator{

intadd(intx,inty){

x+y

}

}

<--fromthefile'beans.xml'-->

<beans>

<lang:groovyid="calculator"script-source="classpath:calculator.groovy"/>

</beans>

packageorg.springframework.scripting;

importorg.springframework.context.ApplicationContext;

importorg.springframework.context.support.ClassPathXmlApplicationContext;

publicclassMain{

publicstaticvoidMain(String[]args){

ApplicationContextctx=newClassPathXmlApplicationContext("beans.xml");

Calculatorcalc=(Calculator)ctx.getBean("calculator");

System.out.println(calc.add(2,8));

}

}

10 24.4“”

, GroovyclassGroovyJava(public)

24.3.3.1.GroovyGroovyObjectCustomizer Groovybean

publicinterfaceGroovyObjectCustomizer{

voidcustomize(GroovyObjectgoo);

}

SpringGroovybean GroovyObjectGroovyObject MetaClass

publicfinalclassSimpleMethodTracingCustomizerimplementsGroovyObjectCustomizer{

publicvoidcustomize(GroovyObjectgoo){

DelegatingMetaClassmetaClass=newDelegatingMetaClass(goo.getMetaClass()){

BeanShellSpringBeanShellclasspath

bsh-2.0b4.jar

cglib-nodep-2.1_3.jar

Spring-with-dependecies

publicObjectinvokeMethod(Objectobject,StringmethodName,Object[]arguments){

System.out.println("Invoking'"+methodName+"'.");

returnsuper.invokeMethod(object,methodName,arguments);

}

};

metaClass.initialize();

goo.setMetaClass(metaClass);

}

}

GroovyGroovy

<!--definetheGroovyObjectCustomizerjustlikeanyotherbean-->

<beanid="tracingCustomizer"class="example.SimpleMethodTracingCustomizer"/>

<!--...andplugitintothedesiredGroovybeanviathe'

<lang:groovyid="calculator"

script-source="classpath:org/springframework/scripting/groovy/Calculator.groovy"

customizer-ref="tracingCustomizer"/>

Spring2.0 GroovyObjectCustomizer

<beanid="calculator"class="org.springframework.scripting.groovy.GroovyScriptFactory">

<constructor-argvalue="classpath:org/springframework/scripting/groovy/Calculator.groovy"/>

<!--definetheGroovyObjectCustomizer(asaninnerbean)-->

<constructor-arg>

<beanid="tracingCustomizer"class="example.SimpleMethodTracingCustomizer"/>

</constructor-arg>

</bean>

<beanclass="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>

24.3.4.BeanShellbeansBeanShell...“BeanShellJavaJavaBeanShellJavaPerlJavaScript

”GroovyBeanShellbeanSpring

BeanShell <lang:bsh>'script-

interfaces'SpringJDKBeanShellbean BeanShell-backedJDK

BeanShellbean Messenger

packageorg.springframework.scripting;

publicinterfaceMessenger{

StringgetMessage();

}

HereistheBeanShell'implementation'(thetermisusedlooselyhere)oftheMessengerinterface.BeanShellMessenger

Stringmessage;

StringgetMessage(){

returnmessage;

}

voidsetMessage(StringaMessage){

message=aMessage;

}

SpringXML“”“”

<lang:bshid="messageService"script-source="classpath:BshMessenger.bsh"

script-interfaces="org.springframework.scripting.Messenger">

<lang:propertyname="message"value="HelloWorld!"/>

</lang:bsh>

24.4“” BeanShellbean

24.4.SpringbeanSpring(Spring)

24.4.1.SpringMVCdynamic-language-backedbeanSpringMVCSpringMVCwebSpringMVCwebSpring SpringMVCdynamic-language-backedbean()bean()

“”dynamic-language-backedbean'refreshablebeans' 24.3.1.2“Refreshablebean”

Groovy org.springframework.web.servlet.mvc.Controller

Spring 'samples/showcases/dynamvc/'

//fromthefile'/WEB-INF/groovy/FortuneController.groovy'

packageorg.springframework.showcase.fortune.web

importorg.springframework.showcase.fortune.service.FortuneService

importorg.springframework.showcase.fortune.domain.Fortune

importorg.springframework.web.servlet.ModelAndView

importorg.springframework.web.servlet.mvc.Controller

importjavax.servlet.http.HttpServletRequest

importjavax.servlet.http.HttpServletResponse

classFortuneControllerimplementsController{

@PropertyFortuneServicefortuneService

ModelAndViewhandleRequest(

HttpServletRequestrequest,HttpServletResponsehttpServletResponse){

returnnewModelAndView("tell","fortune",this.fortuneService.tellFortune())

}

}

<lang:groovyid="fortune"

refresh-check-delay="3000"

script-source="/WEB-INF/groovy/FortuneController.groovy">

<lang:propertyname="fortuneService"ref="fortuneService"/>

</lang:groovy>

24.4.2.ValidatorSpringdynamic-language-backedbeandynamic-language-backedbean

“”dynamic-language-backedbean'refreshablebeans' 24.3.1.2“Refreshablebean”

Groovy org.springframework.validation.Validator

Spring Validator”

importorg.springframework.validation.Validator

importorg.springframework.validation.Errors

importorg.springframework.beans.TestBean

classTestBeanValidatorimplementsValidator{

booleansupports(Classclazz){

returnTestBean.class.isAssignableFrom(clazz)

}

voidvalidate(Objectbean,Errorserrors){

if(bean.name?.trim()?.size()>0){

return

}

errors.reject("whitespace","Cannotbecomposedwhollyofwhitespace.")

}

}

24.5.Bitsandbobs

24.5.Bitsandbobs

24.5.1.AOP-beanSpringAOPbeanSpringAOPbean Springbean

24.5.2.beanbean <lang:language/>

singletonbeanscopeGroovybeanprototype

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:lang="http://www.springframework.org/schema/lang"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd">

<lang:groovyid="messenger"script-source="classpath:Messenger.groovy"

<lang:propertyname="message"value="ICanDoTheRoboCop"/>

</lang:groovy>

<beanid="bookingService"class="x.y.DefaultBookingService">

<propertyname="messenger"ref="messenger"/>

</bean>

</beans>

3 IoC() 3.4“Bean” Spring

25

25.1.25.2.Spring25.3.

25.3.1.@Required

25.3.2.Spring@Annotations25.4.JakartaCommonsAttributes25.5.SpringAOP

25.5.1.25.5.2.

25.1.

/**

*Normalcommentshere

*@@org.springframework.transaction.interceptor.DefaultTransactionAttribute()

*/

publicclassPetStoreImplimplementsPetStoreFacade,OrderService{

/**

*Normalcommentshere

*@@org.springframework.transaction.interceptor.RuleBasedTransactionAttribute()

*@@org.springframework.transaction.interceptor.RollbackRuleAttribute(Exception.class)

*@@org.springframework.transaction.interceptor.NoRollbackRuleAttribute("ServletException")

*/

publicvoidechoException(Exceptionex)throwsException{

....

}

JakartaCommonsAttributesXDoclet(Java)Microsoft.NET (pooling)J2EEEJBXML

JavaJava(JSR-175Java5) SpringJMX(AspectJ)Java5 SpringJava1.4JVMSpringXDocletJava1.4CommonsAttributes

25.2.SpringSpringSpring(facade)

Java5

Java5

Java5JavaAPISpring

1.31.4Spring

APICommonsAttributes(Spring1.0-1.2)SpringSpringAttributes

publicinterfaceAttributes{

CollectiongetAttributes(ClasstargetClass);

CollectiongetAttributes(ClasstargetClass,Classfilter);

CollectiongetAttributes(MethodtargetMethod);

CollectiongetAttributes(MethodtargetMethod,Classfilter);

CollectiongetAttributes(FieldtargetField);

CollectiongetAttributes(FieldtargetField,Classfilter);

}

JSR-175.NET Object String NanningAspects ObjectJavaBeanCommonsAttributesSpringAPI Attributes

25.3.SpringJava5+

25.3.1.@Required

org.springframework.beans.factory.annotation@ Required(setter)) Exception

publicclassSimpleMovieLister{

//theSimpleMovieListerhasadependencyontheMovieFinder

privateMovieFindermovieFinder;

//asettermethodsothattheSpringcontainercan'inject'a

@Required

publicvoidsetMovieFinder(MovieFindermovieFinder){

this.movieFinder=movieFinder;

}

//businesslogicthatactually'uses'theinjectedMovieFinder

}

SimpleMovieListerBeanDefinitionsXML

<beanid="movieLister"class="x.y.SimpleMovieLister">

<!--whoops,noMovieFinderisset(andthispropertyis@

</bean>

Spring()

Exceptioninthread"main"java.lang.IllegalArgumentException:

Property'movieFinder'isrequiredforbean'movieLister'.

()Spring '' 'setter' @RequiredAnnotationBeanPostProcessor BeanPostProcessor

@Required'' beanSpringXML

<beanclass="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>

RequiredAnnotationBeanPostProcessor Annotation @RequiredAnnotationBeanPostProcessor

(/)@ Mandatory RequiredAnnotationBeanPostProcessor

@Mandatory

<beanclass="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">

<propertyname="requiredAnnotationType"value="your.company.package.Mandatory"/>

</bean>

@Mandatory (target)(runtimeretentionpolicy)

packageyour.company.package;

importjava.lang.annotation.ElementType;

importjava.lang.annotation.Retention;

importjava.lang.annotation.RetentionPolicy;

importjava.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)

@Target(ElementType.METHOD)

public@interfaceMandatory{

}

25.3.2.Spring@AnnotationsSpring

9.5.6“ @Transactional”

6.8.1“SpringAspectJdomainobject”

6.2“@AspectJ”

3.11“Annotation-based”

3.12“Classpath”

25.4.JakartaCommonsAttributesorg.springframework.metadata.AttributesSpringJakartaCommons

AttributesCommonsAttributes2.2(http://jakarta.apache.org/commons/attributes/)JavaBean (JavaBeanSpring)CommonsAttributes

(fullyqualifiedname,FQN) FQN

JavaBeanBean

/**

*@@MyAttribute(myBooleanJavaBeanProperty=true)

*/

JavaBean(SpringIoC)CommonAttributesJava1.5JavaCommmonsAttributes1.jar$ANT_HOME/libjarSpring

CommonsAttributesjarAPIjar

XDocletxJavadoc.jar

JakartaCommonscommons-collections.jar2.CommonsAttributesant

<taskdefresource="org/apache/commons/attributes/anttasks.properties"/>

3.CommonsAttributesattribute-compiler“”

<targetname="compileAttributes">

<attribute-compilerdestdir="${commons.attributes.tempdir}">

<filesetdir="${src.dir}"includes="**/*.java"/>

</attribute-compiler>

</target>

javacCommonsAttributesMavenCommonsAttributes(Springweb)jar

<attribute-indexerjarFile="myCompiledSources.jar">

<classpathrefid="master-classpath"/>

</attribute-indexer>

SpringjPetStore/attributesSpringAttributesCommonsAttributes CommonsAttributesAPISpring

25.5.SpringAOPSpringAOP.NET

25.5.1.SpringAOP

<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>

<beanclass="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">

<propertyname="transactionInterceptor"ref="txInterceptor"/>

</bean>

<beanid="txInterceptor"class="org.springframework.transaction.interceptor.TransactionInterceptor">

<propertyname="transactionManager"ref="transactionManager"/>

<propertyname="transactionAttributeSource">

<beanclass="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource">

<propertyname="attributes"ref="attributes"/>

</bean>

</property>

</bean>

<beanid="attributes"class="org.springframework.metadata.commons.CommonsAttributes"/>

AOPbeancreatoradvisorbeanorg.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator

beanadvisor("auto-proxy")beanAOPadvisoradvisor (advisor)

beanCommons AttributesAttributesorg.springframework.metadata.Attributes

25.5.2.bean“”

V.Spring

26.26.1.26.2.SpringMVC

26.2.1.26.3.SimpleJdbcTemplate@RepositoryDAO

26.3.1.26.3.2.DataAccessObject26.3.3.

26

26.1.26.2.SpringMVC

26.2.1.26.3.SimpleJdbcTemplate@RepositoryDAO

26.3.1.26.3.2.DataAccessObject26.3.3.

26.1.SpringFramework Spring2.0

26.2.SpringMVCSpring2.0SpringMVCWeb SpringMVCGroovy'FortuneController.groovy''war/WEB-INF/groovy''war/WEB-INF/fortune-servlet.xml'SpringMVC'fortune'beanGroovy

<lang:groovy/>'refresh-check-delay''fortune'beanrefreshablebeanrefreshable3Tomcat'/WEB-INF/groovy''FortuneController.groovy''fortune'bean…………SpringMVCFortuneFortuneServiceGroovyFortuneServiceWebFortuneFortune

26.2.1.samples/showcases/dynamvcweb-appApacheAnt>=1.4GroovyJDK1.4Ant>=1.5“build.bat”"build.batbuild","build.batwarfile"XML"%JAVA_HOME%/jre/lib/ext"JDK1.4 “warfile.bat”WARWAR"dist"

26.3. SimpleJdbcTemplate@RepositoryDAOSpringJava5HibernateJDBCDAO@RepositoryDAO

26.3.1.PartCarModel CarPartsInventory

26.3.2.DataAccessObject3 CarPartsInventoryDAO HibernateJDBC JdbcCarPartsInventoryImplJDBCSimpleJdbcTemplateDAOSimpleJdbcTemplateJava5DAOTemplateHibernateCarPartsInventoryImplHibernateTemplatePartSpringHibernate PlainHibernateCarPartsInventoryImpl

HibernateTemplateHibernate3APIHibernate3APISpringDataAccessExceptions HibernateTemplateSpring2.0@Repository PlainHibernateCarPartsInventoryImplPersistenceExceptionTranslatorPostProcessorHibernateSpringDataAccessExceptions

26.3.3.samples/showcases/java5-dao ApacheAntJava5VM anttests

A.XMLSchema-basedconfiguration

A.1.IntroductionA.2.XMLSchema-basedconfiguration

A.2.1.ReferencingtheschemasA.2.2.TheutilschemaA.2.3.ThejeeschemaA.2.4.ThelangschemaA.2.5.ThejmsschemaA.2.6.Thetx(transaction)schemaA.2.7.TheaopschemaA.2.8.ThecontextschemaA.2.9.ThetoolschemaA.2.10.Thebeansschema

A.3.SettingupyourIDEA.3.1.SettingupEclipseA.3.2.SettingupIntelliJIDEAA.3.3.Integrationissues

DTDsupport?Authoring Spring configurationfilesusingtheolderDTDstyleisstillfullysupported.Nothingwillbreak if you foregothe use of the new XMLSchema-based approach toauthoring Spring XMLconfiguration files. All that youloseoutonistheopportunitytohavemoresuccinctandclearerconfiguration. Regardless ofwhether the XML configurationis DTD- or Schema-based, intheend it all boils down to thesame object model in thecontainer (namely one ormoreBeanDefinitioninstances).

A.1.IntroductionThisappendixdetailstheXMLSchema-basedconfigurationintroducedinSpring2.0.ThecentralmotivationformovingtoXMLSchemabasedconfigurationfileswastomake Spring XML configuration easier.The 'classic' <bean/>-based approach isgood, but its generic-nature comeswitha price in terms of configurationoverhead.FromtheSpringIoCcontainerspoint-of-view,everything is a bean. That's greatnews for the Spring IoC container,because if everything is a bean theneverything can be treated in the exactsamefashion.Thesame,however,isnottrue from a developer's point-of-view.The objects defined in a Spring XMLconfiguration file are not all generic,vanilla beans. Usually, each beanrequiressomedegreeofspecificconfiguration.Spring2.0'snewXMLSchema-basedconfigurationaddressesthisissue.The <bean/> element is still present, and if you wanted to, you couldcontinuetowritetheexactsamestyleofSpringXMLconfigurationusingonly<bean/>elements.ThenewXMLSchema-basedconfigurationdoes,however, make Spring XML configuration files substantially clearer toread.Inaddition,itallowsyoutoexpresstheintentofabeandefinition.The key thing to remember is that the new custom tagswork best forinfrastructure or integration beans: for example, AOP, collections,transactions, integration with 3rd-party frameworks such as Mule, etc.,whiletheexistingbeantagsarebestsuitedtoapplication-specificbeans,suchasDAOs,servicelayerobjects,validators,etc.The examples included below will hopefully convince you that theinclusion of XMLSchema support in Spring 2.0was a good idea. Thereceptioninthecommunityhasbeenencouraging;also,pleasenotethe

fact that this new configuration mechanism is totally customisable andextensible. This means you can write your own domain-specificconfigurationtagsthatwouldbetterrepresentyourapplication'sdomain;theprocessinvolvedindoingsoiscoveredintheappendixentitled B,ExtensibleXMLauthoring.

A.2.XMLSchema-basedconfiguration

A.2.1.ReferencingtheschemasTo switch over from theDTD-style to the newXMLSchema-style, youneedtomakethefollowingchange.

<?xmlversion="1.0"encoding="UTF-8"?>

<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"

"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

<!--<bean/>definitionshere-->

</beans>

TheequivalentfileintheXMLSchema-stylewouldbe...

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<!--<bean/>definitionshere-->

</beans>

The 'xsi:schemaLocation' fragment is not actually required,but can be included to reference a local copy of a schema(whichcanbeusefulduringdevelopment).

TheaboveSpringXMLconfigurationfragmentisboilerplatethatyoucancopyandpaste (!) and then plug <bean/> definitions into like you havealways done. However, the entire point of switching over is to takeadvantageofthenewSpring2.0XMLtagssincetheymakeconfigurationeasier.ThesectionentitledA.2.2“The utilschema”demonstrateshowyou

canstartimmediatelybyusingsomeofthemorecommonutilitytags.The rest of this chapter is devoted to showing examples of the newSpringXMLSchemabasedconfiguration,withat leastoneexample foreverynewtag.Theformatfollowsabeforeandafterstyle,withabeforesnippetofXMLshowingtheold(butstill100%legalandsupported)style,followed immediatelybyanafterexampleshowingtheequivalent in thenewXMLSchema-basedstyle.

A.2.2.TheutilschemaFirstupiscoverageoftheutiltags.Asthenameimplies,theutiltagsdeal with common, utility configuration issues, such as configuringcollections,referencingconstants,andsuchlike.To use the tags in the util schema, you need to have the followingpreamble at the top of your Spring XML configuration file; theemboldenedtext inthesnippetbelowreferencesthecorrectschemasothatthetagsintheutilnamespaceareavailabletoyou.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:util="http://www.springframework.org/schema/util"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-2.5.xsd"

<!--<bean/>definitionshere-->

</beans>

A.2.2.1.<util:constant/>Before...

<beanid="..."class="...">

<propertyname="isolation">

<beanid="java.sql.Connection.TRANSACTION_SERIALIZABLE"

class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>

</property>

</bean>

TheaboveconfigurationusesaSpringFactoryBean implementation, theFieldRetrievingFactoryBean,tosetthevalueofthe'isolation'propertyon a bean to the value of the'java.sql.Connection.TRANSACTION_SERIALIZABLE' constant. This is allwell and good, but it is a tad verbose and (unneccessarily) exposesSpring'sinternalplumbingtotheenduser.The following XMLSchema-based version ismore concise and clearlyexpresses thedeveloper's intent ('inject thisconstantvalue'),and it justreadsbetter.

<beanid="..."class="...">

<propertyname="isolation">

<util:constantstatic-field="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>

</property>

</bean>

A.2.2.1.1.Settingabeanpropertyorconstructorargfromafieldvalue

FieldRetrievingFactoryBean is a FactoryBean which retrieves a static ornon-staticfieldvalue.Itistypicallyusedforretrievingpublicstaticfinalconstants,whichmaythenbeusedtosetapropertyvalueorconstructorargforanotherbean.Findbelowanexamplewhichshowshowastatic field isexposed,byusingthestaticFieldproperty:

<beanid="myField"

class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">

<propertyname="staticField"value="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>

</bean>

There is also a convenience usage form where the static field isspecifiedasthebeanname:

<beanid="java.sql.Connection.TRANSACTION_SERIALIZABLE"

class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>

Thisdoesmeanthatthereisnolongeranychoiceinwhatthebeanidis(soanyotherbeanthatreferstoitwillalsohavetousethislongername),butthisformisveryconcisetodefine,andveryconvenienttouseasaninner bean since the id doesn't have to be specified for the beanreference:

<beanid="..."class="...">

<propertyname="isolation">

<beanid="java.sql.Connection.TRANSACTION_SERIALIZABLE"

class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>

</property>

</bean>

Itisalsopossibletoaccessanon-static(instance)fieldofanotherbean,asdescribedintheAPIdocumentationfortheFieldRetrievingFactoryBeanclass.Injecting enum values into beans as either property or constructorargumentsisveryeasytodoinSpring,inthatyoudon'tactuallyhavetodoanythingorknowanythingabout theSpring internals(orevenaboutclasses such as the FieldRetrievingFactoryBean). Let's look at anexampletoseehoweasyinjectinganenumvalueis;considerthisJDK5enum:

packagejavax.persistence;

publicenumPersistenceContextType{

TRANSACTION,

EXTENDED

}

NowconsiderasetteroftypePersistenceContextType:

packageexample;

publicclassClient{

privatePersistenceContextTypepersistenceContextType;

publicvoidsetPersistenceContextType(PersistenceContextTypetype){

this.persistenceContextType=type;

}

}

..andthecorrespondingbeandefinition:

<beanclass="example.Client">

<propertyname="persistenceContextType"value="TRANSACTION"/>

</bean>

Thisworks forclassic type-safeemulatedenums(onJDK1.4andJDK1.3)aswell;Springwillautomaticallyattempttomatchthestringpropertyvaluetoaconstantontheenumclass.

A.2.2.2.<util:property-path/>Before...

<!--targetbeantobereferencedbyname-->

<beanid="testBean"class="org.springframework.beans.TestBean"scope="prototype">

<propertyname="age"value="10"/>

<propertyname="spouse">

<beanclass="org.springframework.beans.TestBean">

<propertyname="age"value="11"/>

</bean>

</property>

</bean>

<!--willresultin10,whichisthevalueofproperty'age'ofbean'testBean'-->

<beanid="testBean.age"class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>

TheaboveconfigurationusesaSpringFactoryBean implementation, thePropertyPathFactoryBean, to create a bean (of type int) called'testBean.age' that has a value equal to the 'age' property of the'testBean'bean.After...

<!--targetbeantobereferencedbyname-->

<beanid="testBean"class="org.springframework.beans.TestBean"scope="prototype">

<propertyname="age"value="10"/>

<propertyname="spouse">

<beanclass="org.springframework.beans.TestBean">

<propertyname="age"value="11"/>

</bean>

</property>

</bean>

<!--willresultin10,whichisthevalueofproperty'age'ofbean'testBean'-->

<util:property-pathid="name"path="testBean.age"/>

Thevalueofthe'path'attributeofthe<property-path/> tag followstheform'beanName.beanProperty'.

A.2.2.2.1.Using<util:property-path/> to setabeanpropertyorconstructor-argument

PropertyPathFactoryBeanisaFactoryBeanthatevaluatesapropertypathonagiventargetobject.Thetargetobjectcanbespecifieddirectlyorviaabeanname.Thisvaluemaythenbeusedinanotherbeandefinitionasapropertyvalueorconstructorargument.Here'sanexamplewhereapathisusedagainstanotherbean,byname:

//targetbeantobereferencedbyname

<beanid="person"class="org.springframework.beans.TestBean"scope="prototype">

<propertyname="age"value="10"/>

<propertyname="spouse">

<beanclass="org.springframework.beans.TestBean">

<propertyname="age"value="11"/>

</bean>

</property>

</bean>

//willresultin11,whichisthevalueofproperty'spouse.age'ofbean'person'

<beanid="theAge"

class="org.springframework.beans.factory.config.PropertyPathFactoryBean">

<propertyname="targetBeanName"value="person"/>

<propertyname="propertyPath"value="spouse.age"/>

</bean>

Inthisexample,apathisevaluatedagainstaninnerbean:

<!--willresultin12,whichisthevalueofproperty'age'oftheinnerbean-->

<beanid="theAge"

class="org.springframework.beans.factory.config.PropertyPathFactoryBean">

<propertyname="targetObject">

<beanclass="org.springframework.beans.TestBean">

<propertyname="age"value="12"/>

</bean>

</property>

<propertyname="propertyPath"value="age"/>

</bean>

Thereisalsoashortcutform,wherethebeannameisthepropertypath.

<!--willresultin10,whichisthevalueofproperty'age'ofbean'person'-->

<beanid="person.age"

class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>

Thisformdoesmeanthatthereisnochoiceinthenameofthebean.Anyreference to itwill alsohave to use the same id,which is thepath.Ofcourse,ifusedasaninnerbean,thereisnoneedtorefertoitatall:

<beanid="..."class="...">

<propertyname="age">

<beanid="person.age"

class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>

</property>

</bean>

Theresulttypemaybespecificallysetintheactualdefinition.Thisisnotnecessary formostusecases,butcanbeofuse forsome.Please seetheJavadocsformoreinfoonthisfeature.

A.2.2.3.<util:properties/>Before...

<!--createsajava.util.Propertiesinstancewithvaluesloadedfromthesuppliedlocation-->

<beanid="jdbcConfiguration"class="org.springframework.beans.factory.config.PropertiesFactoryBean">

<propertyname="location"value="classpath:com/foo/jdbc-production.properties"/>

</bean>

TheaboveconfigurationusesaSpringFactoryBean implementation, thePropertiesFactoryBean, to instantiate a java.util.Properties instancewithvaluesloadedfromthesuppliedResourcelocation).After...

<!--createsajava.util.Propertiesinstancewithvaluesloadedfromthesuppliedlocation-->

<util:propertiesid="jdbcConfiguration"location="classpath:com/foo/jdbc-production.properties"/>

A.2.2.4.<util:list/>Before...

<!--createsajava.util.Listinstancewithvaluesloadedfromthesupplied

<beanid="emails"class="org.springframework.beans.factory.config.ListFactoryBean">

<propertyname="sourceList">

<list>

<value>pechorin@hero.org</value>

<value>raskolnikov@slums.org</value>

<value>stavrogin@gov.org</value>

<value>porfiry@gov.org</value>

</list>

</property>

</bean>

TheaboveconfigurationusesaSpringFactoryBean implementation, theListFactoryBean, to create a java.util.List instance initialized withvaluestakenfromthesupplied'sourceList'.After...

<!--createsajava.util.Listinstancewithvaluesloadedfromthesupplied

<util:listid="emails">

<value>pechorin@hero.org</value>

<value>raskolnikov@slums.org</value>

<value>stavrogin@gov.org</value>

<value>porfiry@gov.org</value>

</util:list>

You can also explicitly control the exact type of List that will beinstantiated and populated via the use of the 'list-class' attribute onthe <util:list/> element. For example, if we really need ajava.util.LinkedList to be instantiated, we could use the followingconfiguration:

<util:listid="emails"list-class="java.util.LinkedList">

<value>jackshaftoe@vagabond.org</value>

<value>eliza@thinkingmanscrumpet.org</value>

<value>vanhoek@pirate.org</value>

<value>d'Arcachon@nemesis.org</value>

</util:list>

If no 'list-class' attribute is supplied, a List implementation will bechosenbythecontainer.Finally, you can also control the merging behavior using the 'merge'attributeof the<util:list/>element;collectionmerging isdescribed inmoredetailinthesectionentitled3.3.2.4.1“” .

A.2.2.5.<util:map/>Before...

<!--createsajava.util.Mapinstancewithvaluesloadedfromthesupplied

<beanid="emails"class="org.springframework.beans.factory.config.MapFactoryBean">

<propertyname="sourceMap">

<map>

<entrykey="pechorin"value="pechorin@hero.org"/>

<entrykey="raskolnikov"value="raskolnikov@slums.org"/>

<entrykey="stavrogin"value="stavrogin@gov.org"/>

<entrykey="porfiry"value="porfiry@gov.org"/>

</map>

</property>

</bean>

TheaboveconfigurationusesaSpringFactoryBean implementation, theMapFactoryBean, to create a java.util.Map instance initialized with key-

valuepairstakenfromthesupplied'sourceMap'.After...

<!--createsajava.util.Mapinstancewithvaluesloadedfromthesupplied

<util:mapid="emails">

<entrykey="pechorin"value="pechorin@hero.org"/>

<entrykey="raskolnikov"value="raskolnikov@slums.org"/>

<entrykey="stavrogin"value="stavrogin@gov.org"/>

<entrykey="porfiry"value="porfiry@gov.org"/>

</util:map>

You can also explicitly control the exact type of Map that will beinstantiatedandpopulatedviatheuseofthe'map-class'attributeonthe<util:map/>element.Forexample,ifwereallyneedajava.util.TreeMaptobeinstantiated,wecouldusethefollowingconfiguration:

<util:mapid="emails"map-class="java.util.TreeMap">

<entrykey="pechorin"value="pechorin@hero.org"/>

<entrykey="raskolnikov"value="raskolnikov@slums.org"/>

<entrykey="stavrogin"value="stavrogin@gov.org"/>

<entrykey="porfiry"value="porfiry@gov.org"/>

</util:map>

If no 'map-class' attribute is supplied, a Map implementation will bechosenbythecontainer.Finally, you can also control the merging behavior using the 'merge'attribute of the <util:map/> element; collectionmerging is described inmoredetailinthesectionentitled3.3.2.4.1“” .

A.2.2.6.<util:set/>Before...

<!--createsajava.util.Setinstancewithvaluesloadedfromthesupplied

<beanid="emails"class="org.springframework.beans.factory.config.SetFactoryBean">

<propertyname="sourceSet">

<set>

<value>pechorin@hero.org</value>

<value>raskolnikov@slums.org</value>

<value>stavrogin@gov.org</value>

<value>porfiry@gov.org</value>

</set>

</property>

</bean>

TheaboveconfigurationusesaSpringFactoryBean implementation, theSetFactoryBean,tocreateajava.util.Setinstanceinitializedwithvaluestakenfromthesupplied'sourceSet'.After...

<!--createsajava.util.Setinstancewithvaluesloadedfromthesupplied

<util:setid="emails">

<value>pechorin@hero.org</value>

<value>raskolnikov@slums.org</value>

<value>stavrogin@gov.org</value>

<value>porfiry@gov.org</value>

</util:set>

You can also explicitly control the exact type of Set that will beinstantiatedandpopulatedviatheuseofthe'set-class'attributeonthe<util:set/>element.Forexample,ifwereallyneedajava.util.TreeSettobeinstantiated,wecouldusethefollowingconfiguration:

<util:setid="emails"set-class="java.util.TreeSet">

<value>pechorin@hero.org</value>

<value>raskolnikov@slums.org</value>

<value>stavrogin@gov.org</value>

<value>porfiry@gov.org</value>

</util:set>

If no 'set-class' attribute is supplied, a Set implementation will bechosenbythecontainer.Finally, you can also control the merging behavior using the 'merge'attribute of the <util:set/> element; collectionmerging is described inmoredetailinthesectionentitled3.3.2.4.1“” .

A.2.3.ThejeeschemaThe jee tags deal with JEE (Java Enterprise Edition)-related

configurationissues,suchaslookingupaJNDIobjectanddefiningEJBreferences.To use the tags in the jee schema, you need to have the followingpreamble at the top of your Spring XML configuration file; theemboldened text in the followingsnippet references thecorrectschemasothatthetagsinthejeenamespaceareavailabletoyou.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:jee="http://www.springframework.org/schema/jee"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/jeehttp://www.springframework.org/schema/jee/spring-jee-2.5.xsd"

<!--<bean/>definitionshere-->

</beans>

A.2.3.1.<jee:jndi-lookup/>(simple)Before...

<beanid="dataSource"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="jdbc/MyDataSource"/>

</bean>

<beanid="userDao"class="com.foo.JdbcUserDao">

<!--Springwilldothecastautomatically(asusual)-->

<propertyname="dataSource"ref="dataSource"/>

</bean>

After...

<jee:jndi-lookupid="dataSource"jndi-name="jdbc/MyDataSource"/>

<beanid="userDao"class="com.foo.JdbcUserDao">

<!--Springwilldothecastautomatically(asusual)-->

<propertyname="dataSource"ref="dataSource"/>

</bean>

A.2.3.2. <jee:jndi-lookup/> (with single JNDI environmentsetting)Before...

<beanid="simple"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="jdbc/MyDataSource"/>

<propertyname="jndiEnvironment">

<props>

<propkey="foo">bar</prop>

</props>

</property>

</bean>

After...

<jee:jndi-lookupid="simple"jndi-name="jdbc/MyDataSource">

<jee:environment>foo=bar</jee:environment>

</jee:jndi-lookup>

A.2.3.3.<jee:jndi-lookup/> (withmultiple JNDI environmentsettings)Before...

<beanid="simple"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="jdbc/MyDataSource"/>

<propertyname="jndiEnvironment">

<props>

<propkey="foo">bar</prop>

<propkey="ping">pong</prop>

</props>

</property>

</bean>

After...

<jee:jndi-lookupid="simple"jndi-name="jdbc/MyDataSource">

<!--newline-separated,key-valuepairsfortheenvironment(standard

<jee:environment>

foo=bar

ping=pong

</jee:environment>

</jee:jndi-lookup>

A.2.3.4.<jee:jndi-lookup/>(complex)Before...

<beanid="simple"class="org.springframework.jndi.JndiObjectFactoryBean">

<propertyname="jndiName"value="jdbc/MyDataSource"/>

<propertyname="cache"value="true"/>

<propertyname="resourceRef"value="true"/>

<propertyname="lookupOnStartup"value="false"/>

<propertyname="expectedType"value="com.myapp.DefaultFoo"/>

<propertyname="proxyInterface"value="com.myapp.Foo"/>

</bean>

After...

<jee:jndi-lookupid="simple"

jndi-name="jdbc/MyDataSource"

cache="true"

resource-ref="true"

lookup-on-startup="false"

expected-type="com.myapp.DefaultFoo"

proxy-interface="com.myapp.Foo"/>

A.2.3.5.<jee:local-slsb/>(simple)The <jee:local-slsb/> tag configures a reference to an EJBStatelessSessionBean.Before...

<beanid="simple"

class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">

<propertyname="jndiName"value="ejb/RentalServiceBean"/>

<propertyname="businessInterface"value="com.foo.service.RentalService"/>

</bean>

After...

<jee:local-slsbid="simpleSlsb"jndi-name="ejb/RentalServiceBean"

business-interface="com.foo.service.RentalService"/>

A.2.3.6.<jee:local-slsb/>(complex)

<beanid="complexLocalEjb"

class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">

<propertyname="jndiName"value="ejb/RentalServiceBean"/>

<propertyname="businessInterface"value="com.foo.service.RentalService"/>

<propertyname="cacheHome"value="true"/>

<propertyname="lookupHomeOnStartup"value="true"/>

<propertyname="resourceRef"value="true"/>

</bean>

After...

<jee:local-slsbid="complexLocalEjb"

jndi-name="ejb/RentalServiceBean"

business-interface="com.foo.service.RentalService"

cache-home="true"

lookup-home-on-startup="true"

resource-ref="true">

A.2.3.7.<jee:remote-slsb/>The <jee:remote-slsb/> tag configures a reference to a remote EJBStatelessSessionBean.Before...

<beanid="complexRemoteEjb"

class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">

<propertyname="jndiName"value="ejb/MyRemoteBean"/>

<propertyname="businessInterface"value="com.foo.service.RentalService"/>

<propertyname="cacheHome"value="true"/>

<propertyname="lookupHomeOnStartup"value="true"/>

<propertyname="resourceRef"value="true"/>

<propertyname="homeInterface"value="com.foo.service.RentalService"/>

<propertyname="refreshHomeOnConnectFailure"value="true"/>

</bean>

After...

<jee:remote-slsbid="complexRemoteEjb"

jndi-name="ejb/MyRemoteBean"

business-interface="com.foo.service.RentalService"

cache-home="true"

lookup-home-on-startup="true"

resource-ref="true"

home-interface="com.foo.service.RentalService"

refresh-home-on-connect-failure="true">

A.2.4.ThelangschemaThe lang tags deal with exposing objects that have been written in adynamic language such as JRuby or Groovy as beans in the Springcontainer.These tags (and the dynamic language support) are comprehensivelycoveredin thechapterentitled 24 .Pleasedoconsult thatchapter forfulldetailsonthissupportandthelangtagsthemselves.Intheinterestofcompleteness,tousethetagsinthelangschema,youneed to have the following preamble at the top of your Spring XMLconfigurationfile;theemboldenedtextinthefollowingsnippetreferencesthecorrectschemasothatthetagsinthelangnamespaceareavailabletoyou.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:lang="http://www.springframework.org/schema/lang"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd"

<!--<bean/>definitionshere-->

</beans>

A.2.5.ThejmsschemaThejms tagsdealwithconfiguringJMS-relatedbeanssuchasSpring'sMessageListenerContainers.These tags are detailed in the section of the JMSchapterentitled19.6“JMS” .Pleasedoconsultthatchapterforfulldetailsonthissupportandthejmstagsthemselves.In the interestofcompleteness, touse the tags in thejmsschema, youneed to have the following preamble at the top of your Spring XMLconfigurationfile;theemboldenedtextinthefollowingsnippetreferencesthecorrectschemasothatthetagsinthejmsnamespaceareavailabletoyou.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:jms="http://www.springframework.org/schema/jms"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/jmshttp://www.springframework.org/schema/jms/spring-jms-2.5.xsd"

<!--<bean/>definitionshere-->

</beans>

A.2.6.Thetx(transaction)schemaThe tx tags deal with configuring all of those beans in Spring'scomprehensive support for transactions.These tagsare covered in thechapterentitled9 .

You are strongly encouraged to look at the 'spring-tx-2.5.xsd'filethatshipswiththeSpringdistribution.Thisfileis(of course), the XML Schema for Spring's transactionconfiguration, and covers all of the various tags in the txnamespace,includingattributedefaultsandsuchlike.Thisfileisdocumentedinline,andthustheinformationisnotrepeatedhere in the interests of adhering to the DRY (Don't Repeat

Yourself)principle.In the interest of completeness, to use the tags in thetx schema, youneed to have the following preamble at the top of your Spring XMLconfigurationfile;theemboldenedtextinthefollowingsnippetreferencesthecorrectschemasothatthetagsinthetxnamespaceareavailabletoyou.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop"

xmlns:tx="http://www.springframework.org/schema/tx"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<!--<bean/>definitionshere-->

</beans>

Oftenwhenusingthetags inthetxnamespaceyouwillalsobe using the tags from the aop namespace (since thedeclarativetransactionsupportinSpringisimplementedusingAOP). The above XML snippet contains the relevant linesneededtoreferencetheaopschemasothatthetagsintheaopnamespaceareavailabletoyou.

A.2.7.TheaopschemaTheaoptagsdealwithconfiguringallthingsAOPinSpring:thisincludesSpring'sownproxy-basedAOP frameworkandSpring's integrationwiththeAspectJAOPframework.Thesetagsarecomprehensivelycoveredinthechapterentitled6 SpringAOP .In the interestofcompleteness, touse the tags in theaopschema, youneed to have the following preamble at the top of your Spring XMLconfigurationfile;theemboldenedtextinthefollowingsnippetreferences

thecorrectschemasothatthetagsintheaopnamespaceareavailabletoyou.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="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/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd"

<!--<bean/>definitionshere-->

</beans>

A.2.8.ThecontextschemaThecontexttagsdealwithApplicationContextconfigurationthatrelatestoplumbing-thatis,notusuallybeansthatareimportanttoanend-userbut rather beans that do a lot of grunt work in Spring, such asBeanfactoryPostProcessors.Thefollowingsnippetreferencesthecorrectschemasothatthetagsinthecontextnamespaceareavailabletoyou.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:context="http://www.springframework.org/schema/context"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd"

<!--<bean/>definitionshere-->

</beans>

ThecontextschemawasonlyintroducedinSpring2.5.

A.2.8.1.<property-placeholder/>

Thiselementactivatesthereplacementof${...}placeholders,resolvedagainst the specified properties file (as a Spring resource location). Thiselement is a convenience mechanism that sets up aPropertyPlaceholderConfigurer foryou; ifyouneedmorecontrolover thePropertyPlaceholderConfigurer,justdefineoneyourselfexplicitly.

A.2.8.2.<annotation-config/>ActivatestheSpringinfrastructureforvariousannotationstobedetectedinbeanclasses:Spring's@Requiredand@Autowired,aswellasJSR250's@PostConstruct, @PreDestroy and @Resource (if available), and JPA's@PersistenceContext and @PersistenceUnit (if available). Alternatively,you can choose to activate the individual BeanPostProcessors for thoseannotationsexplictly.

This element does not activate processing of Spring's@Transactional annotation. Use the <tx:annotation-driven/>

elementforthatpurpose.

A.2.8.3.<component-scan/>Thiselementisdetailedinthesectionentitled3.11“Annotation-based” .

A.2.8.4.<load-time-weaver/>Thiselementisdetailedinthesectionentitled6.8.4“SpringAspectJLTW” .

A.2.8.5.<spring-configured/>Thiselementisdetailedinthesectionentitled6.8.1“SpringAspectJdomainobject” .

A.2.8.6.<mbean-export/>This element is detailed in the section entitled 20.4.3 “ <context:mbean-

export/>” .

A.2.9.ThetoolschemaThetooltagsareforusewhenyouwanttoaddtooling-specificmetadata

to your custom configuration elements. This metadata can then beconsumed by tools that are aware of thismetadata, and the tools canthendoprettymuchwhatevertheywantwithit(validation,etc.).Thetool tagsarenotdocumented in thisreleaseofSpringas theyarecurrentlyundergoingreview.Ifyouareathirdpartytoolvendorandyouwould like to contribute to this reviewprocess, thendomail theSpringmailing list. The currently supported tool tags can be found in the file'spring-tool-2.5.xsd' in the'src/org/springframework/beans/factory/xml' directory of the Springsourcedistribution.

A.2.10.ThebeansschemaLastbutnotleastwehavethetagsinthebeansschema.Theseare thesame tags that have been in Spring since the very dawn of theframework. Examples of the various tags in the beans schema are notshown here because they are quite comprehensively covered in thesectionentitled3.3.2“” (andindeedinthatentirechapter).Onethingthat isnewtothebeanstagsthemselvesinSpring2.0istheideaofarbitrarybeanmetadata. InSpring2.0 it isnowpossible toaddzero or more key / value pairs to <bean/> XML definitions. What, ifanything, is done with this extra metadata is totally up to your owncustomlogic(andso is typicallyonlyofuse ifyouarewritingyourowncustomtagsasdescribedintheappendixentitledB,ExtensibleXMLauthoring).Findbelowanexampleofthe<meta/>taginthecontextofasurrounding<bean/>(pleasenotethatwithoutanylogictointerpretitthemetadataiseffectivelyuselessas-is).

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<beanid="foo"class="x.y.Foo">

<metakey="cacheName"value="foo"/>

<propertyname="name"value="Rick"/>

</bean>

</beans>

Inthecaseoftheaboveexample,youwouldassumethatthereissomelogic that will consume the bean definition and set up some cachinginfrastructureusingthesuppliedmetadata.

A.3.SettingupyourIDEThisfinalsectiondocumentsthestepsinvolvedinsettingupanumberofpopularJavaIDEstoeffect theeasiereditingofSpring'sXMLSchema-based configuration files. If your favourite Java IDE or editor is notincludedinthelistofdocumentedIDEs, thenpleasedo raisean issueandan example with your favorite IDE/editormay be included in the nextrelease.

A.3.1.SettingupEclipseThe following steps illustrate setting up Eclipse to be XSD-aware. Theassumption in the following steps is that you already have an Eclipseprojectopen(eitherabrandnewprojectoranalreadyexistingone).

ThefollowingstepswerecreatedusingEclipse3.2.Thesetupwill probably be the same (or similar) on an earlier or laterversionofEclipse.StepOneCreateanewXMLfile.Youcannamethisfilewhateveryouwant.Intheexamplebelow,thefileisnamed'context.xml'.Copyandpastethefollowingtextintothefilesothatitmatchesthescreenshot.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:util="http://www.springframework.org/schema/util"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-2.5.xsd">

</beans>

Contributingdocumentation...Patches showing how toconfigure an Eclipse XMLeditor are welcomed. Anysuch contributions are bestsubmitted as patches via theSpringFrameworkJIRAIssueTrackerandmay be featuredinthenextrelease.

StepTwoAs can be seen in the above screenshot (unless you have acustomisedversionofEclipsewith thecorrectplugins) theXMLfilewillbetreatedasplain text.There isnoXMLeditingsupportoutofthe box in Eclipse, and as such there is not even any syntaxhighlightingofelementsandattributes.Toaddressthis,youwillhavetoinstallanXMLeditorpluginforEclipse...

A.1.EclipseXMLeditors

XMLEditor LinkTheEclipseWebToolsPlatform(WTP) http://www.eclipse.org/webtools/

AlistofEclipseXMLplugins http://eclipse-plugins.2y.net/eclipse/plugins.jsp?category=XML

Unfortunately, precisely becausethere is no standard XML editor forEclipse,thereare(bartheonebelow)no further stepsshowingyouhow toconfigure XML Schema support inEclipse... each XML editor pluginwould require itsveryowndedicatedsection, and this isSpring referencedocumentation, not Eclipse XML

editordocumentation.Youwillhavetoread the documentation that comeswith your XML editor plugin (good luck there) and figure it out foryourself.SpringIDEThere is a dedicated Spring Framework plugin for Eclipse calledSpring IDE and it isprettydarn cool. (There'sa consideredandnon-biasedopinionforyou!)ThispluginmakesusingSpringeveneasier,and ithasmore than just support for thecoreSpringFramework...SpringWebFlow is supported too. Details of how to install SpringIDEcanbefoundontheSpringIDEinstallationpage.

WebToolsPlatform(WTP)forEclipseIfyouareusingtheWebToolsPlatform(WTP)forEclipse,youdon'tneedtodoanythingotherthanopenaSpringXMLconfigurationfileusing the WTP platform's XML editor. As can be seen in thescreenshotbelow,youimmediatelygetsomeslickIDE-levelsupportforautocompletingtagsandsuchlike.

A.3.2.SettingupIntelliJIDEAThe following steps illustrate setting up the IntelliJ IDEA IDE to be XSD-aware.TheassumptioninthefollowingstepsisthatyoualreadyhaveanIDEA project open (either a brand new project or an already existingone).RepeatasrequiredforsettingupIDEAtoreferencetheotherSpringXSDfiles.

StepOneCreateanewXMLfile(youcannamethisfilewhateveryouwant).Intheexamplebelow,thefileisnamed'context.xml'.Copyandpastethefollowingtextintothefilesothatitmatchesthescreenshot.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:util="http://www.springframework.org/schema/util"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-2.5.xsd">

</beans>

StepTwoAscanbeseenintheabovescreenshot,theXMLfilehasanumberofnastyredcontextualerrormarkers.Torectifythis,IDEAhastobemadeawareofthelocationofthereferencedXSDnamespace(s).Todothis,simplypositionthecursoroverthesquigglyredarea(seethe screenshot below); then press the Alt-Enter keystrokecombination, and press the Enter key again when the popupbecomesactivetofetchtheexternalresource.

StepThreeIf the external resource could not be fetched (maybe no active

Internet connection is available), you can manually configure theresourcetoreferencea localcopyof theXSDfile.Simplyopenupthe'Settings'dialog (using theCtrl-A-Skeystrokecombinationorviathe'File|Settings'menu),andclickonthe'Resources'button.

StepFourAscanbeseeninthefollowingscreenshot,thiswillbringupadialogthat allows you to add an explicit reference to a local copy of theutilschemafile.(YoucanfindallofthevariousSpringXSDfilesinthe'src'directoryoftheSpringdistribution.)

StepFiveClickingthe'Add'buttonwillbringupanotherdialogthatallowsyouto explicitly to associate a namespace URI with the path to therelevantXSD file.As can be seen in the following screenshot, the'http://www.springframework.org/schema/util'namespaceisbeingassociated with the file resource'C:\bench\spring\src\org\springframework\beans\factory\xml\spring-

util-2.5.xsd'.

StepSixExitingoutofthenesteddialogsbyclickingthe'OK'buttonwill thenbring back the main editing window, and as can be seen in thefollowing screenshot, the contextual error markers havedisappeared; typing the '<' character into the editing window nowalso brings up a handy dropdown box that contains all of theimportedtagsfromtheutilnamespace.

A.3.3.IntegrationissuesThis final section details integration issues that may arise when youswitchovertousingtheaboveXSD-styleforSpring2.0configuration.Thissection isquitesmallat themoment (andhopefully itwillstay thatway).IthasbeenincludedintheSpringdocumentationasaconveniencetoSpringuserssothatifyouencounteranissuewhenswitchingovertotheXSD-styleinsomespecificenvironmentyoucanrefertothissectionfortheauthoritativeanswer.

A.3.3.1.XMLparsingerrorsintheResinv.3applicationserverIf you are using the XSD-style for Spring 2.0 XML configuration anddeployingtov.3ofCaucho'sResinapplicationserver,youwillneedtosetsomeconfigurationoptionspriortostartupsothatanXSD-awareparserisavailabletoSpring.Please do read this resource, http://www.caucho.com/resin-3.0/xml/jaxp.xtp#xerces,forfurtherdetails.

B.ExtensibleXMLauthoring

B.1.IntroductionB.2.AuthoringtheschemaB.3.CodingaNamespaceHandlerB.4.CodingaBeanDefinitionParserB.5.Registeringthehandlerandtheschema

B.5.1.'META-INF/spring.handlers'B.5.2.'META-INF/spring.schemas'

B.6.UsingacustomextensioninyourSpringXMLconfigurationB.7.Meatierexamples

B.7.1.NestingcustomtagswithincustomtagsB.7.2.Customattributeson'normal'elements

B.8.FurtherResources

B.1.IntroductionSinceversion2.0,Springhas featuredamechanism forschema-basedextensionsto the basicSpringXML format for defining and configuringbeans. This section is devoted to detailing how you would go aboutwriting your own custom XML bean definition parsers and integratingsuchparsersintotheSpringIoCcontainer.To facilitate the authoring of configuration files using a schema-awareXMLeditor,Spring's extensibleXML configurationmechanism is basedon XML Schema. If you are not familiar with Spring's current XMLconfigurationextensionsthatcomewiththestandardSpringdistribution,pleasefirstreadtheappendixentitledA,XMLSchema-basedconfiguration.Creating new XML configuration extensions can be done by followingthese(relatively)simplesteps:

AuthoringanXMLschematodescribeyourcustomelement(s).

Coding a custom NamespaceHandler implementation (this is an easystep,don'tworry).Coding one or more BeanDefinitionParser implementations (this iswheretherealworkisdone).RegisteringtheaboveartifactswithSpring(thistooisaneasystep).

Whatfollowsisadescriptionofeachofthesesteps.Fortheexample,wewillcreateanXMLextension(acustomXMLelement) thatallowsus toconfigure objects of the type SimpleDateFormat (from the java.textpackage) in an easy manner. When we are done, we will be able todefinebeandefinitionsoftypeSimpleDateFormatlikethis:

<myns:dateformatid="dateFormat"

pattern="yyyy-MM-ddHH:mm"

lenient="true"/>

(Don'tworryaboutthefact thatthisexample isverysimple;muchmoredetailed examples follow afterwards. The intent in this first simpleexampleistowalkyouthroughthebasicstepsinvolved.)

B.2.AuthoringtheschemaCreating an XML configuration extension for use with Spring's IoCcontainer starts with authoring an XML Schema to describe theextension. What follows is the schema we'll use to configureSimpleDateFormatobjects.

<!--myns.xsd(insidepackageorg/springframework/samples/xml)-->

<?xmlversion="1.0"encoding="UTF-8"?>

<xsd:schemaxmlns="http://www.mycompany.com/schema/myns"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:beans="http://www.springframework.org/schema/beans"

targetNamespace="http://www.mycompany.com/schema/myns"

elementFormDefault="qualified"

attributeFormDefault="unqualified">

<xsd:importnamespace="http://www.springframework.org/schema/beans"/>

<xsd:elementname="dateformat">

<xsd:complexType>

<xsd:complexContent>

<xsd:extensionbase="beans:identifiedType">

<xsd:attributename="lenient"type="xsd:boolean"/>

<xsd:attributename="pattern"type="xsd:string"use="required"/>

</xsd:extension>

</xsd:complexContent>

</xsd:complexType>

</xsd:element>

</xsd:schema>

(Theemphasizedlinecontainsanextensionbaseforalltagsthatwillbeidentifiable (meaning theyhaveanidattribute thatwill be used as thebeanidentifierinthecontainer).WeareabletousethisattributebecauseweimportedtheSpring-provided'beans'namespace.)Theabove schemawill be used to configureSimpleDateFormat objects,directly inanXMLapplication context fileusing the<myns:dateformat/>element.

<myns:dateformatid="dateFormat"

pattern="yyyy-MM-ddHH:mm"

lenient="true"/>

Note that after we've created the infrastructure classes, the abovesnippetofXMLwillessentiallybeexactlythesameasthefollowingXMLsnippet. In other words, we're just creating a bean in the container,identified by the name 'dateFormat' of type SimpleDateFormat, with acoupleofpropertiesset.

<beanid="dateFormat"class="java.text.SimpleDateFormat">

<constructor-argvalue="yyyy-HH-ddHH:mm"/>

<propertyname="lenient"value="true"/>

</bean>

Theschema-basedapproach tocreatingconfiguration formatallows for tight integration with an IDE that has a schema-awareXMLeditor.Usingaproperlyauthoredschema,youcanuse autocompletion to have a user choose between severalconfigurationoptionsdefinedintheenumeration.

B.3.CodingaNamespaceHandlerInadditiontotheschema,weneedaNamespaceHandlerthatwillparseallelements of this specific namespace Spring encounters while parsingconfigurationfiles.TheNamespaceHandlershouldinourcasetakecareoftheparsingofthemyns:dateformatelement.The NamespaceHandler interface is pretty simple in that it features justthreemethods:

init() - allows for initializationof theNamespaceHandler andwill becalledbySpringbeforethehandlerisusedBeanDefinitionparse(Element,ParserContext)-calledwhenSpringencountersa top-levelelement (notnested insideabeandefinitionoradifferentnamespace).Thismethodcanregisterbeandefinitionsitselfand/orreturnabeandefinition.BeanDefinitionHolder decorate(Node, BeanDefinitionHolder,

ParserContext) - called when Spring encounters an attribute ornestedelementofadifferentnamespace.Thedecorationofoneormorebeandefinitionsisusedforexamplewiththeout-of-the-boxscopesSpring2.0supports.We'llstartbyhighlightingasimpleexample,withoutusingdecoration,afterwhichwewillshowdecorationinasomewhatmoreadvancedexample.

Although it is perfectly possible to code your own NamespaceHandler forthe entire namespace (and hence provide code that parses each andeveryelementinthenamespace),itisoftenthecasethateachtop-levelXMLelement inaSpringXMLconfigurationfileresults inasinglebeandefinition (as in our case, where a single <myns:dateformat/> elementresults in a single SimpleDateFormat bean definition). Spring features anumber of convenience classes that support this scenario. In thisexample,we'llmakeusetheNamespaceHandlerSupportclass:

packageorg.springframework.samples.xml;

importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;

publicclassMyNamespaceHandlerextendsNamespaceHandlerSupport{

publicvoidinit(){

registerBeanDefinitionParser("dateformat",newSimpleDateFormatBeanDefinitionParser());

}

}

The observant readerwill notice that there isn't actually awhole lot ofparsing logic in this class. Indeed... the NamespaceHandlerSupport classhas a built in notion of delegation. It supports the registration of anynumber of BeanDefinitionParser instances, to which it will delegate towhen it needs to parse an element in it's namespace. This cleanseparation of concerns allows a NamespaceHandler to handle theorchestration of the parsing of all of the custom elements in it'snamespace,while delegating to BeanDefinitionParsers to do the gruntworkoftheXMLparsing;thismeansthateachBeanDefinitionParserwillcontainjustthelogicforparsingasinglecustomelement,aswecanseeinthenextstep

B.4.CodingaBeanDefinitionParserABeanDefinitionParserwillbeused if theNamespaceHandler encountersanXMLelementof thetypethathasbeenmappedtothespecificbeandefinitionparser(whichis'dateformat'inthiscase).Inotherwords,theBeanDefinitionParser is responsible for parsing one distinct top-levelXMLelementdefinedintheschema.Intheparser,we'llhaveaccesstotheXMLelement (and thus it's subelements too) so thatwe canparseourcustomXMLcontent,ascanbeseeninthefollowingexample:

packageorg.springframework.samples.xml;

importorg.springframework.beans.factory.support.BeanDefinitionBuilder;

importorg.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;

importorg.springframework.util.StringUtils;

importorg.w3c.dom.Element;

importjava.text.SimpleDateFormat;

publicclassSimpleDateFormatBeanDefinitionParserextendsAbstractSingleBeanDefinitionParser{

protectedClassgetBeanClass(Elementelement){

returnSimpleDateFormat.class;

}

protectedvoiddoParse(Elementelement,BeanDefinitionBuilderbean){

//thiswillneverbenullsincetheschemaexplicitlyrequiresthatavaluebesupplied

Stringpattern=element.getAttribute("pattern");

bean.addConstructorArg(pattern);

//thishoweverisanoptionalproperty

Stringlenient=element.getAttribute("lenient");

if(StringUtils.hasText(lenient)){

bean.addPropertyValue("lenient",Boolean.valueOf(lenient));

}

}

}

WeusetheSpring-provided

AbstractSingleBeanDefinitionParsertohandlealotofthebasicgruntworkofcreatingasingleBeanDefinition.

WesupplytheAbstractSingleBeanDefinitionParsersuperclasswiththetypethatoursingleBeanDefinitionwillrepresent.

In this simple case, this is all that we need to do. The creation of oursingle BeanDefinition is handled by theAbstractSingleBeanDefinitionParsersuperclass,asistheextractionandsettingofthebeandefinition'suniqueidentifier.

B.5.RegisteringthehandlerandtheschemaThecodingisfinished!AllthatremainstobedoneistosomehowmaketheSpringXMLparsing infrastructureawareofourcustomelement;wedothisbyregisteringourcustomnamespaceHandlerandcustomXSDfilein two special purpose properties files. These properties files are bothplaced in a 'META-INF' directory in your application, and can, forexample,bedistributedalongsideyourbinaryclassesinaJARfile.TheSpring XML parsing infrastructurewill automatically pick up your newextension by consuming these special properties files, the formats ofwhicharedetailedbelow.

B.5.1.'META-INF/spring.handlers'Thepropertiesfilecalled'spring.handlers'containsamappingofXMLSchemaURIs to namespace handler classes. So for our example, weneedtowritethefollowing:

http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler

(The':'characterisavaliddelimiterintheJavapropertiesformat,andsothe':'characterintheURIneedstobeescapedwithabackslash.)The firstpart (thekey)of thekey-valuepair is theURIassociatedwithyourcustomnamespaceextension,andneedstomatchexactlythevalueof the 'targetNamespace' attribute as specified in your custom XSDschema.

B.5.2.'META-INF/spring.schemas'Theproperties file called'spring.schemas' containsamappingof XMLSchemalocations(referredtoalongwiththeschemadeclarationinXMLfilesthatusetheschemaaspartofthe'xsi:schemaLocation'attribute)toclasspathresources.ThisfileisneededtopreventSpringfromabsolutelyhaving to useadefaultEntityResolver that requires Internet access toretrievetheschemafile.Ifyouspecifythemappinginthispropertiesfile,Spring will search for the schema on the classpath (in this case'myns.xsd'inthe'org.springframework.samples.xml'package):

http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd

TheupshotofthisisthatyouareencouragedtodeployyourXSDfile(s)right alongside the NamespaceHandler and BeanDefinitionParser classesontheclasspath.

B.6. Using a custom extension in your Spring XMLconfigurationUsing a custom extension that you yourself have implemented is nodifferent fromusingoneof the 'custom'extensions thatSpringprovidesstraight out of the box. Find below an example of using the custom<dateformat/>elementdevelopedinthepreviousstepsinaSpringXMLconfigurationfile.

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:myns="http://www.mycompany.com/schema/myns"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.mycompany.com/schema/mynshttp://www.mycompany.com/schema/myns/myns.xsd">

<!--asatop-levelbean-->

<myns:dateformatid="defaultDateFormat"pattern="yyyy-MM-ddHH:mm"lenient="true"/>

<beanid="jobDetailTemplate"abstract="true">

<propertyname="dateFormat">

<!--asaninnerbean-->

<myns:dateformatpattern="HH:mmMM-dd-yyyy"/>

</property>

</bean>

</beans>

B.7.MeatierexamplesFindbelowsomemuchmeatierexamplesofcustomXMLextensions.

B.7.1.NestingcustomtagswithincustomtagsThis example illustrates how you might go about writing the variousartifactsrequiredtosatisfyatargetofthefollowingconfiguration:

<?xmlversion="1.0"encoding="UTF-8"?>

<beansxmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:foo="http://www.foo.com/schema/component"

xsi:schemaLocation="

http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd

http://www.foo.com/schema/componenthttp://www.foo.com/schema/component/component.xsd">

<foo:componentid="bionic-family"name="Bionic-1">

<foo:componentname="Sport-1"/>

<foo:componentname="Rock-1"/>

</foo:component>

</beans>

The above configuration actually nests custom extensions within eachother. The class that is actually configured by the above<foo:component/>elementistheComponentclass(showndirectlybelow).NoticehowtheComponentclassdoesnotexposeasettermethodforthe'components' property; this makes it hard (or rather impossible) toconfigureabeandefinitionfortheComponentclassusingsetterinjection.

packagecom.foo;

importjava.util.ArrayList;

importjava.util.List;

publicclassComponent{

privateStringname;

privateListcomponents=newArrayList();

//mmm,thereisnosettermethodforthe'components'

publicvoidaddComponent(Componentcomponent){

this.components.add(component);

}

publicListgetComponents(){

returncomponents;

}

publicStringgetName(){

returnname;

}

publicvoidsetName(Stringname){

this.name=name;

}

}

The typicalsolution to this issue is tocreateacustomFactoryBean thatexposesasetterpropertyforthe'components'property.

packagecom.foo;

importorg.springframework.beans.factory.FactoryBean;

importjava.util.Iterator;

importjava.util.List;

publicclassComponentFactoryBeanimplementsFactoryBean{

privateComponentparent;

privateListchildren;

publicvoidsetParent(Componentparent){

this.parent=parent;

}

publicvoidsetChildren(Listchildren){

this.children=children;

}

publicObjectgetObject()throwsException{

if(this.children!=null&&this.children.size()>0){

for(Iteratorit=children.iterator();it.hasNext();){

ComponentchildComponent=(Component)it.next();

this.parent.addComponent(childComponent);

}

}

returnthis.parent;

}

publicClassgetObjectType(){

returnComponent.class;

}

publicbooleanisSingleton(){

returntrue;

}

}

This is all verywell, anddoesworknicely, but exposesa lot ofSpringplumbing to the end user.What we are going to do is write a customextension that hides awayall of thisSpring plumbing. Ifwe stick to thestepsdescribedpreviously,we'llstartoffbycreatingtheXSDschematodefinethestructureofourcustomtag.

<?xmlversion="1.0"encoding="UTF-8"standalone="no"?>

<xsd:schemaxmlns="http://www.foo.com/schema/component"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://www.foo.com/schema/component"

elementFormDefault="qualified"

attributeFormDefault="unqualified">

<xsd:elementname="component">

<xsd:complexType>

<xsd:choiceminOccurs="0"maxOccurs="unbounded">

<xsd:elementref="component"/>

</xsd:choice>

<xsd:attributename="id"type="xsd:ID"/>

<xsd:attributename="name"use="required"type="xsd:string"/>

</xsd:complexType>

</xsd:element>

</xsd:schema>

We'llthencreateacustomNamespaceHandler.

packagecom.foo;

importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;

publicclassComponentNamespaceHandlerextendsNamespaceHandlerSupport{

publicvoidinit(){

registerBeanDefinitionParser("component",newComponentBeanDefinitionParser());

}

}

Next up is the custom BeanDefinitionParser. Remember that what wearecreatingisaBeanDefinitiondescribingaComponentFactoryBean.

packagecom.foo;

importorg.springframework.beans.factory.support.AbstractBeanDefinition;

importorg.springframework.beans.factory.support.BeanDefinitionBuilder;

importorg.springframework.beans.factory.support.ManagedList;

importorg.springframework.beans.factory.xml.AbstractBeanDefinitionParser;

importorg.springframework.beans.factory.xml.ParserContext;

importorg.springframework.util.xml.DomUtils;

importorg.w3c.dom.Element;

importjava.util.List;

publicclassComponentBeanDefinitionParserextendsAbstractBeanDefinitionParser{

protectedAbstractBeanDefinitionparseInternal(Elementelement,ParserContextparserContext){

BeanDefinitionBuilderfactory=BeanDefinitionBuilder.rootBeanDefinition(ComponentFactoryBean.class);

BeanDefinitionBuilderparent=parseComponent(element);

factory.addPropertyValue("parent",parent.getBeanDefinition());

ListchildElements=DomUtils.getChildElementsByTagName(element,"component");

if(childElements!=null&&childElements.size()>0){

parseChildComponents(childElements,factory);

}

returnfactory.getBeanDefinition();

}

privatestaticBeanDefinitionBuilderparseComponent(Elementelement){

BeanDefinitionBuildercomponent=BeanDefinitionBuilder.rootBeanDefinition(Component.class);

component.addPropertyValue("name",element.getAttribute("name"));

returncomponent;

}

privatestaticvoidparseChildComponents(ListchildElements,BeanDefinitionBuilderfactory){

ManagedListchildren=newManagedList(childElements.size());

for(inti=0;i<childElements.size();++i){

ElementchildElement=(Element)childElements.get(i);

BeanDefinitionBuilderchild=parseComponent(childElement);

children.add(child.getBeanDefinition());

}

factory.addPropertyValue("children",children);

}

}

Lastly, the various artifacts need to be registeredwith the Spring XMLinfrastructure.

#in'META-INF/spring.handlers'

http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler

#in'META-INF/spring.schemas'

http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd

B.7.2.Customattributeson'normal'elementsWriting your own customparser and the associated artifacts isn't hard,butsometimesitisnottherightthingtodo.Considerthescenariowhereyou need to addmetadata to already existing bean definitions. In thiscaseyoucertainlydon'twanttohavetogooffandwriteyourownentirecustomextension; rather you justwant toaddanadditionalattribute totheexistingbeandefinitionelement.Bywayofanotherexample, let'ssaythattheserviceclassthatyouaredefiningabeandefinitionforaserviceobjectthatwill(unknowntoit)be

accessing a clustered JCache, and you want to ensure that the namedJCacheinstanceiseagerlystartedwithinthesurroundingcluster:

<beanid="checkingAccountService"class="com.foo.DefaultCheckingAccountService"

jcache:cache-name="checking.account">

<!--otherdependencieshere...-->

</bean>

WhatwearegoingtodohereiscreateanotherBeanDefinitionwhenthe'jcache:cache-name' attribute is parsed; this BeanDefinition will theninitialize the named JCache for us. We will also modify the existingBeanDefinition for the 'checkingAccountService' so that it will have adependencyonthisnewJCache-initializingBeanDefinition.

packagecom.foo;

publicclassJCacheInitializer{

privateStringname;

publicJCacheInitializer(Stringname){

this.name=name;

}

publicvoidinitialize(){

//lotsofJCacheAPIcallstoinitializethenamedcache...

}

}

Nowontothecustomextension.Firstly,theauthoringoftheXSDschemadescribingthecustomattribute(quiteeasyinthiscase).

<?xmlversion="1.0"encoding="UTF-8"standalone="no"?>

<xsd:schemaxmlns="http://www.foo.com/schema/jcache"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://www.foo.com/schema/jcache"

elementFormDefault="qualified">

<xsd:attributename="cache-name"type="xsd:string"/>

</xsd:schema>

Next,theassociatedNamespaceHandler.

packagecom.foo;

importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;

publicclassJCacheNamespaceHandlerextendsNamespaceHandlerSupport{

publicvoidinit(){

super.registerBeanDefinitionDecoratorForAttribute("cache-name",

newJCacheInitializingBeanDefinitionDecorator());

}

}

Next, the parser. Note that in this case, because we are going to beparsinganXMLattribute,wewriteaBeanDefinitionDecoratorratherthanaBeanDefinitionParser.

packagecom.foo;

importorg.springframework.beans.factory.config.BeanDefinitionHolder;

importorg.springframework.beans.factory.support.AbstractBeanDefinition;

importorg.springframework.beans.factory.support.BeanDefinitionBuilder;

importorg.springframework.beans.factory.xml.BeanDefinitionDecorator;

importorg.springframework.beans.factory.xml.ParserContext;

importorg.w3c.dom.Attr;

importorg.w3c.dom.Node;

importjava.util.ArrayList;

importjava.util.Arrays;

importjava.util.List;

publicclassJCacheInitializingBeanDefinitionDecoratorimplementsBeanDefinitionDecorator{

privatestaticfinalString[]EMPTY_STRING_ARRAY=newString[0];

publicBeanDefinitionHolderdecorate(

Nodesource,BeanDefinitionHolderholder,ParserContextctx){

StringinitializerBeanName=registerJCacheInitializer(source,ctx);

createDependencyOnJCacheInitializer(holder,initializerBeanName);

returnholder;

}

privatevoidcreateDependencyOnJCacheInitializer(BeanDefinitionHolderholder,StringinitializerBeanName){

AbstractBeanDefinitiondefinition=((AbstractBeanDefinition)holder.getBeanDefinition());

String[]dependsOn=definition.getDependsOn();

if(dependsOn==null){

dependsOn=newString[]{initializerBeanName};

}else{

Listdependencies=newArrayList(Arrays.asList(dependsOn));

dependencies.add(initializerBeanName);

dependsOn=(String[])dependencies.toArray(EMPTY_STRING_ARRAY);

}

definition.setDependsOn(dependsOn);

}

privateStringregisterJCacheInitializer(Nodesource,ParserContextctx){

StringcacheName=((Attr)source).getValue();

StringbeanName=cacheName+"-initializer";

if(!ctx.getRegistry().containsBeanDefinition(beanName)){

BeanDefinitionBuilderinitializer=BeanDefinitionBuilder.rootBeanDefinition(JCacheInitializer.class);

initializer.addConstructorArg(cacheName);

ctx.getRegistry().registerBeanDefinition(beanName,initializer.getBeanDefinition());

}

returnbeanName;

}

}

Lastly, the various artifacts need to be registeredwith the Spring XMLinfrastructure.

#in'META-INF/spring.handlers'

http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler

#in'META-INF/spring.schemas'

http\://www.foo.com/schema/jcache/jcache.xsd=com/foo/jcache.xsd

B.8.FurtherResourcesFindbelow links to further resources concerningXMLSchemaand theextensibleXMLsupportdescribedinthischapter.

TheXMLSchemaPart1:StructuresSecondEdition

TheXMLSchemaPart2:DatatypesSecondEdition

C.spring-beans-2.0.dtd

<!--

SpringXMLBeansDTD,version2.0

Authors:RodJohnson,JuergenHoeller,AlefArendsen,ColinSampaleanu,RobHarrop

Thisdefinesasimpleandconsistentwayofcreatinganamespace

ofJavaBeansobjects,managedbyaSpringBeanFactory,readby

XmlBeanDefinitionReader(withDefaultBeanDefinitionDocumentReader).

ThisdocumenttypeisusedbymostSpringfunctionality,including

webapplicationcontexts,whicharebasedonbeanfactories.

Each"bean"elementinthisdocumentdefinesaJavaBean.

Typicallythebeanclassisspecified,alongwithJavaBeanproperties

and/orconstructorarguments.

Abeaninstancecanbea"singleton"(sharedinstance)ora"prototype"

(independentinstance).Furtherscopescanbeprovidedbyextended

beanfactories,forexampleinawebenvironment.

Referencesamongbeansaresupported,thatis,settingaJavaBeanproperty

oraconstructorargumenttorefertoanotherbeaninthesamefactory

(oranancestorfactory).

Asalternativetobeanreferences,"innerbeandefinitions"canbeused.

Singletonflagsofsuchinnerbeandefinitionsareeffectivelyignored:

Innerbeansaretypicallyanonymousprototypes.

Thereisalsosupportforlists,sets,maps,andjava.util.Properties

asbeanpropertytypesorconstructorargumenttypes.

Forsimplepurposes,thisDTDissufficient.AsofSpring2.0,

XSD-basedbeandefinitionsaresupportedasmorepowerfulalternative.

XMLdocumentsthatconformtothisDTDshoulddeclarethefollowingdoctype:

<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"

"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

-->

<!--

Thedocumentroot.Adocumentcancontainbeandefinitionsonly,

importsonly,oramixtureofboth(typicallywithimportsfirst).

-->

<!ELEMENTbeans(

description?,

(import|alias|bean)*

)>

<!--

Defaultvaluesforallbeandefinitions.Canbeoverriddenat

the"bean"level.Seethoseattributedefinitionsfordetails.

-->

<!ATTLISTbeansdefault-lazy-init(true|false)"false">

<!ATTLISTbeansdefault-autowire(no|byName|byType|constructor|autodetect)"no">

<!ATTLISTbeansdefault-dependency-check(none|objects|simple|all)"none">

<!ATTLISTbeansdefault-init-methodCDATA#IMPLIED>

<!ATTLISTbeansdefault-destroy-methodCDATA#IMPLIED>

<!ATTLISTbeansdefault-merge(true|false)"false">

<!--

Elementcontaininginformativetextdescribingthepurposeoftheenclosing

element.Alwaysoptional.

UsedprimarilyforuserdocumentationofXMLbeandefinitiondocuments.

-->

<!ELEMENTdescription(#PCDATA)>

<!--

SpecifiesanXMLbeandefinitionresourcetoimport.

-->

<!ELEMENTimportEMPTY>

<!--

TherelativeresourcelocationoftheXMLbeandefinitionfiletoimport,

forexample"myImport.xml"or"includes/myImport.xml"or"../myImport.xml".

-->

<!ATTLISTimportresourceCDATA#REQUIRED>

<!--

Definesanaliasforabean,whichcanresideinadifferentdefinitionfile.

-->

<!ELEMENTaliasEMPTY>

<!--

Thenameofthebeantodefineanaliasfor.

-->

<!ATTLISTaliasnameCDATA#REQUIRED>

<!--

Thealiasnametodefineforthebean.

-->

<!ATTLISTaliasaliasCDATA#REQUIRED>

<!--

Allowsforarbitrarymetadatatobeattachedtoabeandefinition.

-->

<!ELEMENTmetaEMPTY>

<!--

Specifiesthekeynameofthemetadataparameterbeingdefined.

-->

<!ATTLISTmetakeyCDATA#REQUIRED>

<!--

SpecifiesthevalueofthemetadataparameterbeingdefinedasaString.

-->

<!ATTLISTmetavalueCDATA#REQUIRED>

<!--

Definesasingle(usuallynamed)bean.

Abeandefinitionmaycontainnestedtagsforconstructorarguments,

propertyvalues,lookupmethods,andreplacedmethods.Mixingconstructor

injectionandsetterinjectiononthesamebeanisexplicitlysupported.

-->

<!ELEMENTbean(

description?,

(meta|constructor-arg|property|lookup-method|replaced-method)*

)>

<!--

Beanscanbeidentifiedbyanid,toenablereferencechecking.

ThereareconstraintsonavalidXMLid:ifyouwanttoreferenceyourbean

inJavacodeusinganamethat'sillegalasanXMLid,usetheoptional

"name"attribute.Ifneitherisgiven,thebeanclassnameisusedasid

(withanappendedcounterlike"#2"ifthereisalreadyabeanwiththatname).

-->

<!ATTLISTbeanidID#IMPLIED>

<!--

Optional.Canbeusedtocreateoneormorealiasesillegalinanid.

Multiplealiasescanbeseparatedbyanynumberofspaces,commas,or

semi-colons(orindeedanymixtureofthethree).

-->

<!ATTLISTbeannameCDATA#IMPLIED>

<!--

Eachbeandefinitionmustspecifythefullyqualifiednameoftheclass,

exceptifitpureservesasparentforchildbeandefinitions.

-->

<!ATTLISTbeanclassCDATA#IMPLIED>

<!--

Optionallyspecifyaparentbeandefinition.

Willusethebeanclassoftheparentifnonespecified,butcan

alsooverrideit.Inthelattercase,thechildbeanclassmustbe

compatiblewiththeparent,i.e.accepttheparent'spropertyvalues

andconstructorargumentvalues,ifany.

Achildbeandefinitionwillinheritconstructorargumentvalues,

propertyvaluesandmethodoverridesfromtheparent,withtheoption

toaddnewvalues.Ifinitmethod,destroymethod,factorybeanand/orfactory

methodarespecified,theywilloverridethecorrespondingparentsettings.

Theremainingsettingswillalwaysbetakenfromthechilddefinition:

dependson,autowiremode,dependencycheck,scope,lazyinit.

-->

<!ATTLISTbeanparentCDATA#IMPLIED>

<!--

Thescopeofthisbean:typically"singleton"(onesharedinstance,

whichwillbereturnedbyallcallstogetBean()withtheid),

or"prototype"(independentinstanceresultingfromeachcallto

getBean().Defaultis"singleton".

Singletonsaremostcommonlyused,andareidealformulti-threaded

serviceobjects.Furtherscopes,suchas"request"or"session",

mightbesupportedbyextendedbeanfactories(forexample,ina

webenvironment).

Note:Thisattributewillnotbeinheritedbychildbeandefinitions.

Hence,itneedstobespecifiedperconcretebeandefinition.

Innerbeandefinitionsinheritthesingletonstatusoftheircontaining

beandefinition,unlessexplicitlyspecified:Theinnerbeanwillbea

singletonifthecontainingbeanisasingleton,andaprototypeif

thecontainingbeanhasanyotherscope.

-->

<!ATTLISTbeanscopeCDATA#IMPLIED>

<!--

Isthisbean"abstract",i.e.notmeanttobeinstantiateditselfbut

ratherjustservingasparentforconcretechildbeandefinitions.

Defaultis"false".Specify"true"totellthebeanfactorytonottryto

instantiatethatparticularbeaninanycase.

Note:Thisattributewillnotbeinheritedbychildbeandefinitions.

Hence,itneedstobespecifiedperabstractbeandefinition.

-->

<!ATTLISTbeanabstract(true|false)#IMPLIED>

<!--

Ifthisbeanshouldbelazilyinitialized.

Iffalse,itwillgetinstantiatedonstartupbybeanfactories

thatperformeagerinitializationofsingletons.

Note:Thisattributewillnotbeinheritedbychildbeandefinitions.

Hence,itneedstobespecifiedperconcretebeandefinition.

-->

<!ATTLISTbeanlazy-init(true|false|default)"default">

<!--

Indicateswhetherornotthisbeanshouldbeconsideredwhenlooking

forcandidatestosatisfyanotherbeansautowiringrequirements.

-->

<!ATTLISTbeanautowire-candidate(true|false)#IMPLIED>

<!--

Optionalattributecontrollingwhetherto"autowire"beanproperties.

Thisisanautomagicalprocessinwhichbeanreferencesdon'tneedtobecoded

explicitlyintheXMLbeandefinitionfile,butSpringworksoutdependencies.

Thereare5modes:

1."no"

ThetraditionalSpringdefault.Noautomagicalwiring.Beanreferences

mustbedefinedintheXMLfileviathe<ref>element.Werecommendthis

inmostcasesasitmakesdocumentationmoreexplicit.

2."byName"

Autowiringbypropertyname.IfabeanofclassCatexposesadogproperty,

Springwilltrytosetthistothevalueofthebean"dog"inthecurrentfactory.

Ifthereisnomatchingbeanbyname,nothingspecialhappens;

usedependency-check="objects"toraiseanerrorinthatcase.

3."byType"

Autowiringifthereisexactlyonebeanofthepropertytypeinthebeanfactory.

Ifthereismorethanone,afatalerrorisraised,andyoucan'tusebyType

autowiringforthatbean.Ifthereisnone,nothingspecialhappens;

usedependency-check="objects"toraiseanerrorinthatcase.

4."constructor"

Analogousto"byType"forconstructorarguments.Ifthereisn'texactlyonebean

oftheconstructorargumenttypeinthebeanfactory,afatalerrorisraised.

5."autodetect"

Chooses"constructor"or"byType"throughintrospectionofthebeanclass.

Ifadefaultconstructorisfound,"byType"getsapplied.

ThelattertwoaresimilartoPicoContainerandmakebeanfactoriessimpleto

configureforsmallnamespaces,butdoesn'tworkaswellasstandardSpring

behaviourforbiggerapplications.

Notethatexplicitdependencies,i.e."property"and"constructor-arg"elements,

alwaysoverrideautowiring.Autowirebehaviorcanbecombinedwithdependency

checking,whichwillbeperformedafterallautowiringhasbeencompleted.

Note:Thisattributewillnotbeinheritedbychildbeandefinitions.

Hence,itneedstobespecifiedperconcretebeandefinition.

-->

<!ATTLISTbeanautowire(no|byName|byType|constructor|autodetect|default)"default">

<!--

Optionalattributecontrollingwhethertocheckwhetherallthis

beansdependencies,expressedinitsproperties,aresatisfied.

Defaultisnodependencychecking.

"simple"typedependencycheckingincludesprimitivesandString;

"objects"includescollaborators(otherbeansinthefactory);

"all"includesbothtypesofdependencychecking.

Note:Thisattributewillnotbeinheritedbychildbeandefinitions.

Hence,itneedstobespecifiedperconcretebeandefinition.

-->

<!ATTLISTbeandependency-check(none|objects|simple|all|default)"default">

<!--

Thenamesofthebeansthatthisbeandependsonbeinginitialized.

Thebeanfactorywillguaranteethatthesebeansgetinitializedbefore.

Notethatdependenciesarenormallyexpressedthroughbeanpropertiesor

constructorarguments.Thispropertyshouldjustbenecessaryforotherkinds

ofdependencieslikestatics(*ugh*)ordatabasepreparationonstartup.

Note:Thisattributewillnotbeinheritedbychildbeandefinitions.

Hence,itneedstobespecifiedperconcretebeandefinition.

-->

<!ATTLISTbeandepends-onCDATA#IMPLIED>

<!--

Optionalattributeforthenameofthecustominitializationmethod

toinvokeaftersettingbeanproperties.Themethodmusthavenoarguments,

butmaythrowanyexception.

-->

<!ATTLISTbeaninit-methodCDATA#IMPLIED>

<!--

Optionalattributeforthenameofthecustomdestroymethodtoinvoke

onbeanfactoryshutdown.Themethodmusthavenoarguments,

butmaythrowanyexception.

Note:Onlyinvokedonbeanswhoselifecycleisunderfullcontrol

ofthefactory-whichisalwaysthecaseforsingletons,butnot

guaranteedforanyotherscope.

-->

<!ATTLISTbeandestroy-methodCDATA#IMPLIED>

<!--

Optionalattributespecifyingthenameofafactorymethodtouseto

createthisobject.Useconstructor-argelementstospecifyarguments

tothefactorymethod,ifittakesarguments.Autowiringdoesnotapply

tofactorymethods.

Ifthe"class"attributeispresent,thefactorymethodwillbeastatic

methodontheclassspecifiedbythe"class"attributeonthisbean

definition.Oftenthiswillbethesameclassasthatoftheconstructed

object-forexample,whenthefactorymethodisusedasanalternative

toaconstructor.However,itmaybeonadifferentclass.Inthatcase,

thecreatedobjectwill*not*beoftheclassspecifiedinthe"class"

attribute.ThisisanalogoustoFactoryBeanbehavior.

Ifthe"factory-bean"attributeispresent,the"class"attributeisnot

used,andthefactorymethodwillbeaninstancemethodontheobject

returnedfromagetBeancallwiththespecifiedbeanname.Thefactory

beanmaybedefinedasasingletonoraprototype.

Thefactorymethodcanhaveanynumberofarguments.Autowiringisnot

supported.Useindexedconstructor-argelementsinconjunctionwiththe

factory-methodattribute.

SetterInjectioncanbeusedinconjunctionwithafactorymethod.

MethodInjectioncannot,asthefactorymethodreturnsaninstance,

whichwillbeusedwhenthecontainercreatesthebean.

-->

<!ATTLISTbeanfactory-methodCDATA#IMPLIED>

<!--

Alternativetoclassattributeforfactory-methodusage.

Ifthisisspecified,noclassattributeshouldbeused.

Thisshouldbesettothenameofabeaninthecurrentor

ancestorfactoriesthatcontainstherelevantfactorymethod.

ThisallowsthefactoryitselftobeconfiguredusingDependency

Injection,andaninstance(ratherthanstatic)methodtobeused.

-->

<!ATTLISTbeanfactory-beanCDATA#IMPLIED>

<!--

Beandefinitionscanspecifyzeroormoreconstructorarguments.

Thisisanalternativeto"autowireconstructor".

Argumentscorrespondtoeitheraspecificindexoftheconstructorargument

listoraresupposedtobematchedgenericallybytype.

Note:Asinglegenericargumentvaluewilljustbeusedonce,ratherthan

potentiallymatchedmultipletimes(asofSpring1.1).

constructor-argelementsarealsousedinconjunctionwiththefactory-method

elementtoconstructbeansusingstaticorinstancefactorymethods.

-->

<!ELEMENTconstructor-arg(

description?,

(bean|ref|idref|value|null|list|set|map|props)?

)>

<!--

Theconstructor-argtagcanhaveanoptionalindexattribute,

tospecifytheexactindexintheconstructorargumentlist.Onlyneeded

toavoidambiguities,e.g.incaseof2argumentsofthesametype.

-->

<!ATTLISTconstructor-argindexCDATA#IMPLIED>

<!--

Theconstructor-argtagcanhaveanoptionaltypeattribute,

tospecifytheexacttypeoftheconstructorargument.Onlyneeded

toavoidambiguities,e.g.incaseof2singleargumentconstructors

thatcanbothbeconvertedfromaString.

-->

<!ATTLISTconstructor-argtypeCDATA#IMPLIED>

<!--

Ashort-cutalternativetoachildelement"refbean=".

-->

<!ATTLISTconstructor-argrefCDATA#IMPLIED>

<!--

Ashort-cutalternativetoachildelement"value".

-->

<!ATTLISTconstructor-argvalueCDATA#IMPLIED>

<!--

Beandefinitionscanhavezeroormoreproperties.

PropertyelementscorrespondtoJavaBeansettermethodsexposed

bythebeanclasses.Springsupportsprimitives,referencestoother

beansinthesameorrelatedfactories,lists,mapsandproperties.

-->

<!ELEMENTproperty(

description?,meta*,

(bean|ref|idref|value|null|list|set|map|props)?

)>

<!--

ThepropertynameattributeisthenameoftheJavaBeanproperty.

ThisfollowsJavaBeanconventions:anameof"age"wouldcorrespond

tosetAge()/optionalgetAge()methods.

-->

<!ATTLISTpropertynameCDATA#REQUIRED>

<!--

Ashort-cutalternativetoachildelement"refbean=".

-->

<!ATTLISTpropertyrefCDATA#IMPLIED>

<!--

Ashort-cutalternativetoachildelement"value".

-->

<!ATTLISTpropertyvalueCDATA#IMPLIED>

<!--

AlookupmethodcausestheIoCcontainertooverridethegivenmethodandreturn

thebeanwiththenamegiveninthebeanattribute.ThisisaformofMethodInjection.

It'sparticularlyusefulasanalternativetoimplementingtheBeanFactoryAware

interface,inordertobeabletomakegetBean()callsfornon-singletoninstances

atruntime.Inthiscase,MethodInjectionisalessinvasivealternative.

-->

<!ELEMENTlookup-methodEMPTY>

<!--

Nameofalookupmethod.Thismethodshouldtakenoarguments.

-->

<!ATTLISTlookup-methodnameCDATA#IMPLIED>

<!--

Nameofthebeaninthecurrentorancestorfactoriesthatthelookupmethod

shouldresolveto.Oftenthisbeanwillbeaprototype,inwhichcasethe

lookupmethodwillreturnadistinctinstanceoneveryinvocation.This

isusefulforsingle-threadedobjects.

-->

<!ATTLISTlookup-methodbeanCDATA#IMPLIED>

<!--

Similartothelookupmethodmechanism,thereplaced-methodelementisusedtocontrol

IoCcontainermethodoverriding:MethodInjection.Thismechanismallowstheoverriding

ofamethodwitharbitrarycode.

-->

<!ELEMENTreplaced-method(

(arg-type)*

)>

<!--

NameofthemethodwhoseimplementationshouldbereplacedbytheIoCcontainer.

Ifthismethodisnotoverloaded,there'snoneedtousearg-typesubelements.

Ifthismethodisoverloaded,arg-typesubelementsmustbeusedforall

overridedefinitionsforthemethod.

-->

<!ATTLISTreplaced-methodnameCDATA#IMPLIED>

<!--

BeannameofanimplementationoftheMethodReplacerinterfaceinthecurrent

orancestorfactories.Thismaybeasingletonorprototypebean.Ifit's

aprototype,anewinstancewillbeusedforeachmethodreplacement.

Singletonusageisthenorm.

-->

<!ATTLISTreplaced-methodreplacerCDATA#IMPLIED>

<!--

Subelementofreplaced-methodidentifyinganargumentforareplacedmethod

intheeventofmethodoverloading.

-->

<!ELEMENTarg-type(#PCDATA)>

<!--

SpecificationofthetypeofanoverloadedmethodargumentasaString.

Forconvenience,thismaybeasubstringoftheFQN.E.g.allthe

followingwouldmatch"java.lang.String":

-java.lang.String

-String

-Str

Asthenumberofargumentswillbecheckedalso,thisconveniencecanoften

beusedtosavetyping.

-->

<!ATTLISTarg-typematchCDATA#IMPLIED>

<!--

Definesareferencetoanotherbeaninthisfactoryoranexternal

factory(parentorincludedfactory).

-->

<!ELEMENTrefEMPTY>

<!--

Referencesmustspecifyanameofthetargetbean.

The"bean"attributecanreferenceanynamefromanybeaninthecontext,

tobecheckedatruntime.

Localreferences,usingthe"local"attribute,havetousebeanids;

theycanbecheckedbythisDTD,thusshouldbepreferredforreferences

withinthesamebeanfactoryXMLfile.

-->

<!ATTLISTrefbeanCDATA#IMPLIED>

<!ATTLISTreflocalIDREF#IMPLIED>

<!ATTLISTrefparentCDATA#IMPLIED>

<!--

Definesastringpropertyvalue,whichmustalsobetheidofanother

beaninthisfactoryoranexternalfactory(parentorincludedfactory).

Whilearegular'value'elementcouldinsteadbeusedforthesameeffect,

usingidrefinthiscaseallowsvalidationoflocalbeanidsbytheXML

parser,andnamecompletionbysupportingtools.

-->

<!ELEMENTidrefEMPTY>

<!--

IDrefsmustspecifyanameofthetargetbean.

The"bean"attributecanreferenceanynamefromanybeaninthecontext,

potentiallytobecheckedatruntimebybeanfactoryimplementations.

Localreferences,usingthe"local"attribute,havetousebeanids;

theycanbecheckedbythisDTD,thusshouldbepreferredforreferences

withinthesamebeanfactoryXMLfile.

-->

<!ATTLISTidrefbeanCDATA#IMPLIED>

<!ATTLISTidreflocalIDREF#IMPLIED>

<!--

Containsastringrepresentationofapropertyvalue.

Thepropertymaybeastring,ormaybeconvertedtotherequired

typeusingtheJavaBeansPropertyEditormachinery.Thismakesit

possibleforapplicationdeveloperstowritecustomPropertyEditor

implementationsthatcanconvertstringstoarbitrarytargetobjects.

Notethatthisisrecommendedforsimpleobjectsonly.

ConfiguremorecomplexobjectsbypopulatingJavaBean

propertieswithreferencestootherbeans.

-->

<!ELEMENTvalue(#PCDATA)>

<!--

Thevaluetagcanhaveanoptionaltypeattribute,tospecifythe

exacttypethatthevalueshouldbeconvertedto.Onlyneeded

ifthetypeofthetargetpropertyorconstructorargumentis

toogeneric:forexample,incaseofacollectionelement.

-->

<!ATTLISTvaluetypeCDATA#IMPLIED>

<!--

DenotesaJavanullvalue.Necessarybecauseanempty"value"tag

willresolvetoanemptyString,whichwillnotberesolvedtoa

nullvalueunlessaspecialPropertyEditordoesso.

-->

<!ELEMENTnull(#PCDATA)>

<!--

Alistcancontainmultipleinnerbean,ref,collection,orvalueelements.

Javalistsareuntyped,pendinggenericssupportinJava1.5,

althoughreferenceswillbestronglytyped.

Alistcanalsomaptoanarraytype.Thenecessaryconversion

isautomaticallyperformedbytheBeanFactory.

-->

<!ELEMENTlist(

(bean|ref|idref|value|null|list|set|map|props)*

)>

<!--

Enable/disablemergingforcollectionswhenusingparent/childbeans.

-->

<!ATTLISTlistmerge(true|false|default)"default">

<!--

SpecifythedefaultJavatypefornestedvalues.

-->

<!ATTLISTlistvalue-typeCDATA#IMPLIED>

<!--

Asetcancontainmultipleinnerbean,ref,collection,orvalueelements.

Javasetsareuntyped,pendinggenericssupportinJava1.5,

althoughreferenceswillbestronglytyped.

-->

<!ELEMENTset(

(bean|ref|idref|value|null|list|set|map|props)*

)>

<!--

Enable/disablemergingforcollectionswhenusingparent/childbeans.

-->

<!ATTLISTsetmerge(true|false|default)"default">

<!--

SpecifythedefaultJavatypefornestedvalues.

-->

<!ATTLISTsetvalue-typeCDATA#IMPLIED>

<!--

ASpringmapisamappingfromastringkeytoobject.

Mapsmaybeempty.

-->

<!ELEMENTmap(

(entry)*

)>

<!--

Enable/disablemergingforcollectionswhenusingparent/childbeans.

-->

<!ATTLISTmapmerge(true|false|default)"default">

<!--

SpecifythedefaultJavatypefornestedentrykeys.

-->

<!ATTLISTmapkey-typeCDATA#IMPLIED>

<!--

SpecifythedefaultJavatypefornestedentryvalues.

-->

<!ATTLISTmapvalue-typeCDATA#IMPLIED>

<!--

Amapentrycanbeaninnerbean,ref,value,orcollection.

Thekeyoftheentryisgivenbythe"key"attributeorchildelement.

-->

<!ELEMENTentry(

key?,

(bean|ref|idref|value|null|list|set|map|props)?

)>

<!--

Eachmapelementmustspecifyitskeyasattributeoraschildelement.

AkeyattributeisalwaysaStringvalue.

-->

<!ATTLISTentrykeyCDATA#IMPLIED>

<!--

Ashort-cutalternativetoa"key"elementwitha"refbean="childelement.

-->

<!ATTLISTentrykey-refCDATA#IMPLIED>

<!--

Ashort-cutalternativetoachildelement"value".

-->

<!ATTLISTentryvalueCDATA#IMPLIED>

<!--

Ashort-cutalternativetoachildelement"refbean=".

-->

<!ATTLISTentryvalue-refCDATA#IMPLIED>

<!--

Akeyelementcancontainaninnerbean,ref,value,orcollection.

-->

<!ELEMENTkey(

(bean|ref|idref|value|null|list|set|map|props)

)>

<!--

Propselementsdifferfrommapelementsinthatvaluesmustbestrings.

Propsmaybeempty.

-->

<!ELEMENTprops(

(prop)*

)>

<!--

Enable/disablemergingforcollectionswhenusingparent/childbeans.

-->

<!ATTLISTpropsmerge(true|false|default)"default">

<!--

Elementcontentisthestringvalueoftheproperty.

Notethatwhitespaceistrimmedofftoavoidunwantedwhitespace

causedbytypicalXMLformatting.

-->

<!ELEMENTprop(#PCDATA)>

<!--

Eachpropertyelementmustspecifyitskey.

-->

<!ATTLISTpropkeyCDATA#REQUIRED>

D.spring.tld

D.1.IntroductionD.2.ThebindtagD.3.TheescapeBodytagD.4.ThehasBindErrorstagD.5.ThehtmlEscapetagD.6.ThemessagetagD.7.ThenestedPathtagD.8.ThethemetagD.9.Thetransformtag

D.1.IntroductionOneoftheviewtechnologiesyoucanusewiththeSpringFrameworkisJava Server Pages (JSPs). To help you implement views using JavaServer Pages the Spring Framework provides you with some tags forevaluating errors, setting themes and outputting internationalizedmessages.Pleasenote that thevarious tagsgeneratedby this form tag libraryarecompliantwiththeXHTML-1.0-StrictspecificationandattendantDTD.Thisappendixdescribesthespring.tldtaglibrary.

D.2“The bindtag”

D.3“The escapeBodytag”

D.4“The hasBindErrorstag”

D.5“The htmlEscapetag”

D.6“The messagetag”

D.7“The nestedPathtag”

D.8“The themetag”

D.9“The transformtag”

D.2.ThebindtagProvidesBindStatusobjectforthegivenbindpath.TheHTMLescapingflag participates in a page-wide or application-wide setting (i.e. byHtmlEscapeTagora"defaultHtmlEscape"context-paraminweb.xml).

D.1.Attributes

Attribute Required? RuntimeExpression?Description

htmlEscape false true

SetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.

ignoreNestedPath false true Setwhethertoignoreanestedpath,ifany.Defaultistonotignore.

path true true

Thepathtothebeanorbeanpropertytobindstatusinformationfor.Forinstanceaccount.name,company.address.zipCodeorjustemployee.Thestatusobjectwillexportedtothepagescope,specificallyforthisbeanorbeanproperty

D.3.TheescapeBodytagEscapes its enclosed body content, applying HTML escaping and/orJavaScript escaping. The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a"defaultHtmlEscape"context-paraminweb.xml).

D.2.Attributes

Attribute Required? RuntimeExpression?Description

htmlEscape false true

SetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.

javaScriptEscape false true SetJavaScriptescapingforthistag,asbooleanvalue.Defaultisfalse.

D.4.ThehasBindErrorstagProvidesErrorsinstanceincaseofbinderrors.TheHTMLescapingflagparticipates in a page-wide or application-wide setting (i.e. byHtmlEscapeTagora"defaultHtmlEscape"context-paraminweb.xml).

D.3.Attributes

AttributeRequired? RuntimeExpression?Description

htmlEscape false trueSetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.

name true true

Thenameofthebeanintherequest,thatneedstobeinspectedforerrors.Iferrorsareavailableforthisbean,theywillbeboundunderthe'errors'key.

D.5.ThehtmlEscapetagSets default HTML escape value for the current page. Overrides a"defaultHtmlEscape"context-paraminweb.xml,ifany.

D.4.Attributes

Attribute Required? RuntimeExpression?Description

defaultHtmlEscape true trueSetthedefaultvalueforHTMLescaping,tobeputintothecurrentPageContext.

D.6.ThemessagetagRetrieves the message with the given code, or text if code isn'tresolvable. The HTML escaping flag participates in a page-wide orapplication-widesetting(i.e.byHtmlEscapeTagora"defaultHtmlEscape"context-paraminweb.xml).

D.5.Attributes

Attribute Required? RuntimeExpression?Description

arguments false true

Setoptionalmessageargumentsforthistag,asa(comma-)delimitedString(eachStringargumentcancontainJSPEL),anObjectarray(usedasargumentarray),orasingleObject(usedassingleargument).

argumentSeparator false trueTheseparatorcharactertobeusedforsplittingtheargumentsstringvalue;defaultstoa'comma'(',').

code false trueThecode(key)tousewhenlookingupthemessage.Ifcodeisnotprovided,thetextattributewillbeused.

htmlEscape false true

SetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.

javaScriptEscape false true SetJavaScriptescapingforthistag,asbooleanvalue.Defaultisfalse.

message false true

AMessageSourceResolvableargument(directorthroughJSPEL).FitsnicelywhenusedinconjunctionwithSpring'sownvalidationerrorclasseswhichallimplementtheMessageSourceResolvableinterface.Forexample,thisallowsyoutoiterateoveralloftheerrorsinaform,passingeacherror(usingaruntimeexpression)asthevalueofthis'message'attribute,thuseffectingtheeasydisplayofsucherrormessages.

Thescopetousewhenexportingthe

scope false trueresulttoavariable.Thisattributeisonlyusedwhenvarisalsoset.Possiblevaluesarepage,request,sessionandapplication.

text false true

Defaulttexttooutputwhenamessageforthegivencodecouldnotbefound.Ifbothtextandcodearenotset,thetagwilloutputnull.

var false true

Thestringtousewhenbindingtheresulttothepage,request,sessionorapplicationscope.Ifnotspecified,theresultgetsoutputtedtothewriter(i.e.typicallydirectlytotheJSP).

D.7.ThenestedPathtagSetsanestedpathtobeusedbythebindtag'spath.

D.6.Attributes

AttributeRequired? RuntimeExpression?Description

path true true

Setthepaththatthistagshouldapply.E.g.'customer'toallowbindpathslike'address.street'ratherthan'customer.address.street'.

D.8.ThethemetagRetrieves the thememessagewith the given code, or text if code isn'tresolvable. The HTML escaping flag participates in a page-wide orapplication-widesetting(i.e.byHtmlEscapeTagora"defaultHtmlEscape"context-paraminweb.xml).

D.7.Attributes

Attribute Required? RuntimeExpression?Description

arguments false true

Setoptionalmessageargumentsforthistag,asa(comma-)delimitedString(eachStringargumentcancontainJSPEL),anObjectarray(usedasargumentarray),orasingleObject(usedassingleargument).

argumentSeparator false trueTheseparatorcharactertobeusedforsplittingtheargumentsstringvalue;defaultstoa'comma'(',').

code false trueThecode(key)tousewhenlookingupthemessage.Ifcodeisnotprovided,thetextattributewillbeused.

htmlEscape false true

SetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.

javaScriptEscape false true SetJavaScriptescapingforthistag,asbooleanvalue.Defaultisfalse.

message false true AMessageSourceResolvableargument(directorthroughJSPEL).

scope false true

Thescopetousewhenexportingtheresulttoavariable.Thisattributeisonlyusedwhenvarisalsoset.Possiblevaluesarepage,request,sessionandapplication.

text false true

Defaulttexttooutputwhenamessageforthegivencodecouldnotbefound.Ifbothtextandcodearenotset,thetagwilloutputnull.

var false true

Thestringtousewhenbindingtheresulttothepage,request,sessionorapplicationscope.Ifnotspecified,theresultgetsoutputtedtothewriter(i.e.typicallydirectlytotheJSP).

D.9.ThetransformtagProvides transformation of variables to Strings, using an appropriatecustomPropertyEditor fromBindTag(canonlybeused insideBindTag).TheHTMLescapingflagparticipates inapage-wideorapplication-widesetting(i.e.byHtmlEscapeTagora'defaultHtmlEscape'context-paraminweb.xml).

D.8.Attributes

AttributeRequired? RuntimeExpression?Description

htmlEscape false trueSetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.

scope false true

Thescopetousewhenexportedtheresulttoavariable.Thisattributeisonlyusedwhenvarisalsoset.Possiblevaluesarepage,request,sessionandapplication.

value true true

Thevaluetotransform.Thisistheactualobjectyouwanttohavetransformed(forinstanceaDate).UsingthePropertyEditorthatiscurrentlyinusebythe'spring:bind'tag.

var false true

Thestringtousewhenbindingtheresulttothepage,request,sessionorapplicationscope.Ifnotspecified,theresultgetsoutputtedtothewriter(i.e.typicallydirectlytotheJSP).

E.spring-form.tld

E.1.IntroductionE.2.ThecheckboxtagE.3.ThecheckboxestagE.4.TheerrorstagE.5.TheformtagE.6.ThehiddentagE.7.TheinputtagE.8.ThelabeltagE.9.TheoptiontagE.10.TheoptionstagE.11.ThepasswordtagE.12.TheradiobuttontagE.13.TheradiobuttonstagE.14.TheselecttagE.15.Thetextareatag

E.1.IntroductionOneoftheviewtechnologiesyoucanusewiththeSpringFrameworkisJava Server Pages (JSPs). To help you implement views using JavaServer Pages the Spring Framework provides you with some tags forevaluating errors, setting themes and outputting internationalizedmessages.Pleasenote that thevarious tagsgeneratedby this form tag libraryarecompliantwiththeXHTML-1.0-StrictspecificationandattendantDTD.Thisappendixdescribesthespring-form.tldtaglibrary.

E.2“The checkboxtag”

E.3“The checkboxestag”

E.4“The errorstag”

E.5“The formtag”

E.6“The hiddentag”

E.7“The inputtag”

E.8“The labeltag”

E.9“The optiontag”

E.10“The optionstag”

E.11“The passwordtag”

E.12“The radiobuttontag”

E.13“The radiobuttonstag”

E.14“The selecttag”

E.15“The textareatag”

E.2.ThecheckboxtagRendersanHTML'input'tagwithtype'checkbox'.

E.1.Attributes

Attribute Required? RuntimeExpression?Description

accesskey false true HTMLStandardAttribute

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

label false true Valuetobedisplayedaspartofthetag

lang false true HTMLStandardAttribute

onblur false true HTMLEventAttribute

onchange false true HTMLEventAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onfocus false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

path true true Pathtopropertyfordatabinding

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

value false true HTMLOptionalAttribute

E.3.ThecheckboxestagRendersmultipleHTML'input'tagswithtype'checkbox'.

E.2.Attributes

Attribute Required? RuntimeExpression?Description

accesskey false true HTMLStandardAttribute

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

delimiter false trueDelimitertousebetweeneach'input'tagwithtype'checkbox'.Thereisnodelimiterbydefault.

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

element false trueSpecifiestheHTMLelementthatisusedtoencloseeach'input'tagwithtype'checkbox'.Defaultsto'span'.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

itemLabel false true Valuetobedisplayedaspartofthe'input'tagswithtype'checkbox'

items true trueTheCollection,Maporarrayofobjectsusedtogeneratethe'input'tagswithtype'checkbox'

Nameofthepropertymappedto'value'

itemValue false true attributeofthe'input'tagswithtype'checkbox'

lang false true HTMLStandardAttribute

onblur false true HTMLEventAttribute

onchange false true HTMLEventAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onfocus false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

path true true Pathtopropertyfordatabinding

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

E.4.TheerrorstagRendersfielderrorsinanHTML'span'tag.

E.3.Attributes

Attribute Required? RuntimeExpression? Description

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

delimiter false true Delimiterfordisplayingmultipleerrormessages.Defaultstothebrtag.

dir false true HTMLStandardAttribute

element false true SpecifiestheHTMLelementthatisusedtorendertheenclosingerrors.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

lang false true HTMLStandardAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

path false true Pathtoerrorsobjectfordatabinding

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

E.5.TheformtagRendersanHTML'form'tagandexposesabindingpathtoinnertagsforbinding.

E.4.Attributes

Attribute Required? RuntimeExpression?Description

acceptCharset false true

Specifiesthelistofcharacterencodingsforinputdatathatisacceptedbytheserverprocessingthisform.Thevalueisaspace-and/orcomma-delimitedlistofcharsetvalues.Theclientmustinterpretthislistasanexclusive-orlist,i.e.,theserverisabletoacceptanysinglecharacterencodingperentityreceived.

action false true HTMLRequiredAttribute

commandName false trueNameofthemodelattributeunderwhichtheformobjectisexposed.Defaultsto'command'.

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

enctype false true HTMLOptionalAttribute

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

lang false true HTMLStandardAttribute

method false true HTMLOptionalAttribute

modelAttribute false trueNameofthemodelattributeunderwhichtheformobjectisexposed.Defaultsto'command'.

name false true HTMLStandardAttribute-addedforbackwardscompatibilitycases

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

onreset false true HTMLEventAttribute

onsubmit false true HTMLEventAttribute

title false true HTMLStandardAttribute

E.6.ThehiddentagRendersanHTML'input'tagwithtype'hidden'usingtheboundvalue.

E.5.Attributes

AttributeRequired? RuntimeExpression? Description

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

path true true Pathtopropertyfordatabinding

E.7.TheinputtagRendersanHTML'input'tagwithtype'text'usingtheboundvalue.

E.6.Attributes

Attribute Required? RuntimeExpression?Description

accesskey false true HTMLStandardAttribute

alt false true HTMLOptionalAttribute

autocomplete false true CommonOptionalAttribute

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

lang false true HTMLStandardAttribute

maxlength false true HTMLOptionalAttribute

onblur false true HTMLEventAttribute

onchange false true HTMLEventAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onfocus false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

onselect false true HTMLEventAttribute

path true true Pathtopropertyfordatabinding

readonly false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willmaketheHTMLelementreadonly.

size false true HTMLOptionalAttribute

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

E.8.ThelabeltagRendersaformfieldlabelinanHTML'label'tag.

E.7.Attributes

Attribute Required? RuntimeExpression?Description

cssClass false true Equivalentto"class"-HTMLOptionalAttribute.

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedonlywhenerrorsarepresent.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

for false true HTMLStandardAttribute

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

lang false true HTMLStandardAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

path true true Pathtoerrorsobjectfordatabinding

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

E.9.TheoptiontagRendersasingleHTML'option'.Sets'selected'asappropriatebasedonboundvalue.

E.8.Attributes

Attribute Required? RuntimeExpression?Description

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

label false true HTMLOptionalAttribute

lang false true HTMLStandardAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

value true true HTMLOptionalAttribute

E.10.TheoptionstagRendersalistofHTML'option'tags.Sets'selected'asappropriatebasedonboundvalue.

E.9.Attributes

Attribute Required? RuntimeExpression?Description

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

itemLabel false true Nameofthepropertymappedtotheinnertextofthe'option'tag

items true true TheCollection,Maporarrayofobjectsusedtogeneratetheinner'option'tags

itemValue false true Nameofthepropertymappedto'value'attributeofthe'option'tag

lang false true HTMLStandardAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

E.11.ThepasswordtagRendersanHTML'input'tagwithtype'password'usingtheboundvalue.

E.10.Attributes

Attribute Required? RuntimeExpression?Description

accesskey false true HTMLStandardAttribute

alt false true HTMLOptionalAttribute

autocomplete false true CommonOptionalAttribute

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

lang false true HTMLStandardAttribute

maxlength false true HTMLOptionalAttribute

onblur false true HTMLEventAttribute

onchange false true HTMLEventAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onfocus false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

onselect false true HTMLEventAttribute

path true true Pathtopropertyfordatabinding

readonly false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willmaketheHTMLelementreadonly.

showPassword false true Isthepasswordvaluetobeshown?Defaultstofalse.

size false true HTMLOptionalAttribute

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

E.12.TheradiobuttontagRendersanHTML'input'tagwithtype'radio'.

E.11.Attributes

Attribute Required? RuntimeExpression?Description

accesskey false true HTMLStandardAttribute

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

label false true Valuetobedisplayedaspartofthetag

lang false true HTMLStandardAttribute

onblur false true HTMLEventAttribute

onchange false true HTMLEventAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onfocus false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

path true true Pathtopropertyfordatabinding

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

value false true HTMLOptionalAttribute

E.13.TheradiobuttonstagRendersmultipleHTML'input'tagswithtype'radio'.

E.12.Attributes

Attribute Required? RuntimeExpression?Description

accesskey false true HTMLStandardAttribute

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

delimiter false trueDelimitertousebetweeneach'input'tagwithtype'radio'.Thereisnodelimiterbydefault.

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

element false trueSpecifiestheHTMLelementthatisusedtoencloseeach'input'tagwithtype'radio'.Defaultsto'span'.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

itemLabel false true Valuetobedisplayedaspartofthe'input'tagswithtype'radio'

items true true TheCollection,Maporarrayofobjectsusedtogeneratethe'input'tagswithtype'radio'

itemValue false true Nameofthepropertymappedto'value'attributeofthe'input'tagswithtype'radio'

lang false true HTMLStandardAttribute

onblur false true HTMLEventAttribute

onchange false true HTMLEventAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onfocus false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

path true true Pathtopropertyfordatabinding

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

E.14.TheselecttagRendersanHTML'select'element.Supportsdatabindingtotheselectedoption.

E.13.Attributes

Attribute Required? RuntimeExpression?Description

accesskey false true HTMLStandardAttribute

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

itemLabel false true Nameofthepropertymappedtotheinnertextofthe'option'tag

items false true TheCollection,Maporarrayofobjectsusedtogeneratetheinner'option'tags

itemValue false true Nameofthepropertymappedto'value'attributeofthe'option'tag

lang false true HTMLStandardAttribute

multiple false true HTMLOptionalAttribute

onblur false true HTMLEventAttribute

onchange false true HTMLEventAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onfocus false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

path true true Pathtopropertyfordatabinding

size false true HTMLOptionalAttribute

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

E.15.ThetextareatagRendersanHTML'textarea'.

E.14.Attributes

Attribute Required? RuntimeExpression?Description

accesskey false true HTMLStandardAttribute

cols false true HTMLRequiredAttribute

cssClass false true Equivalentto"class"-HTMLOptionalAttribute

cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.

cssStyle false true Equivalentto"style"-HTMLOptionalAttribute

dir false true HTMLStandardAttribute

disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.

htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.

id false true HTMLStandardAttribute

lang false true HTMLStandardAttribute

onblur false true HTMLEventAttribute

onchange false true HTMLEventAttribute

onclick false true HTMLEventAttribute

ondblclick false true HTMLEventAttribute

onfocus false true HTMLEventAttribute

onkeydown false true HTMLEventAttribute

onkeypress false true HTMLEventAttribute

onkeyup false true HTMLEventAttribute

onmousedown false true HTMLEventAttribute

onmousemove false true HTMLEventAttribute

onmouseout false true HTMLEventAttribute

onmouseover false true HTMLEventAttribute

onmouseup false true HTMLEventAttribute

onselect false true HTMLEventAttribute

path true true Pathtopropertyfordatabinding

readonly false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willmaketheHTMLelementreadonly.

rows false true HTMLRequiredAttribute

tabindex false true HTMLStandardAttribute

title false true HTMLStandardAttribute

F.Spring2.5

F.1.F.2.F.3.F.4.

F.1.SpringSpring Framework( http://www.redsaga.com)Spring(http://spring.jactiongroup.net)SpringFrameworkApache2.0()Apache2.0

F.2.SpringJava

F.3.DigitalSonicDenis

F.1.

Yanger Caoxg

DigitalSonic MarcoChen

downpour joyheros

jzk whimet

melthaw crazycy

pesome zhanglong

ginge Kxllen

Jin Java

Joo YuLimin

Echo yeshucheng

Denis

hanson2010 88250

max

(Spring2.5)

F.4.20080305312.594521

20080308SpringSpringzhanglongginge24http://wiki.redsaga.com/confluence/pages/viewpage.action?pageId=26792.020080312KxllenJinJavaJoo4538

20080315YuLiminEchoyeshucheng40crazycy18yeshucheng20080319511xmlcvs20080322Denis118420080326451511200803293hanson201088250max2520080402RodJohnson----SpringSourceInfoQ……2112

200804052.0XML261220080412Wiki

20080419~Denis20080426Denis2.0CVS2008050345161515CVS200805102.5max123061020080517

20080525

20080601

zhanglong20080608

2008061534568zhanglongpesome2008062245820080630

SpringFramework2.54

top related