Page 1
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
Page 2
thatyoudonotchargeanyfeeforsuchcopiesandfurtherprovidedthateachcopycontainsthisCopyrightNotice,whetherdistributedinprintorelectronically.
Page 4
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)[email protected] (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.
Page 5
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
[email protected] .@Resource
Page 6
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
Page 7
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
Page 8
5. BeanWrapper
5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper
5.4.1.5.4.2.PropertyEditor
Page 9
6.SpringAOP6.1.
6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP
[email protected] [email protected] .
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.
[email protected]
6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW
6.9.
Page 10
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.
Page 11
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.
Page 12
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.
Page 13
10.DAO10.1.10.2.10.3.DAO
Page 14
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
Page 15
11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.
Page 16
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
Page 17
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
Page 18
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
[email protected] [email protected] [email protected] [email protected] [email protected]
13.13.
Page 19
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
Page 20
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.
Page 21
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.
Page 22
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.
Page 23
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
Page 24
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
Page 25
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.
Page 26
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.
Page 27
22.Spring22.1.22.2.Spring
22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator
22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.
Page 28
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
Page 29
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.
Page 30
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.
Page 31
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
Page 32
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
Page 33
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
Page 34
E.10.AttributesE.11.AttributesE.12.AttributesE.13.AttributesE.14.AttributesF.1.
Page 35
MVCframework AOP
Spring SpringSpringChristianBauer( Hibernate) DocBook-XSLHibernateHealy
Page 36
2004MartinFowler” Fowler
IoC
http://martinfowler.com/articles/injection.html
1
1.1.1.1.1.
JavaappletsnJavajavaClasswebClasses
FactoryAbstractFactoryBuilderDecorator ServiceLocator “ ......” wikisSpringIoCclassesSpringSpringFrameworkspringSpring
Page 37
1.1.Spring
Spring
CoreIoC BeanFactoryFactoryContext() Core:JNDIContextbeansI18Nresourcebundle,servletDAOJDBCJDBCobjectsORM“/”APIs JPAJDOHibernate iBatisORMSpring“/”
Page 38
Spring AOP AOPAllianceaspect-orientedprogrammingmethod-interceptorspointcutssource-level.NetattributeSpring WebWebServletlistenersIoCWebapplicationcontextWebWorkStrutsSpringSpringSpring MVCWebModel-View-ControllerMVCSpringMVC webformSpring
1.1.1.SpringAppletSpringWeb
SpringWeb
Spring WebEJB POJOSpringIoCemailwebSpringORMJPAHibernateJDOiBatisHibernateHibernateSessionFactoryweb ActionFormsclassHTTP
Page 39
Spring
Spring Spring WebWorkStrutsTapestryUISpring ApplicationContext WebApplicationContext
Page 40
WebServiceSpring Hessian-Burlap-Rmi- JaxRpcProxyFactory
EJBs-POJOs
SpringEJB POJOSessionBeanEJBWeb
Page 41
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)[email protected] (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.
Page 42
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
Page 43
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”
Page 44
2.2.5.classpathSpring2.5 classpathannotationstereotype: @Component,@Repository,@Service,@Controller.SpringbeanAnnotation-drivenbeanconfigurationisdiscussedin3.12.1“ @Component” .Annotationbean3.12.1“ @Component”
Page 45
2.3.(AOP)Spring2.0AOPSpringAOPXMLSpring2.0AspectJpointcut@AspectJaspect 6 SpringAOP
2.3.1.AOPXMLSpring2.0Java AspectJadvice“SchemaAOP”
[email protected] @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”
Page 46
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
Page 47
'?'
SimpleJdbcTemplateJava5+(Tiger) JdbcTemplate
Spring2.5 SimpleJdbcTemplate SimpleJdbcCallSimpleJdbcInsert
Page 48
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
Page 49
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
Page 50
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”
Page 51
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',
Page 52
'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
[email protected] 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
Page 53
JDO1.0spring2.0.7/2.0.8JDO1.0
2.7.1.9.UrlFilenameViewControllerSpring2.0 UrlFilenameViewControllerviewrequestUrlFilenameViewControllerSpring1.xSpring2.x SpringWebMVC
UrlFilenameViewControllerJavadocviewnamedetermination
Page 54
2.8.Spring2.0 Spring[zip|tar.gz]' 26
Spring2.5PetClinicPetPortalSpring2.5Java5autoboxing,varargsJava56SDKPetClinicPetPortalSpring2.5
Page 55
2.9.SpringSpring2.02.5ArthurLoderSpringFrameworkJavadocs
Page 56
I.SpringFrameworkSpringFrameworkIoCSpringFrameworkIoCSpringAOPSpringFrameworkAOPJavaAOP80%SpringAspectJ ,AspectJJavaAOPSpringTDDSpring""
3 IoC()
4
5 BeanWrapper
6 SpringAOP
7 SpringAOPAPIs
8
Page 57
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
[email protected] .@Resource
Page 58
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
Page 59
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
Page 60
5. BeanWrapper
5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper
5.4.1.5.4.2.PropertyEditor
Page 61
6.SpringAOP6.1.
6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP
[email protected] [email protected] .
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.
[email protected]
6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW
6.9.
Page 62
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.
Page 63
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.
Page 64
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
Page 65
[email protected] .@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
Page 66
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]
Page 67
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
Page 68
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;
Page 69
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”
Page 70
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"/>
Page 71
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()
Page 72
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
Page 73
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){
//...
}
}
Page 74
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>
Page 75
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
Page 76
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;
Page 77
}
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;
}
}
Page 78
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/>
Page 79
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
Page 80
</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
Page 81
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-->
Page 82
<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">[email protected] </prop>
<propkey="support">[email protected] </prop>
<propkey="development">[email protected] </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"/>
Page 83
</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">[email protected] </prop>
<propkey="support">[email protected] </prop>
</props>
</property>
</bean>
<beanid="child"parent="parent">
<propertyname="adminEmails">
<!--themergeisspecifiedonthe*child*collectiondefinition-->
<propsmerge="true">
<propkey="sales">[email protected] </prop>
<propkey="support">[email protected] </prop>
Page 84
</props>
</property>
</bean>
<beans>
childbeanadminEmails<props/>merge=true childbeanadminEmailsadminEmails
[email protected]
[email protected]
[email protected]
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"/>
Page 85
<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>
Page 86
<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
Page 87
<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="[email protected] />
</bean>
<beanname="p-namespace"class="com.example.ExampleBean"
p:email="[email protected] "/>
</beans>
beanpemailSpringbeanpropertypschemaattributebeanpropertyThisnextexample includes twomorebeandefinitions thatbothhavea
Page 88
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
Page 89
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
Page 90
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
Page 91
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
Page 92
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;
Page 93
……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">
Page 94
<!--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
Page 95
*/
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“”
Page 96
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
Page 97
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
Page 98
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“”
Page 99
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
Page 100
<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"/>
Page 101
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
Page 102
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
Page 103
<!--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
Page 104
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>
Page 105
</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>
Page 106
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
Page 107
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
Page 108
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.
Page 109
--@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...
}
}
Page 110
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;
Page 111
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;
Page 112
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
Page 113
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()
Page 114
preInstantiateSingletons()abstractbean
ApplicationContextBeanFactorysingletonbeanbeanclass 'abstract''true'
Page 115
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)
Page 116
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"
Page 117
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
Page 118
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
Page 119
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">
Page 120
<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
Page 121
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
Page 122
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
Page 123
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.
Page 124
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(){
Page 125
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
Page 126
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>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </value>
</list>
</property>
</bean>
<beanid="blackListListener"class="example.BlackListNotifier">
<propertyname="notificationAddress"value="[email protected] "/>
</bean>
Page 127
:
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
Page 128
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
Page 129
ant- /WEB-INF/*Context.xml
/WEB-INF/**/*Context.xml(WEB-INF"Context.xml")ContextLoaderServletContextLoaderListener'contextConfigLocation'
Page 130
3.9.singletonSpringIoCsingletonsingletonSpringIoC
Class.forName()SpringIoCstubproxysingletonSpringIoCEJBstub/proxySpringIoCJavaSpringIoCsingletonbeannon-singletonSpringIoCSpringIoCbeanHibernateSessionFactoryJ2EEJAREJBWAREARSpringIoCweb-appWARXMLSpringIoCSpringIoCweb-appsweb-appSpringIoCApplicationContextbeanbeanHibernateSessionFactory ContextSingletonBeanFactoryLocator
SingletonBeanFactoryLocatorsingletonSpringIoCwebSpringIoCbeanSingletonBeanFactoryLocatorContextSingletonBeanFactoryLocatorJavaDoc EJBSpringEJBnon-singleton BeanFactoryLocator
SingletonBeanFactoryLocatorContextSingletonBeanFactoryLocator
Page 131
3.10.J2EERARSpringApplicationContextSpring2.5RARSpringApplicationContextbeanJARsJ2EERARApplicationContextJ2EEJ2EERAR“”(headless)WAR——HTTPJ2EESpringApplicationContextWARRARHTTPBeansJTAJNDIJDBCJMSConnectionFactorybeansJMX——SpringJNDIJMXSpringWorkManagerSpringContextResourceAdapterJavaDocRAR
RAR JAR jarsRAR”META-INF/ra.xml“SpringContextResourceAdapterJavaDocSpringXMLbean"META-INF/applicationContext.xml"RAR
RAR“”JMSRARApplicationContextRMI
Page 132
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;
}
//...
}
Page 133
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;
Page 134
//...
}
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;
Page 135
}
//...
}
requiredSpring greediest@Autowired“” BeanFactory ApplicationContext ResourceLoader
ApplicationEventPublisher MessageSource
ConfigurableApplicationContextResourcePatternResolver
publicclassMovieRecommender{
@Autowired
privateApplicationContextcontext;
publicMovieRecommender(){
}
//...
}
3.11.2.@Qualifier
publicclassMovieRecommender{
@Autowired
@Qualifier("mainCatalog")
privateMovieCatalogmovieCatalog;
//...
}
@Qualifier
publicclassMovieRecommender{
Page 136
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;
}
//...
}
Page 137
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{
Page 138
@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;
Page 139
@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>
Page 140
<!--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
Page 141
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;
Page 142
@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“”
Page 143
3.12.ClasspathXML Spring”beanXML classpath
[email protected] @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"
Page 144
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">
Page 145
<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>
Page 146
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{
//...
Page 147
}
@Component
@Genre("Action")
publicclassActionMovieCatalogimplementsMovieCatalog{
//...
}
@Component
@Offline
publicclassCachingMovieCatalogimplementsMovieCatalog{
//...
}
XML
Page 148
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”
Page 149
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
Page 150
4.1.Java java.net.URLURL ServletContextURLURL( http:) URL
Page 151
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
Page 152
Resource UrlResourceURL URL
Page 153
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
Page 154
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]
Page 155
http: http://myserver/logo.png URL
(none) /data/config.xml ApplicationContext
[a] 4.7.3“ FileSystemResource”
Page 156
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”
Page 157
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"/>
Page 158
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
...
Page 159
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*:
Page 160
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=
Page 161
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");
Page 162
5 BeanWrapper
5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper
5.4.1.5.4.2.PropertyEditor
Page 163
5.1.Spring()WebSpring Validator
Data bindingSpring DataBinder ValidatorDataBinder
validationSpringMVCBeanWrapperSpring BeanWrapper BeanWrapper BeanWrapper
SpringPropertyEditor PropertyEditorJavaBean BeanWrapper
BeanWrapperDataBinder PropertyEditor
Page 164
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");
}
}
}
Page 165
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();
}
}
}
Page 166
ErrorsSpringWebMVC <spring:bind/>Javadoc
Page 167
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
Page 168
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;
}
Page 169
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");
Page 170
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
Page 171
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;
};
};
Page 172
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){
Page 173
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>
Page 174
</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>
Page 175
</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
Page 176
6SpringAOP
6.1.6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP
[email protected] [email protected] .
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.
[email protected]
6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW
6.9.
Page 177
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()
Page 178
Spring2.0 Object
AOPAOP
6.1.2.SpringAOPSpringAOPJavaSpringAOPJ2EEwebSpringjoinpointSpringbeanSpringAOPAPISpringAspectJSpringAOPSpringAOPSpringAOPAOPSpringIoCSpringAOPSpringIoCbeanSpring"autoproxying"AOPSpringAOPAspectJJ2EEAOPSpringAOPSpringAOPAOPAspectJproxy-basedSpringAOPAspectJSpring2.0SpringAOPIoCAspectJAOPSpringSpringAOPAPIAOPAllianceAPISpringAOP SpringAOPAPI
SpringFrameworknon-invasiveness ;/SpringFrameworkSpringSpringFrameworkAspectJSpringAOP@AspectJSpringXML@[email protected] “AOP”
6.1.3.AOPSpringJ2SEdynamicproxies AOPSpringCGLIB.CGLIBCGLIBSpringAOPproxy-based 6.6.1“AOP”
Page 179
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
Page 180
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
Page 181
@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;
Page 182
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.
Page 183
*/
@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)
Page 184
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
Page 185
'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
Page 186
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;
Page 187
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
Page 188
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{
//...
}
Page 189
}
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()
Page 190
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&&"+
Page 191
"@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
}
Page 192
'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
Page 193
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'
Page 194
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;
Page 195
}
}
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{
...
}
Page 196
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
Page 197
6.3.2.
<aop:config>
serviceservice
<aop:config>
<aop:pointcutid="businessService"
expression="execution*com.xyz.myapp.service.*.*.."/>
</aop:config>
6.2“@AspectJ” AspectJ [email protected]
<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>
Page 198
</aop:config>
@AspectJschema(collect)
<aop:config>
<aop:aspectid="myAspect"ref="aBean">
<aop:pointcutid="businessService"
expression="execution*com.xyz.myapp.service.*.*..&&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>
Page 199
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.
Page 200
<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"/>
...
Page 201
</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">
Page 202
<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{
Page 203
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"/>
Page 204
<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
Page 205
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
Page 206
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;
Page 207
}
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"
Page 208
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"/>
Page 209
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
Page 210
@AspectJ @AspectJ“”
Page 211
6.5.@AspectJ schema-definedadvisorSpring1.2
Page 212
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();
}
Page 213
publicvoidbar(){
//somelogic...
}
}
publicclassMain{
publicstaticvoidmain(String[]args){
Pojopojo=newSimplePojo();
//thisisadirectmethodcallonthe'pojo'reference
pojo.foo();
}
}
Page 214
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());
Page 215
factory.adddInterface(Pojo.class);
factory.addAdvice(newRetryAdvice());
factory.setExposeProxy(true);
Pojopojo=(Pojo)factory.getProxy();
//thisisamethodcallontheproxy!
pojo.foo();
}
}
AspectJAOP
Page 216
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();
Page 217
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{
//...
Page 218
}
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
Page 219
<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
Page 220
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"/>
Page 221
</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());
Page 222
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"
Page 223
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
Page 224
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
Page 225
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
Page 226
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="
Page 227
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
Page 228
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
Page 229
6.9.AspectJ AspectJwebsite
EclipseAspectJAdrianColyer(Addison-Wesley,2005) AspectJAspectJinActionRamnivasLaddad(Manning,2003)AOPAOP
Page 230
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.
Page 231
[email protected] Spring1.2Spring2.0Spring1.2Spring2.0
Page 232
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,
Page 233
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
Page 234
<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.
Page 235
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“”
Page 236
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
Page 237
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 :
Page 238
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.
Page 239
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);
}
Page 240
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
Page 241
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
Page 242
LockMixinAdvisorLockMixinAdvised.addAdvisor()XML“”
Page 243
7.4.SpringAdvisorAPISpringAdvisoradvisororg.springframework.aop.support.DefaultPointcutAdvisor
MethodInterceptorBeforeAdvice ThrowsAdvice
SpringAOP Spring
Page 244
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
Page 245
*
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>
Page 246
<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"/>
Page 247
<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">
Page 248
<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"/>
Page 249
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>
Page 250
abstractbeanabstract beanabstracttrue
Page 251
7.7.ProxyFactoryAOPSpringAOPSpringAOPSpringIoC
ProxyFactoryfactory=newProxyFactory(myBusinessInterfaceImpl);
factory.addInterceptor(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterfacetb=(MyBusinessInterface)factory.getProxy();
org.springframework.aop.framework.ProxyFactoryProxyFactoryIntroductionInterceptionAroundAdvisorProxyFactory AdvisedSupport AdvisedSupportProxyFactoryProxyFactoryBean
AOPIoCJavaAOP
Page 252
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());
Page 253
//Addselectiveadviceusingapointcut
advised.addAdvisor(newDefaultPointcutAdvisor(mySpecialPointcut,myAdvice));
assertEquals("Addedtwoadvisors",
oldAdvisorCount+2,advised.getAdvisors().length);
frozen AdvisedisFrozen()trueSpring1.1
Page 254
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.
Page 255
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
Page 256
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">
Page 257
<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
Page 258
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
Page 259
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
Page 260
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
Page 261
7.11. Advice
SpringAOPorg.springframework.aop.framework.adapterSPIorg.aopalliance.aop.Advice
org.springframework.aop.framework.adapterJavadoc
Page 262
7.12.SpringSpringAOP
JPetStoreTransactionProxyFactoryBean
JPetStore/attributes
Page 263
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.
Page 264
8.1.SpringIoC Spring
Page 265
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.
Page 266
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
Page 267
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
Page 268
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“”
Page 269
@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(){
//...
Page 270
}
@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
Page 271
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">
Page 272
<!--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.
Page 273
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
Page 274
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
Page 275
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{
Page 276
//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);
}
}
Page 277
@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)
Page 278
//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
Page 279
@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
}
Page 280
@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()
Page 281
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(){
Page 282
//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=...)
Page 283
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...
Page 284
}
@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
Page 285
@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{}
Page 286
PetClinicSpringSpringDataSourceJtaTransactionManagerJNDIJTABasicDataSourceDataSourceTransactionManager
HibernateTransactionManagerXML''
Page 287
8.4.
JUnitSpringJUnit3.8
TestNGTestNGJUnit3.8Java5
MockObjectsMockObjects
“MockObjects”
EasyMockSpringEasyMock
JMockJMockmockJava
DbUnitDbUnitJUnitAnt
GrinderGrinderJava
Page 288
II.
SpringSpringFramework9
10 DAO
11 JDBC
12 ORM
Page 289
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.
Page 290
10.DAO10.1.10.2.10.3.DAO
Page 291
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
Page 292
11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.
Page 293
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
Page 294
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.
Page 295
9.1.SpringSpring
APIJTAJDBCHibernateJPAJDO
APIJTA API
SpringSpring
SpringEJBCMTAPIHibernate
Spring DataSource
Spring
Spring
Page 296
SpringJ2EEEJBJTASpringEJBCMTJTAOracle9iRACJMSJCASpring EJBCMTJTAJDBCSpring
9.2.J2EE JTAJDBC
. JTAAPIJTAUserTransactionJNDIJTA JNDIJTAJTA EJBCMTJNDIEJBJNDICMTJTAEJBEJBFacadeEJBEJB. JDBCJTASpring Spring
SpringSpringAPI
Page 297
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();
Page 298
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-->
Page 299
</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
Page 300
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
Page 301
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
Page 302
9.5.2. Foo Bar
//
packagex.y.service;
publicinterfaceFooService{
FoogetFoo(StringfooName);
FoogetFoo(StringfooName,StringbarName);
voidinsertFoo(Foofoo);
voidupdateFoo(Foofoo);
}
//
Page 303
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"/>
Page 304
<!--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
Page 305
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]
Page 306
<!--...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">
Page 307
<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'
Page 308
'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
Page 309
<?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>
Page 310
<!--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
Page 311
@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)-->
Page 312
@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“”
Page 313
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
Page 314
@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
Page 315
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED rollback-onlyPROPAGATION_REQUIRED rollback-onlyrollback-only
9.5.7.2.RequiresNew
PROPAGATION_REQUIRES_NEW
PROPAGATION_REQUIRES_NEW
Page 316
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;
}
Page 317
//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>
Page 318
</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)-->
Page 319
<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
Page 320
AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager);
aspect / AspectJJava @Transactional @Transactional AnnotationTransactionAspect AspectJ AspectJ Development
Guide“”load-timeweaving 6.8.4“SpringAspectJLTW” AspectJ“”
Page 321
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();
}
});
}
}
Page 322
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...
Page 323
}
}
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);
Page 325
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
Page 326
9.9.
9.9.1. DataSource PlatformTransactionManager Springorg.springframework.transaction.jta.JtaTransactionManager Spring
Page 327
9.10.Spring
InfoQ JavaJavaTransactionDesignStrategies Java
Page 328
10DAO
10.1.10.2.10.3.DAO
Page 329
10.1.SpringDAO() JDBCHibernateJDO
Page 330
10.2.Spring SQLExceptionJDBCSpringHibernatechecked DAOcatch/throwSpringORMSessionFactoryUtils convertHibernateAccessException
convertJdoAccessException org.springframework.dao
unchecked DAOSpring DataAccessException
Page 331
10.3.DAOJDBCJDOHibernate Spring
JdbcDaoSupport-JDBC DataSource
HibernateDaoSupport-Hibernate SessionFactory
HibernateTemplate HibernateTemplateexceptiontranslatorJdoDaoSupport-JDO PersistenceManagerFactory
JpaDaoSupport-JPA EntityManagerFactory
Page 332
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
Page 333
11.6.3.SqlUpdate11.6.4.StoredProcedure11.6.5.SqlFunction
11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.
Page 334
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
Page 335
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
Page 336
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);
Page 337
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"));
Page 338
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
Page 339
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
Page 340
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);
Page 341
}
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){
Page 342
//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;
Page 343
}
};
//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()
Page 344
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){
Page 345
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(){
Page 346
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);
Page 347
}
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(?)";
Page 348
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
Page 349
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
Page 350
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
Page 351
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
Page 352
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(),
Page 353
actor.getLastName(),
actor.getId()};
batch.add(values);
}
int[]updateCounts=simpleJdbcTemplate.batchUpdate(
"updatet_actorsetfirst_name=?,last_name=?whereid=?",
batch);
returnupdateCounts;
}
//...additionalmethods
}
int JDBCJDBC-2
Page 354
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;
Page 355
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);
Page 356
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;
Page 357
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
Page 358
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);
Page 359
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
}
Page 360
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);
Page 361
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);
Page 362
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
Page 363
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){
Page 364
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
*/
Page 365
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");
Page 366
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;
Page 367
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;
Page 368
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);
}
}
Page 369
11.6.5.SqlFunctionSqlFunctionRDBMSSQL“”wrapperqueryForXxx SqlFunction JdbcTemplate
SQL“selectuser()” “selectsysdatefromdual”StoredProcedureSqlCall
SqlFunction SQLrun
publicintcountRows(){
SqlFunctionsf=newSqlFunction(dataSource,"selectcount(*)frommytable");
sf.compile();
returnsf.run();
}
Page 370
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
Page 371
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");
Page 372
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]);
Page 373
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
Page 374
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
Page 375
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
Page 376
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>
Page 377
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);
Page 378
}
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(
Page 379
"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;
Page 380
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
Page 381
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.
Page 382
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
Page 383
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>
Page 384
</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">
Page 385
<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>
Page 386
</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
Page 387
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
Page 388
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
Page 389
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()
Page 390
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
Page 391
<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();
Page 392
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="
Page 393
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
Page 394
JDBCConnectionJDBCDAO
Spring
PersistenceManagerJDBC
JDOExceptionsSpring DataAccessExceptionsJDO1.0API JDO2.0Spring1.2JDO2.0APISpringJDO JdoDialectJavadoc
Page 395
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>
Page 396
<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();
Page 397
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()
Page 398
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
Page 399
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>
Page 400
<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
Page 401
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"/>
Page 402
</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
Page 403
<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;
Page 404
}
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>
Page 405
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
Page 406
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
Page 407
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
Page 408
<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>
Page 409
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-->
Page 410
<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;
}
});
Page 411
}
}
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;
Page 412
@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/>
Page 413
(@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{
Page 414
//classbodyhere...
}
<beans>
<!--Exceptiontranslationbeanpostprocessor-->
<beanclass="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<beanid="myProductDao"class="product.ProductDaoImpl"/>
</beans>
PersistenceExceptionTranslator @RepositorybeanDAOJavaAPISpringIoC
Page 415
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
Page 416
12.8.JpaDialectJpaTemplateJpaTransactionManager
AbstractEntityManagerFactoryBean JpaDialect"jpaDialect"beanDAO EntityManagerFactory JpaDaoSupport"jpaTemplate" JpaDialectSpring
ConnectionJDBCDAO
PersistenceExceptionsSpring DataAccessExceptionsDefaultJpaDialectDialect
SpringJPA JpaDialectJavadoc
Page 417
III.TheWebSprintFrameworkwebSpringFrameworkweb SpringWebMVCSpringFrameworkweb JSF
SpringMVC Portlet13 WebMVCframeworkWeb
14
15 Web
16 PortletMVC
Page 418
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
Page 419
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
[email protected] [email protected] [email protected] [email protected] [email protected]
13.13.
Page 420
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
Page 421
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.
Page 422
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
Page 423
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
Page 424
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
[email protected] [email protected] [email protected] [email protected] [email protected]
13.13.
Page 425
“”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
Page 426
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“”
Page 427
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>
Page 428
<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
Page 429
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
Page 430
(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
Page 431
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
Page 432
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
Page 433
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)
Page 434
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()));
}
}
Page 435
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
Page 436
Map getTargetPage() onBindAndValidate()
setAllowDirtyBack()setAllowDirtyForward() getTargetPage()
AbstractWizardFormControllerJavaDoc SpringjPetStoreorg.springframework.samples.jpetstore.web.spring.OrderFormController
Page 437
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"/>
Page 438
<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>
Page 439
<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"/>
Page 440
<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>
Page 441
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
Page 442
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
Page 443
<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
Page 444
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
Page 445
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
Page 446
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
Page 447
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-
Page 448
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
Page 449
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
Page 450
<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>
Page 451
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(){
Page 452
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{
Page 453
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){
Page 454
this.file=file;
}
publicMultipartFilegetFile(){
returnfile;
}
}
Page 455
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>
Page 456
</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>
Page 457
</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){
Page 458
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)
Page 459
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”
Page 460
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"/>
Page 461
</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>
Page 462
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>
Page 463
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.");
}
}
Page 464
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>
Page 465
</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>
Page 466
<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>
Page 467
13.10. Spring HandlerExceptionResolvers
Web web.xmlexceptionmappings
HandlerExceptionResolver resolveExceptionExceptionHandler
ModelAndView SimpleMappingExceptionResolver
Page 468
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
Page 469
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”
Page 470
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"/>
Page 471
<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
Page 472
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
Page 473
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")
Page 474
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{
Page 475
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")
Page 476
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
Page 477
@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{
//...
Page 478
@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
Page 479
@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>
Page 480
13.13.SpringWebMVC
SpringSpringWebMVCSpringWebMVCSpring“ docs”SpringFramework
SethLadd“ ExpertSpringWebMVCandWebFlow”ApressSpringWebMVC
Page 481
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
Page 482
14.1.SpringviewMVC VelocityXSLTJSP“” “mvc-viewresolver”viewMVC
Page 483
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
Page 484
14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTLJSTLview JstlViewJSTLi18N
14.2.3.SpringJSPSpringspring.jar(TLD)tagtag
Page 485
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
Page 486
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
Page 487
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>
Page 488
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-->
Page 489
<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>
Page 490
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
Page 491
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”
Page 492
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/>
Page 493
*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=""
Page 494
><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
Page 495
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
Page 497
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
Page 498
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
Page 499
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
Page 500
classpathXMLXSLTJDK1.4J2EE
Page 501
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
Page 502
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");
Page 503
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
Page 504
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
Page 505
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);
Page 506
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
Page 507
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>
Page 508
</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!
</td><td
width="50%">&nbsp;
Page 509
</td></tr>
</table></body></html>
</value></entry></map>
</property></bean>
JasperReportsHtmlView exporternet.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER
HTML
Page 510
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.
Page 511
SpringWebFlowSpringWebFlowSWFWeb
SWFservletportletSpringMVCStrutsJSF SWFSWFSWF SpringWebFlow
15.1.Spring StrutsJSFTapestry WebWorkSpring Spring WebSpringWebSpringMVC WebStrutsSpringSpringSpringWebJavaJavaWeb...JavaWeb SpringWebWebStruts WebStruts Web 15.7“”
Page 512
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()
Page 513
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE NullPointerExceptions getRequiredWebApplicationContext()
ApplicationContext WebApplicationContext beanbeanbeanSpring
Page 514
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>
Page 515
15.3.2.FacesContextUtils faces-config.xmlbean VariableResolver
FacesContextUtils WebApplicationContextUtils
ServletContext
ApplicationContextctx=FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
DelegatingVariableResolverJSFSpring
Page 516
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”
Page 517
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">
Page 518
<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,
Page 519
LookupDispatchActionSupportand
MappingDispatchActionSupport.
Page 520
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"
Page 521
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
Page 522
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);
Page 523
//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
Page 524
<?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>
Page 525
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");
Page 526
}
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;
}
}
/**
Page 527
*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));
}
}
}
Page 528
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"/>
Page 529
</contribution>
</module>
Java5annotationJava5annotationTapestry XML.page .jwc
<injectproperty="userService"object="spring:userService"/>
<injectproperty="authenticationService"object="spring:authenticationService"/>
SpringbeanTapestryTapestryJ2EE
Page 530
15.6.WebWork WebWork...“WebWorkJavaWebJavaBean ”WebWorkWebWebWork IoC WebWorkAction“wiring”WebWork2.2WebWorkIoC IoCSpringWebWork2.2IoC SpringSpringWebWorkDRY-Don'tRepeatYourselfSpring-WebWorkWebWork WebWorkwiki Spring-WebWork
Spring-WebWorkWebWorkSpringSpring-WebWork
Page 531
15.7.Web
TheStrutshomepage
TheJSFhomepage
TheTapestryhomepage
TheWebWorkhomepageWeb
TheStrutsTIprojectwiki
Page 532
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
Page 533
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
Page 534
SpringPortletMVCWebBeanBeanHTTP HTTPWebApplicationContext 3.4.4“” Bean
SpringSpringPortletMVCSpringPortletMVCsamples/petportal'petportal'
Page 535
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“” )
Page 536
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”)
Page 537
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
Page 538
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
Page 539
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
Page 540
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>
Page 541
portlet JSR-168MyFacesOpenSessionInViewInterceptor
Page 542
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'
Page 543
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>
Page 544
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
Page 545
16.6.SpringPortleMVCSprintWebMVCViewViewResolver
portletHTML JSP/JSTLVelocityFreeMakerXSLTportlet
portletHTTP(ActionResponsesendRedirect(..)portal)PortletMVCRedirectView'redirect:'
PortletMVC'forward:' portletURLURLURL
JSPSpringTaglibSpringtaglibServletportlet
Page 546
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
Page 547
<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{
Page 548
//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{
Page 549
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;
}
}
Page 550
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;
}
}
Page 551
16.8.WebMVCPortletMVC HandlerExceptionResolver PortletMVCSimpleMappingExceptionResolver
Page 552
16.9.PortletSpringPortletMVCJSR-168Portletportal/portletservletWeb PortletservletWebPortletPortletServletContextServlet portlet.xml
JSR-168Portlet “”PortletPortletPortletPortlet web.xml PortletServletServletWebPortletServletPortletWebPortletPortletJSPTabportalPortlet ()portalPortlet web.xmlportal ViewRendererServletPortlet
Page 553
IV.SpringFrameworkJ2EE
17 SpringWeb
18 EnterpriseJavaBeans(EJB)
19 JMS(JavaMessageService)
20 JMX
21 JCACCI
22 Spring
23 Spring(Scheduling)(ThreadPooling)
24
25
Page 554
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.
Page 555
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
Page 556
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
Page 557
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.
Page 558
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.
Page 559
22.Spring22.1.22.2.Spring
22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator
22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.
Page 560
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
Page 561
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.
Page 562
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.
Page 563
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.
Page 564
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);
}
Page 565
publicinterfaceRemoteAccountServiceextendsRemote{
publicvoidinsertAccount(Accountaccount)throwsRemoteException;
publicListgetAccounts(Stringname)throwsRemoteException;
}
//
publicclassAccountServiceImplimplementsAccountService{
publicvoidinsertAccount(Accountacc){
//……
}
publicListgetAccounts(Stringname){
//……
}
}
RMIRMIHessian
Page 566
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;
Page 567
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
Page 568
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
Page 569
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
Page 570
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
Page 571
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>
Page 572
</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>
Page 573
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
Page 574
*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
Page 575
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){
Page 576
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
Page 577
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>
Page 578
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);
}
}
Page 579
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);
}
}
Page 580
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;
Page 581
}
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"/>
Page 582
<propertyname="serviceBean">
<beanclass="org.codehaus.xfire.spring.EchoImpl"/>
</property>
<!--theXFirebeanisdefinedinthexfire.xmlfile-->
<propertyname="xfire"ref="xfire"/>
</bean>
</beans>
XFireWSDLXFireXFireSpring docs.codehaus.org/display/XFIRE/Spring
Page 583
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>
Page 584
</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"});
}
}
Page 585
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 ”
Page 586
17.7.InitializingBeanDisposableBean
Page 587
17.8.
RMIHTTPHTTPRMIRMIRMI-JRMPJavaJava-to-JavaHTTPJavaSpringHTTPRMIHTTPHTTPJava-to-JavaSpringSpringRMIRMISpringJMSJMSbroker-JMSJMSJavaJMSXStreamRMIEJBRMIHTTPSpringSpring
Page 588
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
Page 589
18.1.SpringEJBSpringORMJDBCEJBEJBSpringEJBSpringEJBSpringEJBEJBEJBPOJO(Java)SpringEJBSpringSessionBean(SLSBs)
Page 590
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>
Page 591
<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
Page 592
SpringEJB2.XEJB3SessionbeanSpringEJBjee:remote-slsb EJB2.xhomeEJB3home:EJB3sessionbean JndiObjectFactoryBean/jee:jndi-lookupjee:local-slsb/jee:remote-slsbEJB
Page 593
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);
}
Page 594
//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>
Page 595
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
Page 596
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
Page 597
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
Page 598
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
Page 599
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
Page 600
JTAXAConnectionFactoryJ2EE/JMSJMSAPI Connection SessionJMSAPI SessionJMS JmsTemplate SessionTransacted
SessionAcknowledgeMode JmsTemplatePlatformTransactionManagerJMS Session
Page 601
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
Page 602
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}
Page 603
Age={Integer:47}
}
}
19.3.2.SessionCallback ProducerCallback
sendJMS Session MessageProducer SessionCallbackProducerCallback JMS Session Session / MessageProducer
JmsTemplate execute()
Page 604
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"/>
Page 605
<!--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
Page 606
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);
}
Page 607
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.
Page 608
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>
Page 609
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
Page 610
JCASpringContextSpringJMS“”JMSJCAAPI
Page 611
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
Page 612
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'
Page 613
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'
Page 614
client-id JMSid
acknowledge JMS autoclientdups-ok transacted 'auto' 'transacted'
Session transaction-manager
transaction-manager
SpringJtaTransactionManager javax.transaction.TransactionManagerXA “acknowledge”
concurrency Session
prefetch Session
Page 615
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.
Page 616
JMXJMXJMXJMXJMX 20.8“”
20.1.SpringJMXSpringJMXSpringJMX
SpringBeanJMXMBean
Bean
JSR-160MBean
MBeanSpringJMX SpringJMXSpringJMX
Page 617
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>
Page 618
<!--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"/>
<!--
Page 619
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">
Page 620
<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"/>
Page 621
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">
Page 622
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
Page 623
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;
Page 624
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();
Page 625
}
}
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>
Page 626
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(){
Page 627
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>
Page 628
<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
Page 629
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-->
Page 630
<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);
Page 631
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
Page 632
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
Page 633
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>
Page 634
</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
Page 635
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"/>
.
Page 636
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>
Page 637
</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
Page 638
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
Page 639
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"/>
Page 640
</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>
Page 641
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>
Page 642
<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>
Page 643
<!-- 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)
Page 644
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
Page 645
20.8.JMX
Sun JMX
JMXJSR-000003
JMXJSR-000160
MX4JJMX
GettingStartedwithJMX-Sun.
Page 646
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.
Page 647
21.1.J2EEJCAJavaConnectorArchitectureEISEnterpriseInformationSystem
SPIServiceproviderinterfacesconnectorproviderresourceadapter connectionpoolingmanagedmode connectornon-managedmodeCCICommonClientInterfaceEISAPI
SpringCCISpringCCISpring
CCIAPIJCAresourceadaptercontractsconnectionpoolingglobaltransactionssecurity Springconnector-specificAPI
Page 648
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">
Page 649
<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">
Page 650
<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
Page 651
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;
Page 652
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{...}
}
Page 653
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(){...}
Page 654
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,
Page 655
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
Page 656
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);
Page 657
}
});
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());
Page 658
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>
Page 659
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);
...
Page 660
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
Page 661
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{
Page 662
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>
Page 663
<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.
Page 664
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
Page 665
<beanid="connectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="eis/cicseci"/>
</bean>
<beanid="component"class="MyDaoImpl">
<propertyname="connectionFactory"ref="connectionFactory"/>
</bean>
Page 666
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
Page 667
22Spring
22.1.22.2.Spring
22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator
22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.
Page 668
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
Page 669
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()
Page 670
+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="[email protected] "/>
<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;
Page 671
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("[email protected] "));
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());
}
}
}
Page 672
SpringAOP OrderManagerjoinpointSpring FrameworkMailSenderJavaMailJason Hunter MailMessage
com.oreilly.servletJavadocs
Page 673
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("[email protected] ");
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("[email protected] ");
helper.setText("Checkoutthisimage!");
//let'sattachtheinfamouswindowsSamplefile(thistimecopiedtoc:/)
FileSystemResourcefile=newFileSystemResource(newFile("c:/Sample.jpg"));
helper.addAttachment("CoolImage.jpg",file);
sender.send(message);
Page 674
22.3.1.2.MimeMessageHelperemail
JavaMailSenderImplsender=newJavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessagemessage=sender.createMimeMessage();
//usethetrueflagtoindicateyouneedamultipartmessage
MimeMessageHelperhelper=newMimeMessageHelper(message,true);
helper.setTo("[email protected] ");
//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
Page 675
#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...
Page 676
sendConfirmationEmail(user);
}
privatevoidsendConfirmationEmail(finalUseruser){
MimeMessagePreparatorpreparator=newMimeMessagePreparator(){
publicvoidprepare(MimeMessagemimeMessage)throwsException{
MimeMessageHelpermessage=newMimeMessageHelper(mimeMessage);
message.setTo(user.getEmailAddress());
message.setFrom("[email protected] ");//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>
Page 677
</property>
</bean>
</beans>
Page 678
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
Page 679
23.1.SpringSpringJDK1.3 TimerQuartzScheduler(http://www.opensymphony.com/quartz/) FactoryBeanTimerTrigger
QuartzScheduler Timer MethodInvokingFactoryBeanSpringJava1.3,1.4,5JEE
Page 680
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
}
}
Page 681
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
Page 682
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
Page 683
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>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </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>
Page 684
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>
Page 685
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
Page 686
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));
}
Page 687
}
}
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>
Page 688
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.
Page 689
aJava cSpringSpring
24.1.Spring2.0SpringJRubySpringSpring
JRuby
Groovy
BeanShell24.4“” Spring
Spring2.0Spring 1.2.x
Page 690
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{
Page 691
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
Page 692
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
Page 693
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());
}
}
Page 694
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>
Page 695
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<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(){}
Page 696
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{
Page 697
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
Page 698
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
}
}
Page 699
<--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()){
Page 700
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
Page 701
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
Page 702
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())
}
}
Page 703
<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.")
}
}
Page 704
24.5.Bitsandbobs
Page 705
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
Page 706
24.6.
JRuby
Groovy
BeanShellSpringSpring
Page 707
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.
Page 708
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
Page 709
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
Page 710
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
Page 711
<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”
Page 712
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>
Page 713
</target>
javacCommonsAttributesMavenCommonsAttributes(Springweb)jar
<attribute-indexerjarFile="myCompiledSources.jar">
<classpathrefid="master-classpath"/>
</attribute-indexer>
SpringjPetStore/attributesSpringAttributesCommonsAttributes CommonsAttributesAPISpring
Page 714
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“”
Page 716
26.26.1.26.2.SpringMVC
26.2.1.26.3.SimpleJdbcTemplate@RepositoryDAO
26.3.1.26.3.2.DataAccessObject26.3.3.
Page 717
26
26.1.26.2.SpringMVC
26.2.1.26.3.SimpleJdbcTemplate@RepositoryDAO
26.3.1.26.3.2.DataAccessObject26.3.3.
Page 718
26.1.SpringFramework Spring2.0
Page 719
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"
Page 720
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
Page 721
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
Page 722
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
Page 723
fact that this new configuration mechanism is totally customisable andextensible. This means you can write your own domain-specificconfigurationtagsthatwouldbetterrepresentyourapplication'sdomain;theprocessinvolvedindoingsoiscoveredintheappendixentitled B,ExtensibleXMLauthoring.
Page 724
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
Page 725
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>
Page 726
</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"/>
Page 727
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{
Page 728
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...
Page 729
<!--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"/>
Page 730
<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...
Page 731
<!--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>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </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>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </value>
Page 732
<value>[email protected] </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>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </value>
<value>d'[email protected] </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="[email protected] "/>
<entrykey="raskolnikov"value="[email protected] "/>
<entrykey="stavrogin"value="[email protected] "/>
<entrykey="porfiry"value="[email protected] "/>
</map>
</property>
</bean>
TheaboveconfigurationusesaSpringFactoryBean implementation, theMapFactoryBean, to create a java.util.Map instance initialized with key-
Page 733
valuepairstakenfromthesupplied'sourceMap'.After...
<!--createsajava.util.Mapinstancewithvaluesloadedfromthesupplied
<util:mapid="emails">
<entrykey="pechorin"value="[email protected] "/>
<entrykey="raskolnikov"value="[email protected] "/>
<entrykey="stavrogin"value="[email protected] "/>
<entrykey="porfiry"value="[email protected] "/>
</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="[email protected] "/>
<entrykey="raskolnikov"value="[email protected] "/>
<entrykey="stavrogin"value="[email protected] "/>
<entrykey="porfiry"value="[email protected] "/>
</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>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </value>
Page 734
<value>[email protected] </value>
</set>
</property>
</bean>
TheaboveconfigurationusesaSpringFactoryBean implementation, theSetFactoryBean,tocreateajava.util.Setinstanceinitializedwithvaluestakenfromthesupplied'sourceSet'.After...
<!--createsajava.util.Setinstancewithvaluesloadedfromthesupplied
<util:setid="emails">
<value>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </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>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </value>
<value>[email protected] </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
Page 735
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>
Page 736
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>
Page 737
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>
Page 738
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"/>
Page 739
<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>
Page 740
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
Page 741
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
Page 742
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/>
Page 743
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
Page 744
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>
Page 745
</beans>
Inthecaseoftheaboveexample,youwouldassumethatthereissomelogic that will consume the bean definition and set up some cachinginfrastructureusingthesuppliedmetadata.
Page 746
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>
Page 747
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
Page 748
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.
Page 749
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"
Page 750
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
Page 751
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.)
Page 752
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'.
Page 753
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.
Page 754
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.
Page 755
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
Page 756
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.)
Page 757
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.
Page 758
<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.
Page 759
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{
Page 760
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
Page 761
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
Page 762
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.
Page 763
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):
Page 764
http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd
TheupshotofthisisthatyouareencouragedtodeployyourXSDfile(s)right alongside the NamespaceHandler and BeanDefinitionParser classesontheclasspath.
Page 765
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>
Page 766
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();
Page 767
//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{
Page 768
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>
Page 769
</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);
Page 770
}
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
Page 771
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"/>
Page 772
</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){
Page 773
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
Page 774
B.8.FurtherResourcesFindbelow links to further resources concerningXMLSchemaand theextensibleXMLsupportdescribedinthischapter.
TheXMLSchemaPart1:StructuresSecondEdition
TheXMLSchemaPart2:DatatypesSecondEdition
Page 775
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">
-->
Page 776
<!--
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>
<!--
Page 777
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)*
)>
<!--
Page 778
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,
Page 779
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
Page 780
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
Page 781
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>
<!--
Page 782
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.
Page 783
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=".
-->
Page 784
<!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
Page 785
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>
Page 786
<!--
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
Page 787
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
Page 788
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">
Page 789
<!--
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.
-->
Page 790
<!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.
Page 791
-->
<!ELEMENTprop(#PCDATA)>
<!--
Eachpropertyelementmustspecifyitskey.
-->
<!ATTLISTpropkeyCDATA#REQUIRED>
Page 792
D.spring.tld
D.1.IntroductionD.2.ThebindtagD.3.TheescapeBodytagD.4.ThehasBindErrorstagD.5.ThehtmlEscapetagD.6.ThemessagetagD.7.ThenestedPathtagD.8.ThethemetagD.9.Thetransformtag
Page 793
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”
Page 794
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
Page 795
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.
Page 796
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.
Page 797
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.
Page 798
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
Page 799
scope false trueresulttoavariable.Thisattributeisonlyusedwhenvarisalsoset.Possiblevaluesarepage,request,sessionandapplication.
text false true
Defaulttexttooutputwhenamessageforthegivencodecouldnotbefound.Ifbothtextandcodearenotset,thetagwilloutputnull.
var false true
Thestringtousewhenbindingtheresulttothepage,request,sessionorapplicationscope.Ifnotspecified,theresultgetsoutputtedtothewriter(i.e.typicallydirectlytotheJSP).
Page 800
D.7.ThenestedPathtagSetsanestedpathtobeusedbythebindtag'spath.
D.6.Attributes
AttributeRequired? RuntimeExpression?Description
path true true
Setthepaththatthistagshouldapply.E.g.'customer'toallowbindpathslike'address.street'ratherthan'customer.address.street'.
Page 801
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.
Page 802
var false true
Thestringtousewhenbindingtheresulttothepage,request,sessionorapplicationscope.Ifnotspecified,theresultgetsoutputtedtothewriter(i.e.typicallydirectlytotheJSP).
Page 803
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).
Page 804
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
Page 805
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”
Page 806
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
Page 807
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
Page 808
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'
Page 809
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
Page 810
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
Page 811
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path false true Pathtoerrorsobjectfordatabinding
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
Page 812
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'.
Page 813
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
Page 814
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
Page 815
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
Page 816
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
Page 817
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
Page 818
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path true true Pathtoerrorsobjectfordatabinding
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
Page 819
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
Page 820
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
value true true HTMLOptionalAttribute
Page 821
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
Page 822
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
Page 823
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
Page 824
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
Page 825
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
Page 826
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
Page 827
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'
Page 828
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
Page 829
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
Page 830
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
Page 831
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
Page 832
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
Page 833
F.Spring2.5
F.1.F.2.F.3.F.4.
Page 834
F.1.SpringSpring Framework( http://www.redsaga.com)Spring(http://spring.jactiongroup.net)SpringFrameworkApache2.0()Apache2.0
Page 836
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)
Page 837
F.4.20080305312.594521
20080308SpringSpringzhanglongginge24http://wiki.redsaga.com/confluence/pages/viewpage.action?pageId=26792.020080312KxllenJinJavaJoo4538
20080315YuLiminEchoyeshucheng40crazycy18yeshucheng20080319511xmlcvs20080322Denis118420080326451511200803293hanson201088250max2520080402RodJohnson----SpringSourceInfoQ……2112
Page 838
200804052.0XML261220080412Wiki
20080419~Denis20080426Denis2.0CVS2008050345161515CVS200805102.5max123061020080517
20080525
20080601
zhanglong20080608
2008061534568zhanglongpesome2008062245820080630
Page 839
SpringFramework2.54