spring framework ¿ª·¢²Î¿¼ÊÖ²á2. spring 2.0 2.5 2.1. 2.2. (ioc) 2.2.1. bean 2.2.2. xml...
Post on 06-Jun-2020
6 Views
Preview:
TRANSCRIPT
SpringFrameworkRodJohnson
JuergenHoeller
AlefArendsen
ColinSampaleanu
RobHarrop
ThomasRisberg
DarrenDavison
DmitriyKopylenko
MarkPollack
ThierryTemplier
ErwinVervaet
PortiaTung
BenHale
AdrianColyer
JohnLewis
CostinLeau
MarkFisher
SamBrannen
RamnivasLaddad
2.5.2Copiesof thisdocumentmaybemadeforyourownuseandfordistribution toothers,provided
thatyoudonotchargeanyfeeforsuchcopiesandfurtherprovidedthateachcopycontainsthisCopyrightNotice,whetherdistributedinprintorelectronically.
1.1.1.
1.1.1.
2.Spring2.02.52.1.2.2.(IoC)
2.2.1.bean2.2.2.XML2.2.3.XML2.2.4.Annotation()2.2.5.classpath
2.3.(AOP)2.3.1.AOPXML2.3.2.@AspectJ2.3.3.beanpointcut(beannamepointcutelement)2.3.4.AspectJAspectJload-timeweaving
2.4.2.4.1.XML2.4.2.Websphere2.4.3.JPA2.4.4.JMS2.4.5.JDBC
2.5.Web2.5.1.SpringMVC2.5.2.Portlet2.5.3.Annotation2.5.4.SpringMVC2.5.5.Tiles22.5.6.JSF1.22.5.7.JAX-WS
2.6.2.6.1.2.6.2.2.6.3.JMX2.6.4.SpringJCAadapter2.6.5.2.6.6.Java5(Tiger)
2.7.Spring2.52.7.1.
2.8.2.9.
I.
3.IoC()3.1.3.2.-bean
3.2.1.3.2.2.3.2.3.bean3.2.4.
3.3.3.3.1.3.3.2.3.3.3.depends-on3.3.4.bean3.3.5.autowire3.3.6.3.3.7.
3.4.Bean3.4.1.Singleton3.4.2.Prototype3.4.3.Singletonbeansprototype-bean3.4.4.3.4.5.
3.5.bean3.5.1.3.5.2.
3.6.bean3.7.
3.7.1. BeanPostProcessorbean3.7.2. BeanFactoryPostProcessor
3.7.3.FactoryBean3.8.TheApplicationContext
3.8.1.BeanFactory ApplicationContext?3.8.2.MessageSource3.8.3.3.8.4.3.8.5.ApplicationContextWEB
3.9.singleton3.10.J2EERARSpringApplicationContext3.11.Annotation-based
3.11.1.@Autowired3.11.2.3.11.3.CustomAutowireConfigurer3.11.4.@Resource
3.11.5.@PostConstruct @PreDestroy
3.12.Classpath3.12.1.@Component3.12.2.3.12.3.3.12.4.3.12.5.3.12.6.
3.13.LoadTimeWeaver
4.4.1.4.2.Resource4.3. Resource
4.3.1.UrlResource4.3.2.ClassPathResource4.3.3.FileSystemResource4.3.4.ServletContextResource4.3.5.InputStreamResource4.3.6.ByteArrayResource
4.4.ResourceLoader4.5.ResourceLoaderAware4.6. Resource
4.7.Applicationcontext Resource4.7.1.applicationcontext4.7.2.Applicationcontext4.7.3.FileSystemResource
5. BeanWrapper
5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper
5.4.1.5.4.2.PropertyEditor
6.SpringAOP6.1.
6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP
6.2.@AspectJ6.2.1.@AspectJ6.2.2.6.2.3.pointcut6.2.4.6.2.5.Introduction6.2.6.6.2.7.
6.3.SchemaAOP6.3.1.6.3.2.6.3.3.6.3.4.6.3.5.6.3.6.Advisor6.3.7.
6.4.AOP6.4.1.SpringAOPAspectJ6.4.2.SpringAOP@AspectJXML
6.5.6.6.
6.6.1.AOP6.7.@AspectJ6.8.SpringAspectJ
6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW
6.9.
7.SpringAOPAPIs7.1.7.2.SpringAPI
7.2.1.7.2.2.7.2.3.AspectJ7.2.4.7.2.5.7.2.6.
7.3.SpringAPI7.3.1.7.3.2.Spring
7.4.SpringAdvisorAPI7.5.ProxyFactoryBeanAOP
7.5.1.7.5.2.JavaBean7.5.3.JDKCGLIB7.5.4.7.5.5.7.5.6.“”
7.6.7.7.ProxyFactoryAOP7.8.7.9.“autoproxy”
7.9.1.bean7.9.2.
7.10.TargetSource7.10.1.7.10.2.7.10.3.7.10.4.ThreadLocal
7.11.Advice7.12.
8.8.1.8.2.
8.2.1.Mock8.2.2.
8.3.8.3.1.8.3.2.8.3.3.8.3.4.JDBC8.3.5.8.3.6.JUnit3.88.3.7.SpringTestContextFramework8.3.8.PetClinic
8.4.II.
9.9.1.9.2.9.3.9.4.
9.4.1.9.4.2.9.4.3.TransactionAwareDataSourceProxy
9.5.9.5.1.Spring9.5.2.9.5.3.9.5.4.bean9.5.5.<tx:advice/>9.5.6. @Transactional
9.5.7.9.5.8.9.5.9.AspectJ @Transactional
9.6.9.6.1.TransactionTemplate9.6.2.PlatformTransactionManager
9.7.9.8.
9.8.1.IBMWebSphere9.8.2.BEAWebLogic9.8.3.OracleOC4J
9.9.9.9.1. DataSource
9.10.
10.DAO10.1.10.2.10.3.DAO
11.JDBC11.1.
11.1.1.11.1.2.SpringJDBC
11.2.JDBCJDBC11.2.1.JdbcTemplate11.2.2.NamedParameterJdbcTemplate11.2.3.SimpleJdbcTemplate11.2.4.DataSource11.2.5.SQLExceptionTranslator11.2.6.SQL11.2.7.11.2.8.11.2.9.
11.3.11.3.1.DataSourceUtils11.3.2.SmartDataSource11.3.3.AbstractDataSource11.3.4.SingleConnectionDataSource11.3.5.DriverManagerDataSource11.3.6.TransactionAwareDataSourceProxy11.3.7.DataSourceTransactionManager11.3.8.NativeJdbcExtractor
11.4.JDBC11.4.1.JdbcTemplate11.4.2.SimpleJdbcTemplate
11.5.SimpleJdbcJDBC11.5.1.SimpleJdbcInsert11.5.2.SimpleJdbcInsert11.5.3.SimpleJdbcInsert11.5.4.SqlParameterSource11.5.5.SimpleJdbcCall11.5.6.SimpleJdbcCall11.5.7.SqlParameters11.5.8.SimpleJdbcCall11.5.9.SimpleJdbcCallResultSet/REFCursor
11.6.JavaJDBC11.6.1.SqlQuery11.6.2.MappingSqlQuery11.6.3.SqlUpdate11.6.4.StoredProcedure11.6.5.SqlFunction
11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.
12.ORM12.1.12.2.Hibernate
12.2.1.12.2.2.Spring SessionFactory
12.2.3.TheHibernateTemplate12.2.4.SpringDAO12.2.5.Hibernate3APIDAO12.2.6.12.2.7.12.2.8.12.2.9.vs12.2.10.Hibernate
12.3.JDO12.3.1.PersistenceManagerFactory12.3.2.JdoTemplateJdoDaoSupport12.3.3.JDOAPIDAO12.3.4.12.3.5.JdoDialect
12.4.OracleTopLink12.4.1.SessionFactory12.4.2.TopLinkTemplateandTopLinkDaoSupport12.4.3.TopLinkAPIDAO12.4.4.
12.5.iBATISSQLMaps12.5.1.SqlMapClient12.5.2. SqlMapClientTemplate SqlMapClientDaoSupport
12.5.3.iBATISAPIDAO12.6.JPA
12.6.1.SpringJPA12.6.2.JpaTemplate JpaDaoSupport
12.6.3.JPADAO12.6.4.
12.7.12.8.JpaDialect
III.TheWeb
13.WebMVCframeworkWeb13.1.
13.1.1.MVC13.1.2.SpringWebMVC
13.2.DispatcherServlet13.3.
13.3.1.AbstractController WebContentGenerator
13.3.2.13.3.3.MultiActionController13.3.4.
13.4.handlermapping13.4.1.BeanNameUrlHandlerMapping13.4.2.SimpleUrlHandlerMapping13.4.3.HandlerInterceptor
13.5.13.5.1.ViewResolver13.5.2.13.5.3.Rediret
13.6.13.6.1.AcceptHeaderLocaleResolver13.6.2.CookieLocaleResolver13.6.3.SessionLocaleResolver13.6.4.LocaleChangeInterceptor
13.7.13.7.1.13.7.2.13.7.3.
13.8.Springmultipartfileupload13.8.1.13.8.2.MultipartResolver13.8.3.
13.9.Spring13.9.1.13.9.2.form13.9.3.input13.9.4.checkbox13.9.5.checkboxes13.9.6.radiobutton13.9.7.radiobuttons13.9.8.password13.9.9.select
13.9.10.option13.9.11.options13.9.12.textarea13.9.13.hidden13.9.14.errors
13.10.13.11.conventionoverconfiguration
13.11.1. ControllerClassNameHandlerMapping
13.11.2. ModelMapModelAndView
13.11.3. RequestToViewNameTranslator
13.12.13.12.1.dispatcher13.12.2.@Controller13.12.3.@RequestMapping13.12.4.@RequestParam13.12.5.@ModelAttribute13.12.6.@SessionAttributes13.12.7.WebDataBinder
13.13.
14.14.1.14.2.JSPJSTL
14.2.1.14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTL14.2.3.
14.3.Tiles14.3.1.14.3.2.Tiles
14.4.VelocityFreeMarker14.4.1.14.4.2.Context14.4.3.14.4.4.14.4.5.
14.5.XSLT14.5.1.14.5.2.
14.6.PDF/Excel14.6.1.14.6.2.
14.7.JasperReports14.7.1.14.7.2.14.7.3. ModelAndView
14.7.4.14.7.5.Exporter
15.Web15.1.15.2.15.3.JavaServerFaces
15.3.1.DelegatingVariableResolver15.3.2.FacesContextUtils
15.4.Struts15.4.1.ContextLoaderPlugin15.4.2.ActionSupportClasses
15.5.Tapestry15.5.1.Springbeans
15.6.WebWork15.7.
16.PortletMVC16.1.
16.1.1.-MVCC16.1.2.-MVCV16.1.3.WebBean
16.2.DispatcherPortlet16.3.ViewRendererServlet16.4.
16.4.1.AbstractController PortletContentGenerator
16.4.2.16.4.3.Command16.4.4.PortletWrappingController
16.5.16.5.1.PortletModeHandlerMapping16.5.2.ParameterHandlerMapping16.5.3.PortletModeParameterHandlerMapping16.5.4. HandlerInterceptors16.5.5.HandlerInterceptorAdapter16.5.6.ParameterMappingInterceptor
16.6.16.7.Multipart
16.7.1. PortletMultipartResolver
16.7.2.16.8.16.9.Portlet
IV.
17.SpringWeb17.1.17.2.RMI
17.2.1.RmiServiceExporter17.2.2.
17.3.HessianBurlapHTTP17.3.1.Hessianco.DispatcherServlet17.3.2.HessianServiceExporterbean17.3.3.17.3.4.Burlap17.3.5.HessianBurlapHTTPBasic
17.4.HTTP17.4.1.Exposingtheserviceobject17.4.2.
17.5.WebServices17.5.1.JAX-RPCservletweb17.5.2.JAX-RPCweb17.5.3.JAX-RPCBean17.5.4.JAX-RPC17.5.5.JAX-WSservletweb17.5.6.JAX-WSweb17.5.7.SpringJAX-WSRI17.5.8.JAX-WSweb17.5.9.XFireWeb
17.6.JMS17.6.1.17.6.2.
17.7.17.8.
18.EnterpriseJavaBeans(EJB)18.1.18.2.EJB
18.2.1.18.2.2.SessionBean(SLSB)18.2.3.SLSB18.2.4.AccessingEJB2.xSLSBsversusEJB3SLSBs
18.3.SpringEJB18.3.1.EJB2.xbaseclasses18.3.2.EJB3
19.JMS(JavaMessageService)19.1.19.2.SpringJMS
19.2.1.JmsTemplate19.2.2.19.2.3.19.2.4.19.2.5.
19.3.19.3.1.19.3.2.SessionCallback ProducerCallback
19.4.19.4.1.19.4.2.-POJO19.4.3.SessionAwareMessageListener19.4.4.MessageListenerAdapter19.4.5.
19.5.JCA19.6.JMS
20.JMX20.1.20.2.BeanJMX
20.2.1.MBeanServer20.2.2.MBeanServer20.2.3.MBean20.2.4.MBean20.2.5.
20.3.Bean20.3.1.MBeanInfoAssembler20.3.2.20.3.3.JDK5.020.3.4.20.3.5.AutodetectCapableMBeanInfoAssembler20.3.6.Java20.3.7.MethodNameBasedMBeanInfoAssembler
20.4.BeanObjectName20.4.1. PropertiesProperties
20.4.2.MetadataNamingStrategy20.4.3.<context:mbean-export/>
20.5.JSR-16020.5.1.20.5.2.20.5.3.Burlap/Hessian/SOAPJMX
20.6.MBean20.7.
20.7.1.20.7.2.
20.8.
21.JCACCI21.1.21.2.CCI
21.2.1.21.2.2.SpringConnectionFactory21.2.3.CCI21.2.4.CCI
21.3.SpringCCI21.3.1.21.3.2.CciTemplate21.3.3.DAO21.3.4.21.3.5.21.3.6.CCIConnectionInteraction21.3.7.CciTemplate
21.4.CCI21.4.1.MappingRecordOperation21.4.2.MappingCommAreaOperation21.4.3.21.4.4.21.4.5.MappingRecordOperation21.4.6.MappingCommAreaOperation
21.5.
22.Spring22.1.22.2.Spring
22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator
22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.
23.Spring(Scheduling)(ThreadPooling)23.1.23.2.OpenSymphonyQuartz
23.2.1.JobDetailBean23.2.2. MethodInvokingJobDetailFactoryBean
23.2.3.triggersSchedulerFactoryBean23.3.JDKTimer
23.3.1.timers23.3.2. MethodInvokingTimerTaskFactoryBean
23.3.3. TimerFactoryBean
23.4.SpringTaskExecutor23.4.1.TaskExecutor23.4.2.TaskExecutor23.4.3.TaskExecutor
24.24.1.24.2.24.3.bean
24.3.1.24.3.2.JRubybeans24.3.3.Groovybeans24.3.4.BeanShellbeans
24.4.24.4.1.SpringMVC24.4.2.Validator
24.5.Bitsandbobs24.5.1.AOP-bean24.5.2.
24.6.
25.25.1.25.2.Spring25.3.
25.3.1.@Required
25.3.2.Spring@Annotations25.4.JakartaCommonsAttributes25.5.SpringAOP
25.5.1.25.5.2.
V.
26.26.1.26.2.SpringMVC
26.2.1.26.3.SimpleJdbcTemplate@RepositoryDAO
26.3.1.26.3.2.DataAccessObject26.3.3.
A.XMLSchema-basedconfigurationA.1.IntroductionA.2.XMLSchema-basedconfiguration
A.2.1.ReferencingtheschemasA.2.2.TheutilschemaA.2.3.ThejeeschemaA.2.4.ThelangschemaA.2.5.ThejmsschemaA.2.6.Thetx(transaction)schemaA.2.7.TheaopschemaA.2.8.ThecontextschemaA.2.9.ThetoolschemaA.2.10.Thebeansschema
A.3.SettingupyourIDEA.3.1.SettingupEclipseA.3.2.SettingupIntelliJIDEAA.3.3.Integrationissues
B.ExtensibleXMLauthoringB.1.IntroductionB.2.AuthoringtheschemaB.3.CodingaNamespaceHandlerB.4.CodingaBeanDefinitionParserB.5.Registeringthehandlerandtheschema
B.5.1.'META-INF/spring.handlers'B.5.2.'META-INF/spring.schemas'
B.6.UsingacustomextensioninyourSpringXMLconfigurationB.7.Meatierexamples
B.7.1.NestingcustomtagswithincustomtagsB.7.2.Customattributeson'normal'elements
B.8.FurtherResourcesC.spring-beans-2.0.dtdD.spring.tld
D.1.IntroductionD.2.Thebindtag
D.3.TheescapeBodytagD.4.ThehasBindErrorstagD.5.ThehtmlEscapetagD.6.ThemessagetagD.7.ThenestedPathtagD.8.ThethemetagD.9.Thetransformtag
E.spring-form.tldE.1.IntroductionE.2.ThecheckboxtagE.3.ThecheckboxestagE.4.TheerrorstagE.5.TheformtagE.6.ThehiddentagE.7.TheinputtagE.8.ThelabeltagE.9.TheoptiontagE.10.TheoptionstagE.11.ThepasswordtagE.12.TheradiobuttontagE.13.TheradiobuttonstagE.14.TheselecttagE.15.Thetextareatag
F.Spring2.5F.1.F.2.F.3.F.4.
3.1.bean3.2.Autowiringmodes3.3.3.4.Bean3.5.FeatureMatrix3.6.3.7.4.1.Resourcestrings5.1.5.2.PropertyEditors6.1. DefaultContextLoadTimeWeaver
LoadTimeWeaversDefaultContextLoadTimeWeaverLoadTimeWeavers
6.2.aspectj-weaving9.1.<tx:method/>9.2.<tx:annotation-driven/>9.3.@Transactional13.1.WebApplicationContextbean13.2.DispatcherServlet13.3.AbstractController13.4.13.5.CookieLocaleResolver13.6.ThemeResolver14.1.14.2.JasperReportsViewClasses14.3.JasperReportsMultiFormatViewMappingKey16.1.WebApplicationContextBean16.2.DispatcherPortlet16.3.AbstractController19.1.JMSlistener19.2.JMS<listener-container/>19.3.JMS<jca-listener-container/>20.1.20.2.20.3.21.1.UsageofInteractionexecutemethods21.2.UsageofInteractionexecutemethodsA.1.EclipseXMLeditorsD.1.AttributesD.2.AttributesD.3.AttributesD.4.AttributesD.5.AttributesD.6.AttributesD.7.AttributesD.8.AttributesE.1.AttributesE.2.AttributesE.3.AttributesE.4.AttributesE.5.AttributesE.6.AttributesE.7.AttributesE.8.AttributesE.9.Attributes
E.10.AttributesE.11.AttributesE.12.AttributesE.13.AttributesE.14.AttributesF.1.
MVCframework AOP
Spring SpringSpringChristianBauer( Hibernate) DocBook-XSLHibernateHealy
2004MartinFowler” Fowler
IoC
http://martinfowler.com/articles/injection.html
1
1.1.1.1.1.
JavaappletsnJavajavaClasswebClasses
FactoryAbstractFactoryBuilderDecorator ServiceLocator “ ......” wikisSpringIoCclassesSpringSpringFrameworkspringSpring
1.1.Spring
Spring
CoreIoC BeanFactoryFactoryContext() Core:JNDIContextbeansI18Nresourcebundle,servletDAOJDBCJDBCobjectsORM“/”APIs JPAJDOHibernate iBatisORMSpring“/”
Spring AOP AOPAllianceaspect-orientedprogrammingmethod-interceptorspointcutssource-level.NetattributeSpring WebWebServletlistenersIoCWebapplicationcontextWebWorkStrutsSpringSpringSpring MVCWebModel-View-ControllerMVCSpringMVC webformSpring
1.1.1.SpringAppletSpringWeb
SpringWeb
Spring WebEJB POJOSpringIoCemailwebSpringORMJPAHibernateJDOiBatisHibernateHibernateSessionFactoryweb ActionFormsclassHTTP
Spring
Spring Spring WebWorkStrutsTapestryUISpring ApplicationContext WebApplicationContext
WebServiceSpring Hessian-Burlap-Rmi- JaxRpcProxyFactory
EJBs-POJOs
SpringEJB POJOSessionBeanEJBWeb
2Spring2.02.5
2.1.2.2.(IoC)
2.2.1.bean2.2.2.XML2.2.3.XML2.2.4.Annotation()2.2.5.classpath
2.3.(AOP)2.3.1.AOPXML2.3.2.@AspectJ2.3.3.beanpointcut(beannamepointcutelement)2.3.4.AspectJAspectJload-timeweaving
2.4.2.4.1.XML2.4.2.Websphere2.4.3.JPA2.4.4.JMS2.4.5.JDBC
2.5.Web2.5.1.SpringMVC2.5.2.Portlet2.5.3.Annotation2.5.4.SpringMVC2.5.5.Tiles22.5.6.JSF1.22.5.7.JAX-WS
2.6.2.6.1.2.6.2.2.6.3.JMX2.6.4.SpringJCAadapter2.6.5.2.6.6.Java5(Tiger)
2.7.Spring2.52.7.1.
2.8.2.9.
JavaSEJavaEESpringFrameworkJava-Java1.4.2(1.4.2)springJava1.4.2,Java5Java6SpringFramework1.4.2Spring2.5,SpringJava6Spring2.0Java5SpringJ2EE1.3JavaEE5SpringBEAWebLogic 8.1, 9.0, 9.2 10,IBMWebSphere5.1,6.06.1,Oracle OC4J 10.1.3 11,JBoss 3.2, 4.0 4.2,Tomcat4.1,5.0,5.56.0,Jetty4.2,5.16.1,Resin2.1,3.03.1GlassFishV1V2.
2.1.SpringFrameworkSpring:200610Spring2.0,200711Spring2.5
Spring2.02.5SpringSpring2.x
2.2.(IoC)Spring2.0SpringIoC
2.2.1.beanSpringIoCbeanSpring2.0Springwebrequestsessionbean,'''hooks'Springbeans... 3.4“Bean”
2.2.2.XMLXML SchemaXMLSpringXMLSpringSpring A, XMLSchema-basedconfigurationSpring2.0DTDSchemaXMLDOCTYPESpring2.0'dist/resources''spring-beans-2.0.dtd'DTD
<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
2.2.3.XMLXML''SpringDSLdomainspecificlanguage
SpringSpringSpring B,ExtensibleXMLauthoring
2.2.4.Annotation()Spring 2.0 annotation, @Transactional, @Required and@PersistenceContext/@PersistenceUnit.Spring 2.5 Annotation: @AutowiredJSR-250@Resource, @PostConstructand@PreDestroyAnnotationbean 3.11 “Annotation-based” Spring MVCannotation2.5.3“Annotation”
2.2.5.classpathSpring2.5 classpathannotationstereotype: @Component,@Repository,@Service,@Controller.SpringbeanAnnotation-drivenbeanconfigurationisdiscussedin3.12.1“ @Component” .Annotationbean3.12.1“ @Component”
2.3.(AOP)Spring2.0AOPSpringAOPXMLSpring2.0AspectJpointcut@AspectJaspect 6 SpringAOP
2.3.1.AOPXMLSpring2.0Java AspectJadvice“SchemaAOP”
2.3.2.@AspectJSpring2.0@AspectJAspectJSpringAOP!“@AspectJ” @AspectJ
2.3.3.beanpointcut(beannamepointcutelement)Spring 2.5 bean(...)pointcut springbean 6.2.3.1 “PCD”
2.3.4.AspectJAspectJload-timeweavingSpring 2.5AspectJproxyAOP context:load-time-weaverAspectJMETA-INF/aop.xmlAspectJClassLoader(classtransformation)
6.8.4“SpringAspectJLTW”
2.4.
2.4.1.XMLSpring2.01.2.xIoCSpring2.5 context:load-time-weaver
mode="aspectj"
9
2.4.2.WebsphereSpring2.5IBMWebSphereApplicationServer,WebSphere'stransactionmanager.Transactionsuspension(WebSphere UOWManager
APIonWAS6.0.2.19+and6.0.1.9+WebSphere Application ServerSpringSpring 2.5WebSphereUowTransactionManagerPlatformTransactionManagerIBMJTASpring2.5 tx:jta-transaction-manager
IBMWebSphere, PlatformTransactionManager
2.4.3.JPASpring2.0JPASpringJDBCJPA 12.6“JPA” SpringSpring2.5OpenJPAOpenJPA1.0savepoint
2.4.4.JMSSpring2.0SpringJMS JmsTemplateSpring2.0 19.4.2“-POJO” Spring2.5JCA GenericMessageEndpointManagerJMSActionMQJORAMbroker 19.5“JCA”
Spring2.5XMLnamespaceJMSJMSJCAsetup 19.6“JMS”
2.4.5.JDBCSpringJDBC() NamedParameterJdbcTemplateJDBCJDBC
'?'
SimpleJdbcTemplateJava5+(Tiger) JdbcTemplate
Spring2.5 SimpleJdbcTemplate SimpleJdbcCallSimpleJdbcInsert
2.5.WebSpring2.0web Spring2.5controller
2.5.1.SpringMVC... SpringMVCconvention-over-configurationXML ModelAndView 13.11“conventionoverconfiguration” SpringMVC
2.5.2.PortletSpring2.0SpringMVCPorlet 16 PortletMVC
2.5.3.AnnotationSpring 2.5 MVC Annotation(, @RequestMapping,@RequestParam,@ModelAttribute SevletMVCPortletMVCControllerServletPortletAPIServletPortlet
2.5.4.SpringMVCSpringMVCJSP JIRASpringSpring2.0JSPSpringMVCJSPSpringJIRA 13.9“Spring” E,spring-form.tld
2.5.5.Tiles2Spring 2.5 tiles 2,Tiles SpringTiles 1Strutcs 1.xTiles 1 14.3“Tiles”
2.5.6.JSF1.2Spring 2.5 JSF 1.2 DelegatingVariableResolver
SpringBeanFacesELResolver
2.5.7.JAX-WSSpring2.5JAX-WS2.0/2.1Java6JavaEE5JAX-WSJAX-RPCWSDL/SOAPwebserviceJAX-WSwebservice
2.6.Spring2.0/2.5
2.6.1.Spring2.0JavabeanJRubyGroovyBeanShell 24 Spring2.5autowiringJRuby1.0
2.6.2.Spring2.5SpringTestContextFramework,(annotation)JUnit3.8JUnit4.4TestNG
SpringTestContextFrameworkSpring contextmanagementandcaching() ,dependencyinjectionoftestfixturesDI , transactionaltestmanagementrollback
8.3.7“SpringTestContextFramework”
2.6.3.JMXSpringFramework(Notification)MBean MBeanServer
20.7“”
20.2.5“”
Spring2.5 context:mbean-exportbeanSpring @ManagedResource
2.6.4.SpringJCAadapterSpring2.5SpringJCA(JCAresourceadapter)JCARARJ2EE
2.6.5.Spring2.0 23.4“Spring TaskExecutor” TaskExecutorSpringJMSSpring2.5JCA
2.6.6.Java5(Tiger)Spring2.02.5Java5
3.11“Annotation-based”
25.3.1“@ Required”
9.5.6“ @Transactional”
11.2.3“ SimpleJdbcTemplate”
12.6“JPA”
6.2“@AspectJ”
6.8.1“SpringAspectJdomainobject”
2.7.Spring2.5Spring1.2/2.0Spring2.5Spring2.0.xSpring2.5Spring2.5jarJDK1.4.2Spring2.0Spring2.5Java5Spring2.5Spring1.2.xSpringAPISpring2.0Spring1.2.x“deprecated”
Spring 1.2.xXML100%Spring 2.5Spring 1.2.x DTDSpring 2.0(scopes easierAOP transactionconfiguration)Spring2.5jarbugSpring2.5Spring2aspects90%Spring1.2.x1.2.xDTD,10%Spring22.0/2.5DTDXSDSpring2.5XML
2.7.1.SpringFramework2.0 'changelog.txt'
2.7.1.1.JDKSpring2.5JDK1.3Sun2006JDK1.3JDK1.4.2JDK1.3WebSphere4.05.0SpringFramework2.0.7/2.0.8JDK1.3
2.7.1.2.Spring2.5JarSpring2.5SpringWebMVC 'spring.jar'.SpringMVC'spring-webmvc.jar''spring-webmvc-portlet.jar' lib/modulesStruts1.x 'spring-webmvc-struts.jar'
:Spring DispatcherServletSpringWebMVC HessianHTTP DispatcherServlet,'spring-webmvc.jar'( 'spring-webmvc-
portlet/struts.jar')'spring.jar'Spring2.0 'spring-jmx.jar' 'spring-remoting.jar'Spring2.5'spring-context.jar'(JMXHTTP) 'spring-web.jar'
)Spring2.0 'spring-support.jar' 'spring-context-support.jar','spring-portlet.jar' 'spring-webmvc-portlet.jar',SpringWebMVCframework , 'spring-struts.jar' 'spring-webmvc-struts.jar'
Spring2.0'spring-jdo.jar','spring-jpa.jar','spring-hibernate3.jar',
'spring-toplink.jar' 'spring-ibatis.jar'Spring2.5 'spring-
orm.jar'
Spring 2.5 'spring-test.jar' 'spring-mock.jar',test contextframework 'spring-test.jar' 'spring-mock.jar'
Spring2.5 'spring-tx.jar' 'spring-dao.jar''spring-jca.jar'transactionframeworkSpring2.5jarOSGibundleOSGiSpring
2.7.1.3.XMLSpring2.0XSDSpringXMLDTD DTDbeanXSDbeanSpring1.2DTD 'singleton' Spring2.0DTD'singleton'
'scope'bean
2.7.1.4.Deprecated@deprecatedSpring2.0 Spring2.0deprecatedSpringFramework2.0 'changelog.txt'
/Spring2.0ResultReader:RowMapper
BeanFactoryBootstrap:BeanFactoryLocator
2.7.1.5.ApacheOJBSpring2.0SpringApacheOJB SpringModulesApacheOJB
2.7.1.6.iBATISiBATISSQLMaps1.3iBATISSQLMaps1.32.0/2.1
2.7.1.7.HibernateSpring2.5Hibernate2.1Hibernate3.0 Hibernate3.1Hibernate2.13.0Spring2.0.7/2.0.8Hibernate
2.7.1.8.JDOSpring2.5JDO1.0JDO2.0
JDO1.0spring2.0.7/2.0.8JDO1.0
2.7.1.9.UrlFilenameViewControllerSpring2.0 UrlFilenameViewControllerviewrequestUrlFilenameViewControllerSpring1.xSpring2.x SpringWebMVC
UrlFilenameViewControllerJavadocviewnamedetermination
2.8.Spring2.0 Spring[zip|tar.gz]' 26
Spring2.5PetClinicPetPortalSpring2.5Java5autoboxing,varargsJava56SDKPetClinicPetPortalSpring2.5
2.9.SpringSpring2.02.5ArthurLoderSpringFrameworkJavadocs
I.SpringFrameworkSpringFrameworkIoCSpringFrameworkIoCSpringAOPSpringFrameworkAOPJavaAOP80%SpringAspectJ ,AspectJJavaAOPSpringTDDSpring""
3 IoC()
4
5 BeanWrapper
6 SpringAOP
7 SpringAOPAPIs
8
3.IoC()3.1.3.2.-bean
3.2.1.3.2.2.3.2.3.bean3.2.4.
3.3.3.3.1.3.3.2.3.3.3.depends-on3.3.4.bean3.3.5.autowire3.3.6.3.3.7.
3.4.Bean3.4.1.Singleton3.4.2.Prototype3.4.3.Singletonbeansprototype-bean3.4.4.3.4.5.
3.5.bean3.5.1.3.5.2.
3.6.bean3.7.
3.7.1. BeanPostProcessorbean3.7.2. BeanFactoryPostProcessor
3.7.3.FactoryBean3.8.TheApplicationContext
3.8.1.BeanFactory ApplicationContext?3.8.2.MessageSource3.8.3.3.8.4.3.8.5.ApplicationContextWEB
3.9.singleton3.10.J2EERARSpringApplicationContext3.11.Annotation-based
3.11.1.@Autowired3.11.2.3.11.3.CustomAutowireConfigurer3.11.4.@Resource
3.11.5.@PostConstruct @PreDestroy
3.12.Classpath3.12.1.@Component3.12.2.3.12.3.3.12.4.3.12.5.3.12.6.
3.13.LoadTimeWeaver
4.4.1.4.2.Resource4.3. Resource
4.3.1.UrlResource4.3.2.ClassPathResource4.3.3.FileSystemResource4.3.4.ServletContextResource4.3.5.InputStreamResource4.3.6.ByteArrayResource
4.4.ResourceLoader4.5.ResourceLoaderAware4.6. Resource
4.7.Applicationcontext Resource4.7.1.applicationcontext4.7.2.Applicationcontext4.7.3.FileSystemResource
5. BeanWrapper
5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper
5.4.1.5.4.2.PropertyEditor
6.SpringAOP6.1.
6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP
6.2.@AspectJ6.2.1.@AspectJ6.2.2.6.2.3.pointcut6.2.4.6.2.5.Introduction6.2.6.6.2.7.
6.3.SchemaAOP6.3.1.6.3.2.6.3.3.6.3.4.6.3.5.6.3.6.Advisor6.3.7.
6.4.AOP6.4.1.SpringAOPAspectJ6.4.2.SpringAOP@AspectJXML
6.5.6.6.
6.6.1.AOP6.7.@AspectJ6.8.SpringAspectJ
6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW
6.9.
7.SpringAOPAPIs7.1.7.2.SpringAPI
7.2.1.7.2.2.7.2.3.AspectJ7.2.4.7.2.5.7.2.6.
7.3.SpringAPI7.3.1.7.3.2.Spring
7.4.SpringAdvisorAPI7.5.ProxyFactoryBeanAOP
7.5.1.7.5.2.JavaBean7.5.3.JDKCGLIB7.5.4.7.5.5.7.5.6.“”
7.6.7.7.ProxyFactoryAOP7.8.7.9.“autoproxy”
7.9.1.bean7.9.2.
7.10.TargetSource7.10.1.7.10.2.7.10.3.7.10.4.ThreadLocal
7.11.Advice7.12.
8.8.1.8.2.
8.2.1.Mock8.2.2.
8.3.8.3.1.8.3.2.8.3.3.8.3.4.JDBC8.3.5.8.3.6.JUnit3.88.3.7.SpringTestContextFramework8.3.8.PetClinic
8.4.
3IoC()
3.1.3.2.-bean
3.2.1.3.2.2.3.2.3.bean3.2.4.
3.3.3.3.1.3.3.2.3.3.3.depends-on3.3.4.bean3.3.5.autowire3.3.6.3.3.7.
3.4.Bean3.4.1.Singleton3.4.2.Prototype3.4.3.Singletonbeansprototype-bean3.4.4.3.4.5.
3.5.bean3.5.1.3.5.2.
3.6.bean3.7.
3.7.1. BeanPostProcessorbean3.7.2. BeanFactoryPostProcessor
3.7.3.FactoryBean3.8.TheApplicationContext
3.8.1.BeanFactory ApplicationContext?3.8.2.MessageSource3.8.3.3.8.4.3.8.5.ApplicationContextWEB
3.9.singleton3.10.J2EERARSpringApplicationContext3.11.Annotation-based
3.11.1.@Autowired
3.11.2.3.11.3.CustomAutowireConfigurer3.11.4.@Resource3.11.5.@PostConstruct @PreDestroy
3.12.Classpath3.12.1.@Component3.12.2.3.12.3.3.12.4.3.12.5.3.12.6.
3.13.LoadTimeWeaver
BeanFactoryApplicationContext?
BeanFactoryApplicationContext
BeanFactorybeanApplicationContext AOP
ApplicationContext
3.1.Spring(InversionofControlIoC) [1]
org.springframework.beans
org.springframework.contextSpringIoCBeanFactory ApplicationContext
BeanFactory SpringAOP()context (webWebApplicationContext)
BeanFactory ApplicationContext ApplicationContextBeanFactoryBeanFactoryApplicationContext
BeanFactoryApplicationContextApplicationContext
[1]
bean?'bean'''(component) ''(object) Spring(EnterpriseJavaBeans)
3.2.-beanSpring(backbone)SpringIoC beanbeanSpring bean beanbean
3.2.1.
org.springframework.beans.factory.BeanFactorySpringIoC IoCbeanbeanSpring BeanFactoryIoCSpringBeanFactory XmlBeanFactoryXML
SpringIoC
3.2.1.1.SpringIoC
SpringIoCCLASSPATH
IoC4 Resource
XML SpringIoC3.11“Annotation-based” Spring
SpringIoC web)8XML( 3.8.5“ ApplicationContext
WEB” )SpringIoCbeanbean XML<beans/> <bean/>
beanbean DAOStrutsActionHibernate SessionFactoryJMS QueuebeanXML
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanid="..."class="...">
<!--collaboratorsandconfigurationforthisbeangohere-->
</bean>
<beanid="..."class="...">
<!--collaboratorsandconfigurationforthisbeangohere-->
</bean>
<!--morebeandefinitionsgohere-->
</beans>
3.2.2.SpringIoC
ApplicationContextcontext=newClassPathXmlApplicationContext(
newString[]{"services.xml","daos.xml"});
//anApplicationContextisalsoaBeanFactory(viainheritance)
BeanFactoryfactory=context;
3.2.2.1.XMLXMLXML ApplicationContextApplicationContextdefintionreaderbeanSpring
<beans>
<importresource="services.xml"/>
<importresource="resources/messageSource.xml"/>
<importresource="/resources/themeSource.xml"/>
<beanid="bean1"class="..."/>
<beanid="bean2"class="..."/>
</beans>
3 services.xmlmessageSource.xmlthemeSource.xmlbeanservices.xml messageSource.xmlthemeSource.xml‘/’‘/’SpringXML Schema(DTD)XMLbean
3.2.3.beanSpringIoCbeanbean bean(XML <bean/>
bean BeanDefinition
bean
beanbean
beanbean beancollaborators beandependencies .
beanbeanbeanproperties
3.1.bean
class 3.2.3.2“bean”
beanbeanJavaaccountManager
accountService userDao
loginController
beanSpringAOPbean
name 3.2.3.1“bean”
scope 3.4“Bean”
constructorarguments 3.3.1“”
properties 3.3.1“”
autowiringmode 3.3.5“autowire”
dependencycheckingmode 3.3.6“”
lazy-initializationmode 3.3.4“bean”
initializationmethod 3.5.1.1“”
destructionmethod 3.5.1.2“”
beanbean BeanFactoryBeanFactoryDefaultListableBeanFactoryregisterSingleton(..)
3.2.3.1.beanbeanid( ) idIoC
XML idnamebean id XMLIDxmlidXML beanidXMLXMLIDbeanXMLid bean
beanname namename(bean)
3.2.3.1.1.bean
bean id name beanbean beanXML
<aliasname="fromName"alias="toName"/>
beancom.exampleFoo Foo Bar
bean class
com.example.Foo$Bar
$
fromNamebean toName
AXML componentA-dataSourceDataSourcebeanBXMLcomponentB-dataSourcebeanMyAppXML myApp-dataSourcebeanXMLApplicationContextMyAppXML alias
<aliasname="componentA-dataSource"alias="componentB-dataSource"/>
<aliasname="componentA-dataSource"alias="myApp-dataSource"/>
3.2.3.2.beanbean beanbeanbean
XML <bean/> class class(BeanDefinitionClass)( 3.2.3.2.3
“” 3.6“bean” )class bean(new) beanclass)
3.2.3.2.1.
beanSpringclass classIoCJavaBean SpringJavaBean(()beanstyle) JavaBeanSpringXMLbean
<beanid="exampleBean"class="examples.ExampleBean"/>
<beanname="anotherExample"class="examples.ExampleBeanTwo"/>
bean
3.2.3.2.2.
bean class factory-methodbean Spring()
beanbean
<beanid="exampleBean"
class="examples.ExampleBean2"
factory-method="createInstance"/>
bean
3.2.3.2.3.
beanbeanbeanfactory-method
<!--thefactorybean,whichcontainsamethodcalledcreateInstance()
<beanid="serviceLocator"class="com.foo.DefaultServiceLocator">
<!--injectanydependenciesrequiredbythislocatorbean-->
</bean>
<!--thebeantobecreatedviathefactorybean-->
<beanid="exampleBean"
factory-bean="serviceLocator"
factory-method="createInstance"/>
bean bean (DI)
SpringfactorybeanSpring bean FactoryBean
FactoryBean
3.2.4.BeanFactory bean BeanFactory
Resourceres=newFileSystemResource("beans.xml");
BeanFactoryfactory=newXmlBeanFactory(res);
getBean(String)bean BeanFactorygetBean(String) SpringAPI
3.3.Springbean)beanbean
3.3.1.DIbean bean ServiceLocator 3InversionofControlIoC DIbeanDI Setter
3.3.1.1.DI statticbean
publicclassSimpleMovieLister{
//theSimpleMovieListerhasadependencyonaMovieFinder
privateMovieFindermovieFinder;
//aconstructorsothattheSpringcontainercan'inject'a
publicSimpleMovieLister(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
//businesslogicthatactually'uses'theinjectedMovieFinder
}
3.3.1.1.1.
beanbeanbean
packagex.y;
publicclassFoo{
publicFoo(Barbar,Bazbaz){
//...
}
}
Bar Baz
<beans>
<beanname="foo"class="x.y.Foo">
<constructor-arg>
<beanclass="x.y.Bar"/>
</constructor-arg>
<constructor-arg>
<beanclass="x.y.Baz"/>
</constructor-arg>
</bean>
</beans>
beanbean() <value>true<value>Spring
packageexamples;
publicclassExampleBean{
//No.ofyearstothecalculatetheUltimateAnswer
privateintyears;
//TheAnswertoLife,theUniverse,andEverything
privateStringultimateAnswer;
publicExampleBean(intyears,StringultimateAnswer){
this.years=years;
this.ultimateAnswer=ultimateAnswer;
}
}
3.3.1.1.1.1.'type'
<beanid="exampleBean"class="examples.ExampleBean">
<constructor-argtype="int"value="7500000"/>
<constructor-argtype="java.lang.String"value="42"/>
</bean>
Setter?SpringsettersetterDI
DIsetter
3.3.1.1.1.2.index
<beanid="exampleBean"class="examples.ExampleBean">
<constructor-argindex="0"value="7500000"/>
<constructor-argindex="1"value="42"/>
</bean>
2 index0
3.3.1.2.Setterstaticbeanbeansetter setterDIsetter Java
publicclassSimpleMovieLister{
//theSimpleMovieListerhasadependencyontheMovieFinder
privateMovieFindermovieFinder;
//asettermethodsothattheSpringcontainercan'inject'a
publicvoidsetMovieFinder(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
//businesslogicthatactually'uses'theinjectedMovieFinder
}
BeanFactorybeanSetterBeanDefinition PropertyEditor
SpringXMLSpringIoCbean
bean BeanFactorySpringXML BeanFactoryApplicationContext
bean beanbean
bean
beanABBAABbeanSpringIoCBeanCurrentlyInCreationException
settersettersetterbeanbeanbean
SpringString intlongStringboolean
Springbeanbeanbeanbeanbean beansingletonbean ApplicationContextsingletonbeanbeanbeanbeanbeanbeanbeanbeanSpringbeanSpringbeanSpringbeanbean
ApplicationContextbeansingletonbean ApplicationContext
singletonbeanbeanbeanbean beanAbeanBSpringIoCbeanAsetterbeanB beansingletonlifecycle IntializingBeaninitcallback
3.3.1.3.XMLSetterDIXML
<beanid="exampleBean"class="examples.ExampleBean">
<!--setterinjectionusingthenested<ref/>element-->
<propertyname="beanOne"><refbean="anotherExampleBean"/></property>
<!--setterinjectionusingtheneater'ref'attribute-->
<propertyname="beanTwo"ref="yetAnotherBean"/>
<propertyname="integerProperty"value="1"/>
</bean>
<beanid="anotherExampleBean"class="examples.AnotherBean"/>
<beanid="yetAnotherBean"class="examples.YetAnotherBean"/>
publicclassExampleBean{
privateAnotherBeanbeanOne;
privateYetAnotherBeanbeanTwo;
privateinti;
publicvoidsetBeanOne(AnotherBeanbeanOne){
this.beanOne=beanOne;
}
publicvoidsetBeanTwo(YetAnotherBeanbeanTwo){
this.beanTwo=beanTwo;
}
publicvoidsetIntegerProperty(inti){
this.i=i;
}
}
beansetterxml
<beanid="exampleBean"class="examples.ExampleBean">
<!--constructorinjectionusingthenested<ref/>element-->
<constructor-arg>
<refbean="anotherExampleBean"/>
</constructor-arg>
<!--constructorinjectionusingtheneater'ref'attribute-->
<constructor-argref="yetAnotherBean"/>
<constructor-argtype="int"value="1"/>
</bean>
<beanid="anotherExampleBean"class="examples.AnotherBean"/>
<beanid="yetAnotherBean"class="examples.YetAnotherBean"/>
publicclassExampleBean{
privateAnotherBeanbeanOne;
privateYetAnotherBeanbeanTwo;
privateinti;
publicExampleBean(
AnotherBeananotherBean,YetAnotherBeanyetAnotherBean,inti){
this.beanOne=anotherBean;
this.beanTwo=yetAnotherBean;
this.i=i;
}
}
xmlbean ExampleBean
static
<beanid="exampleBean"class="examples.ExampleBean"
factory-method="createInstance">
<constructor-argref="anotherExampleBean"/>
<constructor-argref="yetAnotherBean"/>
<constructor-argvalue="1"/>
</bean>
<beanid="anotherExampleBean"class="examples.AnotherBean"/>
<beanid="yetAnotherBean"class="examples.YetAnotherBean"/>
publicclassExampleBean{
//aprivateconstructor
privateExampleBean(...){
...
}
//astaticfactorymethod;theargumentstothismethodcanbe
//consideredthedependenciesofthebeanthatisreturned,
//regardlessofhowthoseargumentsareactuallyused.
publicstaticExampleBeancreateInstance(
AnotherBeananotherBean,YetAnotherBeanyetAnotherBean,inti){
ExampleBeaneb=newExampleBean(...);
//someotheroperations...
returneb;
}
}
staticconstructor-arg static factory-bean
class
3.3.2.beanbeaninlinebeanspringXML <property/><constructor-arg/>
3.3.2.1.( Strings)<value/> JavaBean PropertyEditorjava.lang.String
<beanid="myDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<!--resultsinasetDriverClassName(String)call-->
<propertyname="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<propertyname="url">
<value>jdbc:mysql://localhost:3306/mydb</value>
</property>
<propertyname="username">
<value>root</value>
</property>
<propertyname="password">
<value>masterkaoli</value>
</property>
</bean>
<property/><constructor-arg/>'value'
<beanid="myDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<!--resultsinasetDriverClassName(String)call-->
<propertyname="driverClassName"value="com.mysql.jdbc.Driver"/>
<propertyname="url"value="jdbc:mysql://localhost:3306/mydb"/>
<propertyname="username"value="root"/>
<propertyname="password"value="masterkaoli"/>
</bean>
Spring <value/>value java.util.Properties
<beanid="mappings"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<!--typedasajava.util.Properties-->
<propertyname="properties">
<value>
jdbc.driver.className=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/mydb
</value>
</property>
</bean>
SpringJavaBean PropertyEditor<value/>java.util.Properties
Spring <value/>value
3.3.2.1.1.idref
idrefbeanid<constructor-arg/> <property/>
<beanid="theTargetBean"class="..."/>
<beanid="theClientBean"class="...">
<propertyname="targetName">
<idrefbean="theTargetBean"/>
</property>
</bean>
bean
<beanid="theTargetBean"class="..."/>
<beanid="client"class="...">
<propertyname="targetName"value="theTargetBean"/>
</bean>
idrefbean clientbeantargetName clientbeanclientbean prototypebeanbeanXMLbeanbean idlocalXMLXMLbean
<propertyname="targetName">
<!--abeanwithanidof'theTargetBean'mustexist;otherwiseanXMLexceptionwillbethrown-->
<idreflocal="theTargetBean"/>
</property>
ProxyFactoryBeanbean<idref/>AOPinterceptor<idref/>ID
3.3.2.2.bean<constructor-arg/><property/>refbeanbeanbeansingletonbeanid/name<ref/>beanbeanbeanXMLXML' bean'bean idname
<refbean="someBean"/>
reflocalbeanXMLbean localbeanidbeanXMLbeanlocal
<reflocal="someBean"/>
refparentbean parentbeanid namebeanparentbeanbean(beanbean)
<!--intheparentcontext-->
<beanid="accountService"class="com.foo.SimpleAccountService">
<!--insertdependenciesasrequiredashere-->
</bean>
<!--inthechild(descendant)context-->
<beanid="accountService"<--noticethatthenameofthisbeanisthe
class="org.springframework.aop.framework.ProxyFactoryBean">
<propertyname="target">
<refparent="accountService"/><--noticehowwerefertothe
</property>
<!--insertotherconfigurationanddependenciesasrequiredashere-->
</bean>
3.3.2.3.beanbeaninnerbeanbean <property/> <constructor-arg/><bean/>beanbeanidnameidname
<beanid="outer"class="...">
<!--insteadofusingareferencetoatargetbean,simplydefinethetargetbeaninline-->
<propertyname="target">
<beanclass="com.example.Person"><!--thisistheinnerbean-->
<propertyname="name"value="FionaApple"/>
<propertyname="age"value="25"/>
</bean>
</property>
</bean>
bean scopeidnamebean prototypebeanbeanbean
3.3.2.4.<list/><set/><map/><props/>JavaCollectionListSetMapProperties
<beanid="moreComplexObject"class="example.ComplexObject">
<!--resultsinasetAdminEmails(java.util.Properties)call-->
<propertyname="adminEmails">
<props>
<propkey="administrator">administrator@example.org</prop>
<propkey="support">support@example.org</prop>
<propkey="development">development@example.org</prop>
</props>
</property>
<!--resultsinasetSomeList(java.util.List)call-->
<propertyname="someList">
<list>
<value>alistelementfollowedbyareference</value>
<refbean="myDataSource"/>
</list>
</property>
<!--resultsinasetSomeMap(java.util.Map)call-->
<propertyname="someMap">
<map>
<entry>
<key>
<value>anentry</value>
</key>
<value>justsomestring</value>
</entry>
<entry>
<key>
<value>aref</value>
</key>
<refbean="myDataSource"/>
</entry>
</map>
</property>
<!--resultsinasetSomeSet(java.util.Set)call-->
<propertyname="someSet">
<set>
<value>justsomestring</value>
<refbean="myDataSource"/>
</set>
</property>
</bean>
mapkeyvaluesetvalue
bean|ref|idref|list|set|map|props|value|null
3.3.2.4.1.
2.0SpringIoC parent-stylechild-style<list/><map/><set/><props/>
parent-childbeanbean 3.6“bean”
Findbelowanexampleofthecollectionmergingfeature:
<beans>
<beanid="parent"abstract="true"class="example.ComplexObject">
<propertyname="adminEmails">
<props>
<propkey="administrator">administrator@example.com</prop>
<propkey="support">support@example.com</prop>
</props>
</property>
</bean>
<beanid="child"parent="parent">
<propertyname="adminEmails">
<!--themergeisspecifiedonthe*child*collectiondefinition-->
<propsmerge="true">
<propkey="sales">sales@example.com</prop>
<propkey="support">support@example.co.uk</prop>
</props>
</property>
</bean>
<beans>
childbeanadminEmails<props/>merge=true childbeanadminEmailsadminEmails
administrator=administrator@example.com
sales=sales@example.com
support=support@example.co.uk
beanProperties<props/>bean support
<list/><map/><set/> <list/> List beanbean MapSet
Properties MapSetProperties
Spring 2.0 map list Exceptionmergebeanbeanmerge
3.3.2.4.2.(Java5+)
Java5Java6() StringCollectionSpringbeanCollectionSpringCollection
publicclassFoo{
privateMap<String,Float>accounts;
publicvoidsetAccounts(Map<String,Float>accounts){
this.accounts=accounts;
}
}
<beans>
<beanid="foo"class="x.y.Foo">
<propertyname="accounts">
<map>
<entrykey="one"value="9.99"/>
<entrykey="two"value="2.75"/>
<entrykey="six"value="3.99"/>
</map>
</property>
</bean>
</beans>
foobeanaccounts Map<String, Float>Springvalue Float 9.99
2.753.99Float
3.3.2.5.Nulls<null/>nullSpring xmlemail
<beanclass="ExampleBean">
<propertyname="email"><value/></property>
</bean>
Java exampleBean.setEmail("")null<null>
<beanclass="ExampleBean">
<propertyname="email"><null/></property>
</bean>
Java exampleBean.setEmail(null)
3.3.2.6.XML“” <property/>bean
3.3.2.6.1.XML-basedconfigurationmetadatashortcuts
<property/><constructor-arg/><entry/>valueattribute <value/>
<propertyname="myProperty">
<value>hello</value>
</property>
<constructor-arg>
<value>hello</value>
</constructor-arg>
<entrykey="myKey">
<value>hello</value>
</entry>
<propertyname="myProperty"value="hello"/>
<constructor-argvalue="hello"/>
<entrykey="myKey"value="hello"/>
The <property/> and <constructor-arg/> elements support a similarshortcut'ref'attributewhichmaybeusedinsteadofafullnested<ref/>element.Therefore,thefollowing:<property/><constructor-arg/>ref <ref/>
<propertyname="myProperty">
<refbean="myBean">
</property>
<constructor-arg>
<refbean="myBean">
</constructor-arg>
<propertyname="myProperty"ref="myBean"/>
<constructor-argref="myBean"/>
<refbean="xxx"> <reflocal="xxx">xmlbeanmapentry key/key-ref value/value-ref
<entry>
<key>
<refbean="myKeyBean"/>
</key>
<refbean="myValueBean"/>
</entry>
<entrykey-ref="myKeyBean"value-ref="myValueBean"/>
<refbean="xxx"> <reflocal="xxx">
3.3.2.6.2.p
XML""p2.0Spring XMLSchema beanXMLSchemaXSDSpringpschema <property/>beanp bean
attributebeanpropertyXMLbeanXMLp
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanname="classic"class="com.example.ExampleBean">
<propertyname="email"value="foo@bar.com/>
</bean>
<beanname="p-namespace"class="com.example.ExampleBean"
p:email="foo@bar.com"/>
</beans>
beanpemailSpringbeanpropertypschemaattributebeanpropertyThisnextexample includes twomorebeandefinitions thatbothhavea
referencetoanotherbean:beanbean
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanname="john-classic"class="com.example.Person">
<propertyname="name"value="JohnDoe"/>
<propertyname="spouse"ref="jane"/>
</bean>
<beanname="john-modern"
class="com.example.Person"
p:name="JohnDoe"
p:spouse-ref="jane"/>
<beanname="jane"class="com.example.Person">
<propertyname="name"value="JaneDoe"/>
</bean>
</beans>
Asyoucansee,thisexampledoesn'tonlyincludeapropertyvalueusingthe p-namespace, but also uses a special format to declare propertyreferences. Whereas the first bean definition uses <property
name="spouse" ref="jane"/> to create a reference from bean john tobean jane, the second bean definition uses p:spouse-ref="jane" as anattributetodotheexactsamething.Inthiscase'spouse' isthepropertynamewhereasthe'-ref'partindicatesthatthisisnotastraightvaluebutratherareferencetoanotherbean.ppropertybean <propertyname="spouse"ref="jane"/>beanjohnbeanjanebean p:spouse-ref="jane"attribute" spouse"property" -ref“bean
pXMLbean RefpXML
3.3.2.7.bean nullbean
<beanid="foo"class="foo.Bar">
<propertyname="fred.bob.sammy"value="123"/>
</bean>
foo beanfred bob bobsammy sammy123 foofredfredbobbeanNullPointerException
3.3.3. depends-on
beanbeanbeanbeanxml <ref/>bean depends-on
beanbean depends-onbean
<beanid="beanOne"class="ExampleBean"depends-on="manager"/>
<beanid="manager"class="ManagerBean"/>
bean 'depends-on'bean 'depends-on'bean
<beanid="beanOne"class="ExampleBean"depends-on="manager,accountDao">
<propertyname="manager"ref="manager"/>
</bean>
<beanid="manager"class="ManagerBean"/>
<beanid="accountDao"class="x.y.jdbc.JdbcAccountDao"/>
“depends-on” singletonbean depends-onbeanbean
3.3.4.beanApplicationContextsingleton bean ApplicationContextsingleton
beansingletonbean ApplicationContextbeanbeanIoC
XML <bean/>lazy-init
<beanid="lazy"class="com.foo.ExpensiveToCreateBean"lazy-init="true"
<beanname="not.lazy"class="com.foo.AnotherBean"/>
ApplicationContext lazybeanApplicationContext not.lazy
beansingletonbean ApplicationContextsingletonbeansingletonbeanbeanIocbeanbeansingletonbean<beans/>'default-lazy-init'
<beansdefault-lazy-init="true">
<!--nobeanswillbepre-instantiated...-->
</beans>
3.3.5.autowireSpringIoCautowire beanSpring BeanFactorybeanbeanautowireautowirebeanbeanautowirebeanautowire
[2]xml <bean/>autowire:
3.2.Autowiringmodes
no
byName beanbeanautowirebynamebean master setMaster(..)Springmasterbeanmaster
byType beanbean byTypebean dependency-check="objects"
Spring
constructor byTypebean
autodetect beanintrospection constructorbyType byType
propertyconstructor-arg StringClass byTypeconstructor key StringMapMapvaluebeanMapkeybean
bean
javajava
SpringSpring
SpringbeansetterMapbeanbean'autowire-candidate''false'beanbean 'primary''true'beanbeanJava5bean2bean
3.3.5.1.beanbeanXMLbean <bean/> autowire-candidatefalsebeanbean <beans/>'default-autowire-candidates' 'Repository'bean"*Repository“bean'false'
beanbeanbeanbeanbean
3.3.6.Springbeanbeanbeanbeanbean notxmlbeandependency-check
3.3.
none bean
simple
object
all
Java5annotations 25.3.1“@ Required”
3.3.7.bean singletonsingletonbeansingletonbeansingletonbeansingletonbeanbeanbeanpropertybeansingletonbeanAsingletonprototypebeanBbeanAbeanAbeanB
BeanFactoryAware beanAbean getBean("B") beanB
//aclassthatusesastatefulCommand-styleclasstoperformsomeprocessing
packagefiona.apple;
//lotsofSpring-APIimports
importorg.springframework.beans.BeansException;
importorg.springframework.beans.factory.BeanFactory;
importorg.springframework.beans.factory.BeanFactoryAware;
publicclassCommandManagerimplementsBeanFactoryAware{
privateBeanFactorybeanFactory;
publicObjectprocess(MapcommandState){
//grabanewinstanceoftheappropriateCommand
Commandcommand=createCommand();
//setthestateonthe(hopefullybrandnew)Commandinstance
command.setState(commandState);
returncommand.execute();
}
//theCommandreturnedherecouldbeanimplementationthatexecutesasynchronously,orwhatever
protectedCommandcreateCommand(){
return(Command)this.beanFactory.getBean("command");
}
publicvoidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException{
this.beanFactory=beanFactory;
……Tapestry 4.0 abstract
TapestryBlog
}
}
SpringFrameworkSpringIoC
3.3.7.1.LookupLookupbeanbeanLookupbeanLookupSpringCGLIBLookupbeanLookup(CommandManager)SpringcreateCommand() CommandManager
Spring
packagefiona.apple;
//nomoreSpringimports!
publicabstractclassCommandManager{
publicObjectprocess(ObjectcommandState){
//grabanewinstanceoftheappropriateCommandinterface
Commandcommand=createCommand();
//setthestateonthe(hopefullybrandnew)Commandinstance
command.setState(commandState);
returncommand.execute();
}
//okay...butwhereistheimplementationofthismethod?
protectedabstractCommandcreateCommand();
}
( CommandManager)
<public|protected>[abstract]<return-type>theMethodName(no-arguments
<!--astatefulbeandeployedasaprototype(non-singleton)-->
<beanid="command"class="fiona.apple.AsyncCommand"scope="prototype">
<!--injectdependencieshereasrequired-->
</bean>
<!--commandProcessorusesstatefulCommandHelper-->
<beanid="commandManager"class="fiona.apple.CommandManager">
<lookup-methodname="createCommand"bean="command"/>
</bean>
commandManagerbeancommandbean createCommand
commandprototype singleton commandbeanCGLIBjarclasspathSpring final final
bean(serialized)
S
erviceLocatorFactoryBean( org.springframework.beans.factory.config
) ObjectFactoryCreatingFactoryBeanlookupSpringlookup ObjectFactoryServiceLocatorFactoryBean
Javadocs( Spring)
3.3.7.2.LookupbeanXMLbean replaced-methodcomputeValue
publicclassMyValueCalculator{
publicStringcomputeValue(Stringinput){
//somerealcode...
}
//someothermethods...
}
org.springframework.beans.factory.support.MethodReplacer
/**meanttobeusedtooverridetheexistingcomputeValue(String)
implementationinMyValueCalculator
*/
publicclassReplacementComputeValueimplementsMethodReplacer{
publicObjectreimplement(Objecto,Methodm,Object[]args)throwsThrowable{
//gettheinputvalue,workwithit,andreturnacomputedresult
Stringinput=(String)args[0];
...
return...;
}
}
bean
<beanid="myValueCalculatorclass="x.y.z.MyValueCalculator">
<!--arbitrarymethodreplacement-->
<replaced-methodname="computeValue"replacer="replacementComputeValue">
<arg-type>String</arg-type>
</replaced-method>
</bean>
<beanid="replacementComputeValue"class="a.b.c.ReplacementComputeValue"/>
<replaced-method/><arg-type/>overrideoverloadjava.lang.String
java.lang.String
String
Str
[2]3.3.1“”
3.4.Beanbeanbean “(recipe)” beanclass“”JavaClassSpringFrameworkwebSpringApplicationContext
3.4.Bean
singleton SpringIoCbean
prototype bean
request HTTPbeanHTTPbean beanwebSpring
session HTTPSessionbeanwebSpring ApplicationContext
globalsession
HTTPSessionbeanportletcontextwebSpring ApplicationContext
3.4.1.Singletonbeansingleton,SpringIoCbeanbeanidbeanbeanbeansingltonSpringIoCbean singletoncache bean
Springsingleton bean“”GoFSingletonGoF SingletonClassLoaderclassSpringsingletoncontainerbeanSpringclassbeanSpring bean SingletonSpringXMLbeansingleton
<beanid="accountService"class="com.foo.DefaultAccountService"/>
<!--thefollowingisequivalent,thoughredundant(singletonscopeisthedefault);using
<beanid="accountService"class="com.foo.DefaultAccountService"scope="singleton"/>
<!--thefollowingisequivalentandpreservedforbackwardcompatibilityin
<beanid="accountService"class="com.foo.DefaultAccountService"singleton="true"/>
3.4.2.PrototypePrototypebeanbeanbean getBean() beanbeanprototypebeansingletonSpringprototype DAOprototypeDAOsingleton
XMLbeanprototype
<!--usingspring-beans-2.0.dtd
<beanid="accountService"class="com.foo.DefaultAccountService"scope="prototype"/>
<!--thefollowingisequivalentandpreservedforbackwardcompatibilityin
<beanid="accountService"class="com.foo.DefaultAccountService"singleton="false"/>
prototypebeanSpringprototypebeanprototypeprototypeprototypeSpringprototypebean beanbeanprototypebeanSpringJava new 3.5.1“” Springbean
3.4.3.Singletonbeansprototype-beanprototypebeansingleton-scopedbean prototype-scopedbeansingleton-scopedbeanprototypebeansingletonbean...scopedbeanprototypesingleton-scopedbeanprototype-scopedbeanprototype-scopedbeansingletonbeanSpringsingletonbean(prototype)bean
3.3.7“”
XMLbean'spring-beans.dtd'DTD bean") 'spring-beans-2.0.dtd'DTDSpring2.0XSDschema" scope"(" singleton" DTDXSD" scope")" singleton" 'spring-beans.dtd'DTD " scope"'spring-beans-2.0.dtd'DTD 'spring-beans-2.0.xsd'XSD
3.4.4.requestsessionglobalsessionwebweb
webSpringApplicationContext XmlWebApplicationContext
Spring IoC XmlBeanFactory
ClassPathXmlApplicationContext IllegalStateException
bean
3.4.4.1.webrequestsessionglobalsessionbeanwebbean bean“”singletonprototypeservlet...SpringWebMVCSpring DispatcherServletDispatcherPortlet
DispatcherServlet DispatcherPortlet
Spring'sDispatcherServletServlet2.4WebJSFStrutsWeb 'web.xml'
javax.servlet.ServletRequestListener
<web-app>
...
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
...
</web-app>
webServlet2.4 javax.servlet.Filterweb.xml
<web-app>
..
<filter>
<filter-name>requestContextFilter</filter-name>
<filter-class>org.springframework.web.filter.RequestContextFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>requestContextFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
...
</web-app>
RequestContextListenerRequestContextFilter HTTPrequestrequestsessionbean
3.4.4.2.Requestbean
<beanid="loginAction"class="com.foo.LoginAction"scope="request"/>
HTTPSpring loginActionbeanLoginActionbean loginActionbeanHTTPrequest loginAction
3.4.4.3.Sessionbean
<beanid="userPreferences"class="com.foo.UserPreferences"scope="session"/>
HTTP SessionSpringuserPreferences beanuserPreferences beanuserPreferencesbeanHTTPSession requestHTTP Session
userPreferences HTTP Session HTTPbean
3.4.4.4.globalsessionbean
<beanid="userPreferences"class="com.foo.UserPreferences"scope="globalSession"/>
globalsessionHTTPSessionportletwebPortlet Sessionportletwebportlet globalsessionbeanportletSessionServletweb globalsessionbeanHTTP Session
3.4.4.5.beanHTTPrequestSession beanSpringIoCbeanHttprequestbeanbeanAOPbeanHTTPrequest
<aop:scoped-proxy/>singletonprototypebeansingletonbeanscopedproxy BeanCreationException
bean“ ”“ ”
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--aHTTPSession-scopedbeanexposedasaproxy-->
<beanid="userPreferences"class="com.foo.UserPreferences"
<!--thisnextelementeffectstheproxyingofthesurroundingbean-->
<aop:scoped-proxy/>
</bean>
<!--asingleton-scopedbeaninjectedwithaproxytotheabovebean
<beanid="userService"class="com.foo.SimpleUserService">
<!--areferencetotheproxied
'userPreferences'
<propertyname="userPreferences"ref="userPreferences"/>
</bean>
</beans>
Bean <aop:scoped-proxy/>(classpathCGLIB
Schema-based configuration) request,session, globalSession ' '<aop:scoped-proxy/>( 'userPreferences'Bean):
<beanid="userPreferences"class="com.foo.UserPreferences"scope="session"/>
<beanid="userManager"class="com.foo.UserManager">
<propertyname="userPreferences"ref="userPreferences"/>
</bean>
singleton bean userManagerHTTP Sessionbean userPreferencessingletonuserManagerbean userPreferencesbean userManager
userPreferencesbeanHTTP Sessionbean userManagerHTTPSessionHTTP SessionuserPreferences
UserPreferences UserPreferencesHTTP request Session
UserPreferences userManagerbean, userManager
UserPreferences UserManagerUserPreferencesHTTP Session
UserPreferences UserPreferences
request-,session-, globalSession-scopedbeans
<beanid="userPreferences"class="com.foo.UserPreferences"scope="session">
<aop:scoped-proxy/>
</bean>
<beanid="userManager"class="com.foo.UserManager">
<propertyname="userPreferences"ref="userPreferences"/>
</bean>
3.4.4.5.1.
bean <aop:scoped-proxy/>SpringCGLIBCGLIBpublic public<aop:scoped-proxy/>' proxy-target-class'' false'JDKclasspath
bean
<!--DefaultUserPreferences
<beanid="userPreferences"class="com.foo.DefaultUserPreferences"scope="session">
<aop:scoped-proxyproxy-target-class="false"
/>
</bean>
<beanid="userManager"class="com.foo.UserManager">
<propertyname="userPreferences"ref="userPreferences"/>
</bean>
6.6“”
3.4.5.Spring 2.0SpringbeanSpringbean singleton
prototype
3.4.5.1.org.springframework.beans.factory.config.ScopeSpringSpringScope ScopeJavadoc
Scope''Sessionsession-scopedbean(Session)
Objectget(Stringname,ObjectFactoryobjectFactory)
sessionsessionsession-scopedbean(null)
Objectremove(Stringname)
JavadocSpringScope
voidregisterDestructionCallback(Stringname,RunnabledestructionCallback)
The lastmethod dealswith obtaining the conversation identifier for theunderlyingscope.Thisidentifierisdifferentforeachscope.Forasessionforexample,thiscanbethesessionidentifier.sessionsession
StringgetConversationId()
3.4.5.2.ScopeSpring ScopeSpring ConfigurableBeanFactory
voidregisterScope(StringscopeName,Scopescope);
registerScope(..) Spring'singleton''prototype'registerScope(..)ScopeScope
//note:theThreadScope
ScopecustomScope=newThreadScope();
beanFactory.registerScope("thread",scope);
<beanid="..."class="..."scope="thread"/>
CustomScopeConfigurer
CustomScopeConfigurer
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<beanclass="org.springframework.beans.factory.config.CustomScopeConfigurer">
<propertyname="scopes">
<map>
<entrykey="thread">
<beanclass="com.foo.ThreadScope"/>
</entry>
</map>
</property>
</bean>
<beanid="bar"class="x.y.Bar"scope="thread">
<propertyname="name"value="Rick"/>
<aop:scoped-proxy/>
</bean>
<beanid="foo"class="x.y.Foo">
<propertyname="bar"ref="bar"/>
</bean>
</beans>
3.5.bean
3.5.1.Springmarkerinterfacebean InitializingBeanDisposableBean
bean afterPropertiesSet() destroy()
SpringBeanPostProcessor BeanPostProcessor3.7“”
Springbeanbean
3.5.1.1.org.springframework.beans.factory.InitializingBeanbean
InitializingBean
voidafterPropertiesSet()throwsException;
InitializingBeanSpringBeanXML init-method
<beanid="exampleInitBean"class="examples.ExampleBean"init-method="init"/>
publicclassExampleBean{
publicvoidinit(){
//dosomeinitializationwork
}
}
......
<beanid="exampleInitBean"class="examples.AnotherExampleBean"/>
publicclassAnotherExampleBeanimplementsInitializingBean{
publicvoidafterPropertiesSet(){
//dosomeinitializationwork
}
}
...Spring
3.5.1.2.org.springframework.beans.factory.DisposableBeanbeanbean
DisposableBean
voiddestroy()throwsException;
DisposableBeanSpringbeanXML destroy-method
<beanid="exampleInitBean"class="examples.ExampleBean"destroy-method="cleanup"/>
publicclassExampleBean{
publicvoidcleanup(){
//dosomedestructionwork(likereleasingpooledconnections)
}
}
......
<beanid="exampleInitBean"class="examples.AnotherExampleBean"/>
publicclassAnotherExampleBeanimplementsDisposableBean{
publicvoiddestroy(){
//dosomedestructionwork(likereleasingpooledconnections)
}
}
...Spring
3.5.1.3.SpringInitializingBeanDisposableBean init()
initialize()dispose()
Spring bean init() XMLbean 'init-method="init"'
SpringIoCbean
publicclassDefaultBlogServiceimplementsBlogService{
privateBlogDaoblogDao;
publicvoidsetBlogDao(BlogDaoblogDao){
this.blogDao=blogDao;
}
//thisis(unsurprisingly)theinitializationcallbackmethod
publicvoidinit(){
if(this.blogDao==null){
thrownewIllegalStateException("The[blogDao]propertymustbeset.");
}
}
}
<beansdefault-init-method="init">
<beanid="blogService"class="com.foo.DefaultBlogService">
<propertyname="blogDao"ref="blogDao"/>
</bean>
</beans>
<beans/>'default-init-method'SpringIoCbean 'init'
(XML) <beans/> 'default-destroy-method'bean
<bean/>'init-method''destroy-method'(XML)SpringbeanbeanAOPbean AOPbeanbeanbean/bean
3.5.1.4.As of Spring 2.5, there are three options for controlling bean lifecyclebehavior: the InitializingBean and DisposableBean callback interfaces;custom init() and destroy() methods; and the @PostConstruct and
@PreDestroyannotations.Spring2.5bean InitializingBeanDisposableBean; init() destroy()
; @PostConstruct@PreDestroyannotations.
--@PostConstruct
InitializingBeanafterPropertiesSet()
init()
:@PreDestroy
DisposableBeandestroy()
destroy()
bean -
3.5.1.5.webSpringIoC
webApplicationContextwebSpringIoCwebSpringIoCsingletonbeanJVM“”shutdownhookSpringIoC“” AbstractApplicationContextregisterShutdownHook()
importorg.springframework.context.support.AbstractApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
publicfinalclassBoot{
publicstaticvoidmain(finalString[]args)throwsException{
AbstractApplicationContextctx
=newClassPathXmlApplicationContext(newString[]{"beans.xml"});
//addashutdownhookfortheabovecontext...
ctx.registerShutdownHook();
//apprunshere...
//mainmethodexits,hookiscalledpriortotheappshuttingdown...
}
}
3.5.2.3.5.2.1.BeanFactoryAwareorg.springframework.beans.factory.BeanFactoryAwareBeanFactoryBeanFactory
publicinterfaceBeanFactoryAware{
voidsetBeanFactory(BeanFactorybeanFactory)throwsBeansException;
}
beanBeanFactoryBeanFactorycastBeanFactorybeanSpringbeanBeanFactoryAware
org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean
Spring BeanFactoryAwareIoCObjectFactoryCreatingFactoryBeanFactoryBeanbean
ObjectFactoryCreatingFactoryBeanBeanFactoryAwarebeanObjectFactorySpringSpring ObjectFactorygetObject()bean
ObjectFactoryBeanFactorybeanObjectFactoryCreatingFactoryBeanbean
packagex.y;
publicclassNewsFeed{
privateStringnews;
publicvoidsetNews(Stringnews){
this.news=news;
}
publicStringgetNews(){
returnthis.toString()+":'"+news+"'";
}
}
packagex.y;
importorg.springframework.beans.factory.ObjectFactory;
publicclassNewsFeedManager{
privateObjectFactoryfactory;
publicvoidsetFactory(ObjectFactoryfactory){
this.factory=factory;
}
publicvoidprintNews(){
//hereiswherethelookupisperformed;notethatthereisno
//needtohardcodethenameofthebeanthatisbeinglookedup...
NewsFeednews=(NewsFeed)factory.getObject();
System.out.println(news.getNews());
}
}
XML
<beans>
<beanid="newsFeedManager"class="x.y.NewsFeedManager">
<propertyname="factory">
<bean
class="org.springframework.beans.factory.config.ObjectFactoryCreatingFactoryBean">
<propertyname="targetBeanName">
<idreflocal="newsFeed"/>
</property>
</bean>
</property>
</bean>
<beanid="newsFeed"class="x.y.NewsFeed"scope="prototype">
<propertyname="news"value="...that'sfittoprint!"/>
</bean>
</beans>
NewsFeedManagerprintNews() ObjectFactory
prototype newsFeedbean
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
importx.y.NewsFeedManager;
publicclassMain{
publicstaticvoidmain(String[]args)throwsException{
ApplicationContextctx=newClassPathXmlApplicationContext("beans.xml");
NewsFeedManagermanager=(NewsFeedManager)ctx.getBean("newsFeedManager");
manager.printNews();
manager.printNews();
}
}
x.y.NewsFeed@1292d26:'...that'sfittoprint!'
x.y.NewsFeed@5329c5:'...that'sfittoprint!'
Spring2.5 BeanFactory BeanFactoryAware "" constructor
byType 3.3.5“autowire” setter BeanFactory @Autowired BeanFactory 3.11.1“ @Autowired
3.5.2.2.BeanNameAwarebeanorg.springframework.beans.factory.BeanNameAware BeanFactory
BeanFactoryBeanNameAwarebeanbeanbeanbeanInitializingBeanafterPropertiesSet
3.6.beanbeanbeanbeanbeanbean/beanBeanFactorybean ChildBeanDefinition XmlBeanFactorybeanXML 'parent'bean
<beanid="inheritedTestBean"abstract="true"
class="org.springframework.beans.TestBean">
<propertyname="name"value="parent"/>
<propertyname="age"value="1"/>
</bean>
<beanid="inheritsWithDifferentClass"
class="org.springframework.beans.DerivedTestBean"
parent="inheritedTestBean"init-method="initialize">
<propertyname="name"value="override"/>
<!--theagepropertyvalueof1willbeinheritedfromparent-->
</bean>
beanclassbeanclassbeanclassbeanbeanbeanbeanbeaninit-methoddestroy-method/ factory-methodbeanbean singleton
abstractbeanbeanclassbean abstract
<beanid="inheritedTestBeanWithoutClass"abstract="true">
<propertyname="name"value="parent"/>
<propertyname="age"value="1"/>
</bean>
<beanid="inheritsWithClass"class="org.springframework.beans.DerivedTestBean"
parent="inheritedTestBeanWithoutClass"init-method="initialize">
<propertyname="name"value="override"/>
<!--agewillinheritthevalueof1fromtheparentbeandefinition-->
</bean>
bean beanbeanbeanbeanrefbeanid getBean()
preInstantiateSingletons()abstractbean
ApplicationContextBeanFactorysingletonbeanbeanclass 'abstract''true'
3.7.SpringIoC BeanFactoryApplicationContextplugin
3.7.1. BeanPostProcessorbeanBeanPostProcessor Springbean BeanPostProcessor
BeanPostProcessor'order'BeanPostProcessor BeanPostProcessor
Ordered BeanPostProcessor Ordered BeanPostProcessor
OrderedJavaDoc
BeanPostProcessorbean SpringIoCbeanBeanPostProcessor
bean BeanFactoryPostProcessor 3.7.2
“ BeanFactoryPostProcessor”
BeanPostProcessor BeanPostProcessorbeanBeanPostProcessorbean
org.springframework.beans.factory.config.BeanPostProcessor
(post-processor)bean afterPropertiesSetbeanbeanproxySpringAOPbean
BeanFactoryApplicationContextbean ApplicationContext
BeanPostProcessorbeanbeanbean BeanFactorybean
ConfigurableBeanFactoryfactory=newXmlBeanFactory(...);
//nowregisteranyneededBeanPostProcessorinstances
MyBeanPostProcessorpostProcessor=newMyBeanPostProcessor();
factory.addBeanPostProcessor(postProcessor);
//nowstartusingthefactory
Spring ApplicationContext BeanPostProcessor
BeanPostProcessorsAOP(auto-proxying)
BeanPostProcessor , . BeanPostProcessorsbeanApplicationContext, BeanPostProcessorsbeanAOPBeanPostProcessorBeanPostProcessorsbean(aspects"")bean “Bean 'foo' isnoteligibleforgettingprocessedbyallBeanPostProcessors(auto_proxying) ”
ApplicationContext BeanPostProcessor
3.7.1.1. BeanPostProcessorHelloWorldBeanPostProcessor BeanPostProcessorbeanbean toString()
BeanPostProcessor
BeanPostProcessor
packagescripting;
importorg.springframework.beans.factory.config.BeanPostProcessor;
importorg.springframework.beans.BeansException;
publicclassInstantiationTracingBeanPostProcessorimplementsBeanPostProcessor{
//simplyreturntheinstantiatedbeanas-is
publicObjectpostProcessBeforeInitialization(Objectbean,StringbeanName)throwsBeansException{
returnbean;//wecouldpotentiallyreturnanyobjectreferencehere...
}
publicObjectpostProcessAfterInitialization(Objectbean,StringbeanName)throwsBeansException{
System.out.println("Bean'"+beanName+"'created:"+bean.toString());
returnbean;
}
}
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
<lang:groovyid="messenger"
script-source="classpath:org/springframework/scripting/groovy/Messenger.groovy">
<lang:propertyname="message"value="FionaAppleIsJustSoDreamy."/>
</lang:groovy>
<!--
whentheabovebean('messenger')isinstantiated,thiscustom
BeanPostProcessorimplementationwilloutputthefacttothesystemconsole
-->
<beanclass="scripting.InstantiationTracingBeanPostProcessor"/>
</beans>
InstantiationTracingBeanPostProcessorbeanbeanGroovybeanSpring2.0 24
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
importorg.springframework.scripting.Messenger;
publicfinalclassBoot{
publicstaticvoidmain(finalString[]args)throwsException{
ApplicationContextctx=newClassPathXmlApplicationContext("scripting/beans.xml");
Messengermessenger=(Messenger)ctx.getBean("messenger");
System.out.println(messenger);
}
}
Bean'messenger'created:org.springframework.scripting.groovy.GroovyMessenger@272961
org.springframework.scripting.groovy.GroovyMessenger@272961
3.7.1.2.RequiredAnnotationBeanPostProcessorSpringBeanPostProcessorSpringIoC 25.3.1“@ Required”
BeanPostProcessorJavaBeanbean
3.7.2. BeanFactoryPostProcessor
org.springframework.beans.factory.config.BeanFactoryPostProcessor
BeanPostProcessor BeanFactoryPostProcessorbeanSpringIoC BeanFactoryPostProcessorbean
BeanFactoryPostProcessor'order'BeanFactoryPostProcessor
BeanFactoryPostProcessorOrdered BeanFactoryPostProcessor
Ordered BeanFactoryPostProcessorOrderedJavaDoc
bean BeanPostProcessor 3.7.1“ BeanPostProcessor
bean”
BeanFactoryPostProcessor BeanFactoryPostProcessor
bean BeanFactoryPostProcessorbeanbean BeanFactory ApplicationContextSpringbeanPropertyResourceConfigurerPropertyPlaceholderConfigurer
BeanNameAutoProxyCreatorbeanproxy BeanFactoryPostProcessor
BeanFactory BeanFactoryPostProcessor
XmlBeanFactoryfactory=newXmlBeanFactory(newFileSystemResource("beans.xml"));
//bringinsomepropertyvaluesfromaPropertiesfile
PropertyPlaceholderConfigurercfg=newPropertyPlaceholderConfigurer();
cfg.setLocation(newFileSystemResource("jdbc.properties"));
//nowactuallydothereplacement
cfg.postProcessBeanFactory(factory);
Spring ApplicationContext BeanFactoryPostProcessor
ApplicationContextBeanFactoryPostProcessorbeanbeanbean
BeanPostProcessor BeanFactoryPostProcessorsSpring<beans/>'default-lazy-init'
BeanFactoryPostProcessor'lazy-init="false"'
3.7.2.1.PropertyPlaceholderConfigurer
PropertyPlaceholderConfigurerbean BeanFactoryJavaPropertiesURLXMLXML DataSourceProperties PropertyPlaceholderConfigurer
dataSource
<beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<propertyname="locations">
<value>classpath:com/foo/jdbc.properties</value>
</property>
</bean>
<beanid="dataSource"destroy-method="close"
class="org.apache.commons.dbcp.BasicDataSource">
<propertyname="driverClassName"value="${jdbc.driverClassName}
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
</bean>
JavaProperties
jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:hsql://production:9002
jdbc.username=sa
jdbc.password=root
Spring2.5 context()
<context:property-placeholderlocation="classpath:com/foo/jdbc.properties"/>
PropertyPlaceholderConfigurerPropertiesJava System
systemPropertiesMode PropertiesPlaceholderConfigurer
JavaDoc
PropertyPlaceholderConfigurer
<beanclass="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<propertyname="locations">
<value>classpath:com/foo/strategy.properties</value>
</property>
<propertyname="properties">
<value>custom.strategy.class=com.foo.DefaultStrategy</value>
</property>
</bean>
<beanid="serviceStrategy"class="${custom.strategy.class}"/>
beanbean ApplicationContext
preInstantiateSingletons()
3.7.2.2.PropertyOverrideConfigurerbeanPropertyOverrideConfigurerPropertyPlaceholderConfigurerbean
PropertiesbeanbeanXML PropertyOverrideConfigurerbeanProperties
beanName.property=value
Anexamplepropertiesfilemightlooklikethis:properties
dataSource.driverClassName=com.mysql.jdbc.Driver
dataSource.url=jdbc:mysql:mydb
bean dataSourcebeanbean driverurl
foo.fred.bob.sammy=123
... thesammypropertyof thebobpropertyof thefredpropertyof thefoobeanisbeingsettothescalarvalue123.foobeanfredbobsammy123
3.7.3. FactoryBean
beanorg.springframework.beans.factory.FactoryBeanFactoryBeanSpringIoCJava()XML FactoryBean FactoryBean
FactoryBean
ObjectgetObject()isSingleton()singletonprototype
booleanisSingleton()FactoryBeansingletontruefalse
ClassgetObjectType()getObject()nullSpringFactoryBeanSpring FactoryBean50
FactoryBeanbean FactoryBean ApplicationContextgetBeanbeanid '&'()id myBeanFactoryBeangetBean("myBean")FactoryBeanbeangetBean("&myBean")FactoryBean
3.8.TheApplicationContextbeansbean contextApplicationContextBeanFactory ApplicationContext
ContextLoaderJ2EEwebApplicationContextcontextApplicationContext BeanFactory BeanFactorycontext
MessageSource,
URL
ApplicationListenerbean
web
3.8.1.BeanFactory ApplicationContext?ApplicationContext""
ApplicationContextBeanFactory BeanFactory Applet""ApplicationContextSpring2.0 link linkend="beans-factory-
extension-bpp">BeanPostProcessor BeanFactoryAOPBeanFactoryApplicationContext ApplicationContext
BeanFactory
3.5.FeatureMatrixBeanFactory ApplicationContext
Bean/ Yes Yes
BeanPostProcessor No Yes
BeanFactoryPostProcessor No Yes
MessageSource( i18n) No Yes
ApplicationEvent No Yes
3.8.2. MessageSource
ApplicationContextMessageSourcei18nHierarchicalMessageSourceSpring
String getMessage(String code, Object[] args, String default,
Localeloc) MessageSourcelocaleargs MessageFormat
StringgetMessage(Stringcode,Object[]args,Localeloc)
NoSuchMessageException
String getMessage(MessageSourceResolvable resolvable, Locale
locale)MessageSourceResolvable MessageSourceResolvable
ApplicationContextcontext MessageSourcebeanbean messageSource
bean ApplicationContextbeanStaticMessageSource
SpringMessageSource: ResourceBundleMessageSourceStaticMessageSource
NestingMessageSource StaticMessageSource
ResourceBundleMessageSource
<beans>
<beanid="messageSource"
class="org.springframework.context.support.ResourceBundleMessageSource">
<propertyname="basenames">
<list>
<value>format</value>
<value>exceptions</value>
<value>windows</value>
</list>
</property>
</bean>
</beans>
classpathresource bundle format exceptionswindows
ResourceBundleJDK…
#in'format.properties'
message=Alligatorsrock!
#in'exceptions.properties'
argument.required=The'{0}'argumentisrequired.
ApplicationContextMessageSource MessageSource
publicstaticvoidmain(String[]args){
MessageSourceresources=newClassPathXmlApplicationContext("beans.xml");
Stringmessage=resources.getMessage("message",null,"Default",null);
System.out.println(message);
}
...
Alligatorsrock!
'beans.xml'classpath messageSourcebean basenames
basenameslistclasspath format.propertiesexceptions.properties
windows.properties
<beans>
<!--thisMessageSourceisbeingusedinawebapplication-->
<beanid="messageSource"class="org.springframework.context.support.ResourceBundleMessageSource">
<propertyname="baseName"value="WEB-INF/test-messages"/>
</bean>
<!--let'sinjecttheaboveMessageSourceintothisPOJO-->
<beanid="example"class="com.foo.Example">
<propertyname="messages"ref="messageSource"/>
</bean>
</beans>
publicclassExample{
privateMessageSourcemessages;
publicvoidsetMessages(MessageSourcemessages){
this.messages=messages;
}
publicvoidexecute(){
Stringmessage=this.messages.getMessage("argument.required",
newObject[]{"userDao"},"Required",null);
System.out.println(message);
}
}
execute()...
The'userDao'argumentisrequired.
i18nSpring MessageResourceJDKResourceBundlelocalemessageSource beanBritish (en-GB) localeformat_en_GB.propertiesexceptions_en_GB.properties
windows_en_GB.properties
Locale(British)locale
#in'exceptions_en_GB.properties'
argument.required=Ebagumlad,the'{0}'argumentisrequired,Isay,required.
publicstaticvoidmain(finalString[]args){
MessageSourceresources=newClassPathXmlApplicationContext("beans.xml");
Stringmessage=resources.getMessage("argument.required",
newObject[]{"userDao"},"Required",Locale.UK);
System.out.println(message);
}
...
Ebagumlad,the'userDao'argumentisrequired,Isay,required.
MessageSourceAwareMessageSource MessageSourceAwarebeanMessageSource
3.8.3.ApplicationContextApplicationEventApplicationListener
ApplicationListenerbean ApplicationEventApplicationContextbeanObserverSpring
3.6.
ContextRefreshedEvent
ApplicationContext
ConfigurableApplicationContextrefresh()
beanbeansingleton ApplicationContext
context ApplicationContext“”( XmlWebApplicationContextGenericApplicationContext.)
ContextStartedEvent
ApplicationContext,ConfigurableApplicationContextstart()"" beans()
ContextStoppedEvent
ConfigurableApplicationContextstop()ApplicationContext"" beans.contextstart()
ContextClosedEventConfigurableApplicationContextclose()ApplicationContext singletonbeancontext
RequestHandledEventwebbeanhttprequestrequestSpringDispatcherServletweb
ApplicationContextpublishEvent() ApplicationEvent
publishEvent()( ApplicationEventMulticaster)contextcontext, ApplicationContext:
<beanid="emailer"class="example.EmailBean">
<propertyname="blackList">
<list>
<value>black@list.org</value>
<value>white@list.org</value>
<value>john@doe.org</value>
</list>
</property>
</bean>
<beanid="blackListListener"class="example.BlackListNotifier">
<propertyname="notificationAddress"value="spam@list.org"/>
</bean>
:
publicclassEmailBeanimplementsApplicationContextAware{
privateListblackList;
privateApplicationContextctx;
publicvoidsetBlackList(ListblackList){
this.blackList=blackList;
}
publicvoidsetApplicationContext(ApplicationContextctx){
this.ctx=ctx;
}
publicvoidsendEmail(Stringaddress,Stringtext){
if(blackList.contains(address)){
BlackListEventevent=newBlackListEvent(address,text);
ctx.publishEvent(event);
return;
}
//sendemail...
}
}
publicclassBlackListNotifierimplementsApplicationListener{
privateStringnotificationAddress;
publicvoidsetNotificationAddress(StringnotificationAddress){
this.notificationAddress=notificationAddress;
}
publicvoidonApplicationEvent(ApplicationEventevent){
if(eventinstanceofBlackListEvent){
//notifyappropriateperson...
}
}
}
AOP
3.8.4.Spring Resource 4
ResourceLoader ResourceResourcejava.net.URLclasspathURLbeanResource ResourceApplicationContext PropertyEditor
Resource
ApplicationContext ClassPathXmlApplicationContext
classpathclasspathURLbean
3.8.5.ApplicationContextWEBBeanFactory ApplicationContext ContextLoaderApplicationContext
ApplicationContext ContextLoader
ContextLoader ContextLoaderListenerContextLoaderServletlistenerServlet2.3Servlet2.4servletcontextlistenersweb(servletcontextlistener)servletcontextlistenerSpring ApplicationContext
ContextLoaderListener ContextLoaderServletJavadocContextLoaderListenerApplicationContext
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/daoContext.xml/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!--orusetheContextLoaderServletinsteadoftheabovelistener
<servlet>
<servlet-name>context</servlet-name>
<servlet-class>org.springframework.web.context.ContextLoaderServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
-->
contextConfigLocation /WEB-INF/applicationContext.xml
ant- /WEB-INF/*Context.xml
/WEB-INF/**/*Context.xml(WEB-INF"Context.xml")ContextLoaderServletContextLoaderListener'contextConfigLocation'
3.9.singletonSpringIoCsingletonsingletonSpringIoC
Class.forName()SpringIoCstubproxysingletonSpringIoCEJBstub/proxySpringIoCJavaSpringIoCsingletonbeannon-singletonSpringIoCSpringIoCbeanHibernateSessionFactoryJ2EEJAREJBWAREARSpringIoCweb-appWARXMLSpringIoCSpringIoCweb-appsweb-appSpringIoCApplicationContextbeanbeanHibernateSessionFactory ContextSingletonBeanFactoryLocator
SingletonBeanFactoryLocatorsingletonSpringIoCwebSpringIoCbeanSingletonBeanFactoryLocatorContextSingletonBeanFactoryLocatorJavaDoc EJBSpringEJBnon-singleton BeanFactoryLocator
SingletonBeanFactoryLocatorContextSingletonBeanFactoryLocator
3.10.J2EERARSpringApplicationContextSpring2.5RARSpringApplicationContextbeanJARsJ2EERARApplicationContextJ2EEJ2EERAR“”(headless)WAR——HTTPJ2EESpringApplicationContextWARRARHTTPBeansJTAJNDIJDBCJMSConnectionFactorybeansJMX——SpringJNDIJMXSpringWorkManagerSpringContextResourceAdapterJavaDocRAR
RAR JAR jarsRAR”META-INF/ra.xml“SpringContextResourceAdapterJavaDocSpringXMLbean"META-INF/applicationContext.xml"RAR
RAR“”JMSRARApplicationContextRMI
3.11.Annotation-based3.7.1.2“ RequiredAnnotationBeanPostProcessor” BeanPostProcessor
SpringIoCSpring2.0 @RequiredSpring2.5Spring@Autowired 3.3.5 “autowire” Spring 2.5 JSR-250
@Resource@PostConstruct@PreDestroyJava5(Tiger)beanXML'
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
</beans>
post-processorsAutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessorPersistenceAnnotationBeanPostProcessor
RequiredAnnotationBeanPostProcessor
3.11.1.@Autowired@Autowired“”setter
publicclassSimpleMovieLister{
privateMovieFindermovieFinder;
@Autowired
publicvoidsetMovieFinder(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
//...
}
publicclassMovieRecommender{
privateMovieCatalogmovieCatalog;
privateCustomerPreferenceDaocustomerPreferenceDao;
@Autowired
publicvoidprepare(MovieCatalogmovieCatalog,CustomerPreferenceDaocustomerPreferenceDao){
this.movieCatalog=movieCatalog;
this.customerPreferenceDao=customerPreferenceDao;
}
//...
}
@Autowired
publicclassMovieRecommender{
@Autowired
privateMovieCatalogmovieCatalog;
privateCustomerPreferenceDaocustomerPreferenceDao;
@Autowired
publicMovieRecommender(CustomerPreferenceDaocustomerPreferenceDao){
this.customerPreferenceDao=customerPreferenceDao;
}
//...
}
ApplicationContextbeans
publicclassMovieRecommender{
@Autowired
privateMovieCatalog[]movieCatalogs;
//...
}
publicclassMovieRecommender{
privateSet<MovieCatalog>movieCatalogs;
@Autowired
publicvoidsetMovieCatalogs(Set<MovieCatalog>movieCatalogs){
this.movieCatalogs=movieCatalogs;
}
//...
}
MapsMapkey StringMapvalueskeysbean
publicclassMovieRecommender{
privateMap<String,MovieCatalog>movieCatalogs;
@Autowired
publicvoidsetMovieCatalogs(Map<String,MovieCatalog>movieCatalogs){
this.movieCatalogs=movieCatalogs;
}
//...
}
0beans required
publicclassSimpleMovieLister{
privateMovieFindermovieFinder;
@Autowired(required=false)
publicvoidsetMovieFinder(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
//...
}
requiredSpring greediest@Autowired“” BeanFactory ApplicationContext ResourceLoader
ApplicationEventPublisher MessageSource
ConfigurableApplicationContextResourcePatternResolver
publicclassMovieRecommender{
@Autowired
privateApplicationContextcontext;
publicMovieRecommender(){
}
//...
}
3.11.2.@Qualifier
publicclassMovieRecommender{
@Autowired
@Qualifier("mainCatalog")
privateMovieCatalogmovieCatalog;
//...
}
@Qualifier
publicclassMovieRecommender{
privateMovieCatalogmovieCatalog;
privateCustomerPreferenceDaocustomerPreferenceDao;
@Autowired
publicvoidprepare(@Qualifier("mainCatalog")MovieCatalogmovieCatalog,CustomerPreferenceDaocustomerPreferenceDao){
this.movieCatalog=movieCatalog;
this.customerPreferenceDao=customerPreferenceDao;
}
//...
}
@Qualifier
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public@interfaceGenre{
Stringvalue();
}
publicclassMovieRecommender{
@Autowired
@Genre("Action")
privateMovieCatalogactionCatalog;
privateMovieCatalogcomedyCatalog;
@Autowired
publicvoidsetComedyCatalog(@Genre("Comedy")MovieCatalogcomedyCatalog){
this.comedyCatalog=comedyCatalog;
}
//...
}
bean <qualifier/><bean/> 'type''value'“”
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<beanclass="example.SimpleMovieCatalog">
<qualifiertype="Genre"value="Action"/>
<!--injectanydependenciesrequiredbythisbean-->
</bean>
<beanclass="example.SimpleMovieCatalog">
<qualifiertype="example.Genre"value="Comedy"/>
<!--injectanydependenciesrequiredbythisbean-->
</bean>
<beanid="movieRecommender"class="example.MovieRecommender"/>
</beans>
3.12“Classpath” XML 3.12.6“”
Internet
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public@interfaceOffline{
}
publicclassMovieRecommender{
@Autowired
@Offline
privateMovieCatalogofflineCatalog;
//...
}
bean
<beanclass="example.SimpleMovieCatalog">
<qualifiertype="Offline"/>
<!--injectanydependenciesrequiredbythisbean-->
</bean>
'value'bean
@Target({ElementType.FIELD,ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@Qualifier
public@interfaceMovieQualifier{
Stringgenre();
Formatformat();
}
Format
publicenumFormat{
VHS,DVD,BLURAY
}
'genre' 'format'
publicclassMovieRecommender{
@Autowired
@MovieQualifier(format=Format.VHS,genre="Action")
privateMovieCatalogactionVhsCatalog;
@Autowired
@MovieQualifier(format=Format.VHS,genre="Comedy")
privateMovieCatalogcomedyVhsCatalog;
@Autowired
@MovieQualifier(format=Format.DVD,genre="Action")
privateMovieCatalogactionDvdCatalog;
@Autowired
@MovieQualifier(format=Format.BLURAY,genre="Comedy")
privateMovieCatalogcomedyBluRayCatalog;
//...
}
beanbean <qualifier/> <qualifier/>bean<meta/>
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:annotation-config/>
<beanclass="example.SimpleMovieCatalog">
<qualifiertype="MovieQualifier">
<attributename="format"value="VHS"/>
<attributename="genre"value="Action"/>
</qualifier>
<!--injectanydependenciesrequiredbythisbean-->
</bean>
<beanclass="example.SimpleMovieCatalog">
<qualifiertype="MovieQualifier">
<attributename="format"value="VHS"/>
<attributename="genre"value="Comedy"/>
</qualifier>
<!--injectanydependenciesrequiredbythisbean-->
</bean>
<beanclass="example.SimpleMovieCatalog">
<metakey="format"value="DVD"/>
<metakey="genre"value="Action"/>
<!--injectanydependenciesrequiredbythisbean-->
</bean>
<beanclass="example.SimpleMovieCatalog">
<metakey="format"value="BLURAY"/>
<metakey="genre"value="Comedy"/>
<!--injectanydependenciesrequiredbythisbean-->
</bean>
</beans>
3.11.3.CustomAutowireConfigurerCustomAutowireConfigurerBeanFactoryPostProcessor Spring@Qualifier
<beanid="customAutowireConfigurer"class="org.springframework.beans.factory.annotation.CustomAutowireConfigurer">
<propertyname="customQualifierTypes">
<set>
<value>example.CustomQualifier</value>
</set>
</property>
</bean>
AutowireCandidateResolver Java Java 5 'autowire-
candidate'<beans/>'default-autowire-candidates'Java5@QualifierCustomAutowireConfigurer
Java“”beansbean 'primary''true'
3.11.4.@ResourceSpringJSR-250beanJavaEE5Java6JSF1.2beansJAX-WS2.0SpringSpring@Resource‘name’Springbean by-name
publicclassSimpleMovieLister{
privateMovieFindermovieFinder;
@Resource(name="myMovieFinder")
publicvoidsetMovieFinder(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
}
settersetterbean"movieFinder"setter
publicclassSimpleMovieLister{
privateMovieFindermovieFinder;
@Resource
publicvoidsetMovieFinder(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
}
BeanFactory bean JNDI SpringSimpleJndiBeanFactorySpringJNDI
@Autowired @Resourcebeanbean"resolvabledependencies" BeanFactory ApplicationContext
ResourceLoader ApplicationEventPublisher MessageSource@Resource
customerPreferenceDao “customerPreferenceDao” beanCustomerPreferenceDao"context" ApplicationContext
publicclassMovieRecommender{
@Resource
privateCustomerPreferenceDaocustomerPreferenceDao;
@Resource
privateApplicationContextcontext;
publicMovieRecommender(){
}
//...
}
3.11.5.@PostConstruct @PreDestroy
CommonAnnotationBeanPostProcessor @Resource JSR-250 lifecycleSpring2.5 initializationcallbacks destructioncallbacks
CommonAnnotationBeanPostProcessorSpring ApplicationContext
Spring
publicclassCachingMovieLister{
@PostConstruct
publicvoidpopulateMovieCache(){
//populatesthemoviecacheuponinitialization...
}
@PreDestroy
publicvoidclearMovieCache(){
//clearsthemoviecacheupondestruction...
}
}
3.5.1.4“”
3.12.ClasspathXML Spring”beanXML classpath
3.12.1.@ComponentSpring2.0 @Repository (DataAccessObjectDAO)12.6.4“”
Spring2.5(stereotypeannotations) @Component@Service@Controller@ComponentSpring @Repository@Service@Controller@Component) @ComponentSpringFramework@Component@Service@Service @Repository
3.12.2.Spring“”(stereotyped) ApplicationContext BeanDefinition
@Service
publicclassSimpleMovieLister{
privateMovieFindermovieFinder;
@Autowired
publicSimpleMovieLister(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
}
@Repository
publicclassJpaMovieFinderimplementsMovieFinder{
//implementationelidedforclarity
}
beanXML'basePackage'
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scanbase-package="org.example"/>
</beans>
AutowiredAnnotationBeanPostProcessorCommonAnnotationBeanPostProcessor
'false' annotation-config
3.12.3.@Component@Repository@Service@Controller( @Component)
' component-scan' include-filterexclude-filter '
3.7.
annotation org.example.SomeAnnotation
assignable org.example.SomeClass
regex org\.example\.Default.*
aspectj org.example..*Service+
XML@Repository“stub”
<beans...>
<context:component-scanbase-package="org.example">
<context:include-filtertype="regex"expression=".*Stub.*Repository"/>
<context:exclude-filtertype="annotation"expression="org.springframework.stereotype.Repository"/>
</context:component-scan>
</beans>
<component-scan/>use-default-filters="false"@Repository@Service@Controller
3.12.4.BeanNameGeneratorbean nameSpring“”
(@Component@Repository@Service@Controller)bean(non-qualified) 'myMovieLister''movieFinderImpl'
@Service("myMovieLister")
publicclassSimpleMovieLister{
//...
}
@Repository
publicclassMovieFinderImplimplementsMovieFinder{
//...
}
bean BeanNameGenerator
<beans...>
<context:component-scanbase-package="org.example"
name-generator="org.example.MyNameGenerator"/>
</beans>
3.12.5.Spring“singleton”
@Scope("prototype")
@Repository
publicclassMovieFinderImplimplementsMovieFinder{
//...
}
ScopeMetadataResolver
<beans...>
<context:component-scanbase-package="org.example"
scope-resolver="org.example.MyScopeResolver"/>
</beans>
singleton 3.4.4.5“bean” 'no''interfaces''targetClass'JDK
<beans...>
<context:component-scanbase-package="org.example"
scoped-proxy="interfaces"/>
</beans>
3.12.6.3.11.2“” @Qualifier @Qualifier'qualifier'' meta'classpath (type-level)
@Component
@Qualifier("Action")
publicclassActionMovieCatalogimplementsMovieCatalog{
//...
}
@Component
@Genre("Action")
publicclassActionMovieCatalogimplementsMovieCatalog{
//...
}
@Component
@Offline
publicclassCachingMovieCatalogimplementsMovieCatalog{
//...
}
XML
3.13. LoadTimeWeaver
Spring2.5contextload-time-weaver
<beans...>
<context:load-time-weaver/>
</beans>
XMLSpringApplicationContext Spring LoadTimeWeaverApplicationContextbean LoadTimeWeaverAware(load-timeweaver)JPA JPA LocalContainerEntityManagerFactoryBean
AspectJ 6.8.4“SpringAspectJLTW”
4
4.1.4.2.Resource4.3. Resource
4.3.1.UrlResource4.3.2.ClassPathResource4.3.3.FileSystemResource4.3.4.ServletContextResource4.3.5.InputStreamResource4.3.6.ByteArrayResource
4.4.ResourceLoader4.5.ResourceLoaderAware4.6. Resource
4.7.Applicationcontext Resource4.7.1.applicationcontext4.7.2.Applicationcontext4.7.3.FileSystemResource
4.1.Java java.net.URLURL ServletContextURLURL( http:) URL
4.2.ResourceSpring Resource
publicinterfaceInputStreamSource{
booleanexists();
booleanisOpen();
URLgetURL()throwsIOException;
FilegetFile()throwsIOException;
ResourcecreateRelative(StringrelativePath)throwsIOException;
StringgetFilename();
StringgetDescription();
}
publicinterfaceInputStreamSource{
InputStreamgetInputStream()throwsIOException;
}
Resource
getInputStream(): InputStream InputStream
exists(): boolean
isOpen(): boolean trueInputStreamInputStreamResourceresource false
getDescription():URL URL File()SpringResourceSpringAPIs( ApplicationContext) Stringcontext ResourceString ResourceResourceSpringSpringSpring URL
Resource UrlResourceURL URL
4.3. ResourceSpring Resource
4.3.1.UrlResourceUrlResource java.net.URLURLHTTPFTPURL String
URL file: http:HTTP ftp:FTPUrlResourceJava UrlResource StringAPIJavaBeansPropertyEditor Resource
UrlResource
4.3.2.ClassPathResourceclasspathcontext(classloader) Resource java.io.File(servlet)jar Resourcejava.net.URLClassPathResourceJavaClassPathResource StringAPIJavaBeans PropertyEditor classpath: ClassPathResource
4.3.3.FileSystemResource java.io.FileResource File URL
4.3.4.ServletContextResource ServletContext ResourcewebURLweb java.io.FileJARDB()Servlet
4.3.5.InputStreamResource InputStream Resource ResourceByteArrayResourceResource Resource - isOpen() true
4.3.6.ByteArrayResourcebyte Resource byte ByteArrayInputStream
byte InputStreamResource
4.4.ResourceLoaderResourceLoader() Resource
publicinterfaceResourceLoader{
ResourcegetResource(Stringlocation);
}
applicationcontext ResourceLoader Resourceapplicationcontext getResource() applicationcontextResource ClassPathXmlApplicationContext
Resourcetemplate=ctx.getResource("some/resource/path/myTemplate.txt");
ClassPathResourceFileSystemXmlApplicationContextFileSystemResource WebApplicationContextServletContextResource
applicationcontextapplicationcontext classpath:ClassPathResource
Resourcetemplate=ctx.getResource("classpath:some/resource/path/myTemplate.txt");
java.net.URL UrlResource
Resourcetemplate=ctx.getResource("file:/some/resource/path/myTemplate.txt");
Resourcetemplate=ctx.getResource("http://myhost.com/resource/path/myTemplate.txt");
String Resource
4.1.Resourcestrings
classpath: classpath:com/myapp/config.xml classpath
file: file:/data/config.xml URL [a]
http: http://myserver/logo.png URL
(none) /data/config.xml ApplicationContext
[a] 4.7.3“ FileSystemResource”
4.5.ResourceLoaderAwareResourceLoaderAware ResourceLoader
publicinterfaceResourceLoaderAware{
voidsetResourceLoader(ResourceLoaderresourceLoader);
}
ResourceLoaderAwareapplicationcontext(Springbean)applicationcontext ResourceLoaderAware application contextsetResourceLoader(ResourceLoader)(Springapplication contextResourceLoader) ApplicationContextResourceLoaderbean ApplicationContextAware
applicationcontext ResourceLoader
ApplicationContextSpring 2.5, ResourceLoader ResourceLoaderAware “”constructor byType( 3.3.5“autowire” )setter ResourceLoader 3.11.1“ @Autowired”
4.6. Resource
beanbean ResourceLoaderbean Resourceapplication context String Resource PropertyEditor
JavaBeans myBean Resourcetemplate
<beanid="myBean"class="...">
<propertyname="template"value="some/resource/path/myTemplate.txt"/>
</bean>
applicationcontext ResourceLoader ClassPathResource
FileSystemResourceServletContextResourcecontext Resource ClassPathResource UrlResource()
<propertyname="template"value="classpath:some/resource/path/myTemplate.txt">
<propertyname="template"value="file:/some/resource/path/myTemplate.txt"/>
4.7.Applicationcontext Resource
4.7.1.applicationcontextapplicationcontext(contextXML) Resource beanapplication contextClassPathXmlApplicationContext
ApplicationContextctx=newClassPathXmlApplicationContext("conf/appContext.xml");
BeanclasspathClassPathResourceFileSystemXmlApplicationContext
ApplicationContextctx=
newFileSystemXmlApplicationContext("conf/appContext.xml");
BeanclasspathURL Resource FileSystemXmlApplicationContext...
ApplicationContextctx=
newFileSystemXmlApplicationContext("classpath:conf/appContext.xml");
...classpathbean FileSystemXmlApplicationContextResourceLoader
4.7.1.1. ClassPathXmlApplicationContext-ClassPathXmlApplicationContext XML() Class
ClassPathXmlApplicationContext
com/
foo/
services.xml
daos.xml
MessengerService.class
'services.xml' 'daos.xml'bean ClassPathXmlApplicationContext
...
ApplicationContextctx=newClassPathXmlApplicationContext(
newString[]{"services.xml","daos.xml"},MessengerService.class);
ClassPathXmlApplicationContextJavadocs
4.7.2.ApplicationcontextApplicationcontext())“”contextapplicationcontext ( PathMatcher
classpath*:Resource
4.7.2.1.AntpatternAntpattern
/WEB-INF/*-context.xml
com/mycompany/**/applicationContext.xml
file:C:/some/path/*-context.xml
classpath:com/mycompany/**/applicationContext.xml
ResourceURL" wsjar") java.io.FilejarURLURL jar
4.7.2.1.1.
URL() ResourceLoaderclasspath Classloader.getResource()
Javadocs) URLclasspath
jarURL java.net.JarURLConnection
4.7.2.2.classpath*:XMLapplicationcontext classpath*:
ApplicationContextctx=
newClassPathXmlApplicationContext("classpath*:conf/appContext.xml");
classpath( ClassLoader.getResources(...)))applicationcontext
Classpath*:classpathclassloader getResources() classloaderjar classpath*:classloaderclasspathjargetClass().getClassLoader().getResources("
<someFileInsideTheJar>")"classpath*:" PathMatcher pattern" classpath*:META-INF/*-
beans.xml" ClassLoader.getResources()
4.7.2.3." classpath*:"Antpatternpattern JDK ClassLoader.getResources()
" classpath:"Antpattern
com/mycompany/package1/service-context.xml
classpath:com/mycompany/**/service-context.xml
getResource("com/mycompany");()URL classloader" classpath*:"
4.7.3.FileSystemResource FileSystemApplicationContext FileSystemResource(FileSystemApplicationContextResourceLoader) FileSystemApplicationContext ResourceLoader
FileSystemApplicationContext FileSystemResource
ApplicationContextctx=
newFileSystemXmlApplicationContext("conf/context.xml");
ApplicationContextctx=
newFileSystemXmlApplicationContext("/conf/context.xml");
()
FileSystemXmlApplicationContextctx=...;
ctx.getResource("some/resource/path/myTemplate.txt");
FileSystemXmlApplicationContextctx=...;
ctx.getResource("/some/resource/path/myTemplate.txt");
FileSystemResource FileSystemXmlApplicationContext file:
URL UrlResource
//actualcontexttypedoesn'tmatter,theResourcewillalwaysbe
ctx.getResource("file:/some/resource/path/myTemplate.txt");
//forcethisFileSystemXmlApplicationContexttoloadit'sdefinitionviaa
ApplicationContextctx=
newFileSystemXmlApplicationContext("file:/conf/context.xml");
5 BeanWrapper
5.1.5.2.SpringValidator5.3.5.4.BeanBeanWrapper
5.4.1.5.4.2.PropertyEditor
5.1.Spring()WebSpring Validator
Data bindingSpring DataBinder ValidatorDataBinder
validationSpringMVCBeanWrapperSpring BeanWrapper BeanWrapper BeanWrapper
SpringPropertyEditor PropertyEditorJavaBean BeanWrapper
BeanWrapperDataBinder PropertyEditor
5.2.Spring Validator
Springvalidator ValidatorErrorsSpring Errors
publicclassPerson{
privateStringname;
privateintage;
//theusualgettersandsetters...
}
org.springframework.validation.Validator Person
supports(Class)ValidatorClass
validate(Object, org.springframework.validation.Errors)
ErrorsValidatorSpring ValidationUtils
publicclassPersonValidatorimplementsValidator{
/**
*ThisValidatorvalidatesjustPersoninstances
*/
publicbooleansupports(Classclazz){
returnPerson.class.equals(clazz);
}
publicvoidvalidate(Objectobj,Errorse){
ValidationUtils.rejectIfEmpty(e,"name","name.empty");
Personp=(Person)obj;
if(p.getAge()<0){
e.rejectValue("age","negativevalue");
}elseif(p.getAge()>110){
e.rejectValue("age","too.darn.old");
}
}
}
ValidationUtilsrejectIfEmpty(..)name 'name' nullValidationUtilsJavaDoc
Validator Validator 'rich'Customer String(firstnamesecondname) Address AddressCustomer AddressValidator
CustomerValidatorAddressValidator CustomerValidator
AddressValidator
publicclassCustomerValidatorimplementsValidator{
privatefinalValidatoraddressValidator;
publicCustomerValidator(ValidatoraddressValidator){
if(addressValidator==null){
thrownewIllegalArgumentException("Thesupplied[Validator]isrequiredandmustnotbenull.");
}
if(!addressValidator.supports(Address.class)){
thrownewIllegalArgumentException(
"Thesupplied[Validator]mustsupportthevalidationof[Address]instances.");
}
this.addressValidator=addressValidator;
}
/**
*ThisValidatorvalidatesCustomerinstances,andanysubclassesof
*/
publicbooleansupports(Classclazz){
returnCustomer.class.isAssignableFrom(clazz);
}
publicvoidvalidate(Objecttarget,Errorserrors){
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"firstName","field.required");
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"surname","field.required");
Customercustomer=(Customer)target;
try{
errors.pushNestedPath("address");
ValidationUtils.invokeValidator(this.addressValidator,customer.getAddress(),errors);
}finally{
errors.popNestedPath();
}
}
}
ErrorsSpringWebMVC <spring:bind/>Javadoc
5.3.nameage MessageSourcenameage ValidationUtils
ErrorsrejectValuereject MessageCodesResolver
DefaultMessageCodesResolver DefaultMessageCodesResolverrejectrejectValue("age","too.darn.old")Spring too.darn.old
too.darn.old.agetoo.darn.old.age.int
MessageCodesResolverJavaDocs MessageCodesResolver
DefaultMessageCodesResolver
5.4.BeanBeanWrapperorg.springframework.beansSunJavaBeanJavaBeanJavasettergetter bingoMadnesssetter setBingoMadness(..)
getBingoMadness()JavaBeanSun( java.sun.com/products/javabeans)BeanWrapper(BeanWrapperImpl)JavaDoc BeanWrapper
BeanWrapper BeanWrapperJavaBeanPropertyChangeListenersVetoableChangeListeners BeanWrapper BeanWrapperDataBinderBeanFactory
BeanWrapper bean
5.4.1.setPropertyValue(s)getPropertyValue(s)SpringJavaDoc
5.1.
name namegetName() isName()setName(..)
account.name accountnamegetAccount().setName()getAccount().getName()
account[2] accountarraylist
account[COMPANYNAME] MapaccountCOMPANYNAMEkey
BeanWrapper
BeanWrapper DataBinderBeanFactory PropertyEditor
publicclassCompany{
privateStringname;
privateEmployeemanagingDirector;
publicStringgetName() {
returnthis.name;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicEmployeegetManagingDirector(){
returnthis.managingDirector;
}
publicvoidsetManagingDirector(EmployeemanagingDirector){
this.managingDirector=managingDirector;
}
}
publicclassEmployee{
privateStringname;
privatefloatsalary;
publicStringgetName() {
returnthis.name;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicfloatgetSalary(){
returnsalary;
}
publicvoidsetSalary(floatsalary){
this.salary=salary;
}
}
CompaniesEmployees
BeanWrappercompany=BeanWrapperImpl(newCompany());
//settingthecompanyname..
company.setPropertyValue("name","SomeCompanyInc.");
//...canalsobedonelikethis:
PropertyValuevalue=newPropertyValue("name","SomeCompanyInc.");
company.setPropertyValue(value);
//ok,let'screatethedirectorandtieittothecompany:
BeanWrapperjim=BeanWrapperImpl(newEmployee());
jim.setPropertyValue("name","JimStravinsky");
company.setPropertyValue("managingDirector",jim.getWrappedInstance());
//retrievingthesalaryofthemanagingDirectorthroughthecompany
Floatsalary=(Float)company.getPropertyValue("managingDirector.salary");
5.4.2. PropertyEditorSpringPropertyEditorObject String Date String
' 2007-14-09'Date Date java.beans.PropertyEditor
BeanWrapperIoCSun java.beansJavaDocPropertyEditors
PropertyEditorsBeanXMLbeanjava.lang.StringSpring ClassEditor
StringClasssetter Class
SpringMVCPropertyEditorsHTTPCommandControllerSpringPropertyEditorsSpring PropertyEditor
org.springframework.beans.PropertyEditors BeanWrapperImpl
5.2. PropertyEditors
ByteArrayPropertyEditor bytebyte BeanWrapperImpl
ClassEditorClassClassBeanWrapperImpl
CustomBooleanEditor Boolean BeanWrapperImpl
CustomCollectionEditor ( Collection)( Collection)
CustomDateEditorjava.util.DateDateFormat
CustomNumberEditorInteger Long Float DoubleNumberBeanWrapperImpl
FileEditor java.io.File BeanWrapperImpl
InputStreamEditor
InputStream ResourceEditor
InputStream InputStream
BeanWrapperImpl
LocaleEditorStringLocaleString[]_[]_[]LocaltoString() BeanWrapperImpl
PatternEditor JDK1.5 Pattern
PropertiesEditorString PropertiesJavaDocjava.lang.PropertiesBeanWrapperImpl
StringTrimmerEditor (trim)String null
URLEditor StringURL URL BeanWrapperImpl
Springjava.beans.PropertyEditorManager sun.bean.editors
PropertyEditor FontColorJavaBean PropertyEditor
EditorEditor“Editor” FooEditor
PropertyEditor
com
chank
pop
Foo
FooEditor//thePropertyEditorfortheFooclass
BeanInfoJavaBean( ) BeanInfoPropertyEditor
com
chank
pop
Foo
FooBeanInfo//theBeanInfofortheFooclass
FooBeanInfo CustomNumberEditorFooage
publicclassFooBeanInfoextendsSimpleBeanInfo{
publicPropertyDescriptor[]getPropertyDescriptors(){
try{
finalPropertyEditornumberPE=newCustomNumberEditor(Integer.class,true);
PropertyDescriptorageDescriptor=newPropertyDescriptor("age",Foo.class){
publicPropertyEditorcreatePropertyEditor(Objectbean){
returnnumberPE;
};
};
returnnewPropertyDescriptor[]{ageDescriptor};
}
catch(IntrospectionExceptionex){
thrownewError(ex.toString());
}
}
}
5.4.2.1. PropertyEditor
beanSpring IoC JavaBean PropertyEditorSpringPropertyEditor(Class Class)JavaJavaBean PropertyEditor
EditorEditorPropertyEditor BeanFactory ConfigurableBeanFactory
registerCustomEditor() CustomEditorConfigurerbeanfactorybeanfactory BeanFactory
beanfactoryapplicationcontext BeanWrapper BeanWrapper
ApplicationContextapplicationcontextJavaBeanPropertyEditorString CustomEditorConfigurerbeanfactory
PropertyEditorApplicationContext
ExoticTypeDependsOnExoticType
packageexample;
publicclassExoticType{
privateStringname;
publicExoticType(Stringname){
this.name=name;
}
}
publicclassDependsOnExoticType{
privateExoticTypetype;
publicvoidsetType(ExoticTypetype){
this.type=type;
}
}
type PropertyEditorExoticType
<beanid="sample"class="example.DependsOnExoticType">
<propertyname="type"value="aNameForExoticType"/>
</bean>
PropertyEditor
//convertsstringrepresentationtoExoticTypeobject
packageexample;
publicclassExoticTypeEditorextendsPropertyEditorSupport{
privateStringformat;
publicvoidsetFormat(Stringformat){
this.format=format;
}
publicvoidsetAsText(Stringtext){
if(format!=null&&format.equals("upperCase")){
text=text.toUpperCase();
}
ExoticTypetype=newExoticType(text);
setValue(type);
}
}
CustomEditorConfigurerApplicationContextPropertyEditor
<beanclass="org.springframework.beans.factory.config.CustomEditorConfigurer">
<propertyname="customEditors">
<map>
<entrykey="example.ExoticType">
<beanclass="example.ExoticTypeEditor">
<propertyname="format"value="upperCase"/>
</bean>
</entry>
</map>
</property>
</bean>
5.4.2.1.1. PropertyEditorRegistrars
Spring PropertyEditorRegistrarPropertyEditorRegistry PropertyEditorRegistrySpringBeanWrapper
DataBinder CustomEditorConfigurerPropertyEditorRegistrars CustomEditorConfigurer
setPropertyEditorRegistrars(..) DataBinderSpringMVCControllersCustomEditorConfigurerPropertyEditorRegistrarsbeanPropertyEditorRegistrarPropertyEditor
PropertyEditorRegistrar PropertyEditorRegistrar
packagecom.foo.editors.spring;
publicfinalclassCustomPropertyEditorRegistrarimplementsPropertyEditorRegistrar{
publicvoidregisterCustomEditors(PropertyEditorRegistryregistry){
//itisexpectedthatnewPropertyEditorinstancesarecreated
registry.registerCustomEditor(ExoticType.class,newExoticTypeEditor());
//youcouldregisterasmanycustompropertyeditorsasarerequiredhere...
}
}
org.springframework.beans.support.ResourceEditorRegistrar
PropertyEditorRegistrar registerCustomEditors(..)
CustomEditorConfigurerCustomPropertyEditorRegistrar
<beanclass="org.springframework.beans.factory.config.CustomEditorConfigurer">
<propertyname="propertyEditorRegistrars">
<list>
<refbean="customPropertyEditorRegistrar"/>
</list>
</property>
</bean>
<beanid="customPropertyEditorRegistrar"class="com.foo.editors.spring.CustomPropertyEditorRegistrar"/>
SpringMVC web Controllers SimpleFormController
PropertyEditorRegistrars initBinder(..)PropertyEditorRegistrar
publicfinalclassRegisterUserControllerextendsSimpleFormController{
privatefinalPropertyEditorRegistrarcustomPropertyEditorRegistrar;
publicRegisterUserController(PropertyEditorRegistrarpropertyEditorRegistrar){
this.customPropertyEditorRegistrar=propertyEditorRegistrar;
}
protectedvoidinitBinder(HttpServletRequestrequest,ServletRequestDataBinderbinder)throwsException{
this.customPropertyEditorRegistrar.registerCustomEditors(binder);
}
//othermethodstodowithregisteringaUser
}
PropertyEditorinitBinder(..) PropertyEditor Controllers
6SpringAOP
6.1.6.1.1.AOP6.1.2.SpringAOP6.1.3.AOP
6.2.@AspectJ6.2.1.@AspectJ6.2.2.6.2.3.pointcut6.2.4.6.2.5.Introduction6.2.6.6.2.7.
6.3.SchemaAOP6.3.1.6.3.2.6.3.3.6.3.4.6.3.5.6.3.6.Advisor6.3.7.
6.4.AOP6.4.1.SpringAOPAspectJ6.4.2.SpringAOP@AspectJXML
6.5.6.6.
6.6.1.AOP6.7.@AspectJ6.8.SpringAspectJ
6.8.1.SpringAspectJdomainobject6.8.2.SpringAspectJ6.8.3.SpringIoCAspectJ6.8.4.SpringAspectJLTW
6.9.
Spring2.0AOPSpring2.0 @AspectJ(advice)AspectJSpringAOPWeavingSpring2.0@AspectJAOPSpring2.0Spring1.21.2APIAOP
6.1.AOPOOPOOPclassesAOP AOP crosscutting
AOPSpringSpringIoCAOPAOPAOPSpringIoC,AOPSpringFramework
EJB
AOPOOPpoolingSpringAOP
6.1.1.AOPAOPSpringAOPSpring
Aspect J2EESpringAOP @Aspect
Joinpoint SpringAOP
Advice “around”“before”“after”AOPSpring
Pointcut AOPSpringAspectJ
Introduction inter-typedeclarationSpringbean IsModified
TargetObject advised SpringAOP
AOPAOPProxy AOPSpringAOPJDKCGLIB
Weaving AspectJSpringJavaAOP
Beforeadvice
Afterreturningadvice
Afterthrowingadvice
After(finally)advice
AroundAdviceAspectJSpring JoinPointproceed()
Spring2.0 Object
AOPAOP
6.1.2.SpringAOPSpringAOPJavaSpringAOPJ2EEwebSpringjoinpointSpringbeanSpringAOPAPISpringAspectJSpringAOPSpringAOPSpringAOPAOPSpringIoCSpringAOPSpringIoCbeanSpring"autoproxying"AOPSpringAOPAspectJJ2EEAOPSpringAOPSpringAOPAOPAspectJproxy-basedSpringAOPAspectJSpring2.0SpringAOPIoCAspectJAOPSpringSpringAOPAPIAOPAllianceAPISpringAOP SpringAOPAPI
SpringFrameworknon-invasiveness ;/SpringFrameworkSpringSpringFrameworkAspectJSpringAOP@AspectJSpringXML@AspectJSpring@AspectJSpringXML6.4“AOP”
6.1.3.AOPSpringJ2SEdynamicproxies AOPSpringCGLIB.CGLIBCGLIBSpringAOPproxy-based 6.6.1“AOP”
6.2.@AspectJ@AspectJJava5Java@AspectJAspectJ5 AspectJprojectSpring2.0AspectJ5AspectJAOPSpringAOPAspectJweaverAspectJAspectJ 6.8“SpringAspectJ”
6.2.1.@AspectJSpring@AspectJSpring@AspectJ autoproxying beanSpringbeanSpringSpring@AspectJ
<aop:aspectj-autoproxy/>
A,XMLSchema-basedconfigurationschemaaop A.2.7“The aopschema”
DTDapplicationcontext@AspectJ
<beanclass="org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator"/>
classpathAspectJ aspectjweaver.jaraspectjrt.jarAspectJ1.5.1'lib'Spring-with-dependencies 'lib/aspectj'
6.2.2.@AspectJapplicationcontext@Aspect @AspectbeanSpringSpringAOPapplicationcontextbean @Aspectbean
<beanid="myAspect"class="org.xyz.NotVeryUsefulAspect">
<!--configurepropertiesofaspecthereasnormal-->
</bean>
NotVeryUsefulAspect org.aspectj.lang.annotation.Aspect
packageorg.xyz;
importorg.aspectj.lang.annotation.Aspect;
@Aspect
AspectJSpring call,get,
set, preinitialization,
staticinitialization,
initialization, handler,
adviceexecution, withincode,
cflow,cflowbelow, if, @this
@withincodeSpring AOPIllegalArgumentException
SpringAOPAspectJ
publicclassNotVeryUsefulAspect{
}
@Aspectinter-type
SpringAOP @Aspect
6.2.3.pointcutSpringAOPSpringbeanSpringbean
@AspectJAOP'anyOldTransfer'"transfer"
@Pointcut"execution*transfer.." //thepointcutexpression
privatevoidanyOldTransfer{} //thepointcutsignature
@PointcutAspectJ5AspectJ AspectJJava5 AspectJ5
AspectJColyeret.al.“ EclipseAspectJ”RamnivasLaddad“ AspectJinAction”
6.2.3.1.PCDSpringAOPAspectJ
execution-Spring
within-SpringAOP
this-SpringAOPbeanreferenceSpringAOPtarget-SpringAOP
args-SpringAOP
@target-SpringAOP
@args-SpringAOP
@within-SpringAOP
@annotation-SpringAOP,SpringAOP' bean'PCDPCDSpringbeanSpringbean' bean'PCD:
beanidOrNameOfBean
'idOrNameOfBean'Springbean' *'Springbean' bean'PCD' bean'PCD&&,||!
' bean'PCD SpringAOPAspectJ.SpringAspectJPCD'bean'PCDAOP Springbean
SpringAOPpointcutAspectJAspectJ'this''target'SpringAOP'this''target'
6.2.3.2.'&','||' '!' tradingOperation
@Pointcut"executionpublic**.."
privatevoidanyPublicOperation{}
@Pointcut"withincom.xyz.someapp.trading..*"
privatevoidinTrading{}
@Pointcut"anyPublicOperation&&inTrading"
privatevoidtradingOperation{}
Java
6.2.3.3.“SystemArchitecture”
packagecom.xyz.someapp;
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.Pointcut;
@Aspect
publicclassSystemArchitecture{
/**
*Ajoinpointisintheweblayerifthemethodisdefined
*inatypeinthecom.xyz.someapp.webpackageoranysub-package
*underthat.
*/
@Pointcut"withincom.xyz.someapp.web..*"
publicvoidinWebLayer{}
/**
*Ajoinpointisintheservicelayerifthemethodisdefined
*inatypeinthecom.xyz.someapp.servicepackageoranysub-package
*underthat.
*/
@Pointcut"withincom.xyz.someapp.service..*"
publicvoidinServiceLayer{}
/**
*Ajoinpointisinthedataaccesslayerifthemethodisdefined
*inatypeinthecom.xyz.someapp.daopackageoranysub-package
*underthat.
*/
@Pointcut"withincom.xyz.someapp.dao..*"
publicvoidinDataAccessLayer{}
/**
*Abusinessserviceistheexecutionofanymethoddefinedonaservice
*interface.Thisdefinitionassumesthatinterfacesareplacedinthe
*"service"package,andthatimplementationtypesareinsub-packages.
*
*Ifyougroupserviceinterfacesbyfunctionalareaforexample,
*inpackagescom.xyz.someapp.abc.serviceandcom.xyz.def.service
*thepointcutexpression"execution*com.xyz.someapp..service.*.*..
*couldbeusedinstead.
*
*Alternatively,youcanwritetheexpressionusingthe'
*PCD,likeso"bean*Service ".Thisassumesthatyouhave
*namedyourSpringservicebeansinaconsistentfashion.
*/
@Pointcut"execution*com.xyz.someapp.service.*.*.."
publicvoidbusinessService{}
/**
*Adataaccessoperationistheexecutionofanymethoddefinedona
*daointerface.Thisdefinitionassumesthatinterfacesareplacedinthe
*"dao"package,andthatimplementationtypesareinsub-packages.
*/
@Pointcut"execution*com.xyz.someapp.dao.*.*.."
publicvoiddataAccessOperation{}
}
service
<aop:config>
<aop:advisor
pointcut="com.xyz.someapp.SystemArchitecture.businessService"
advice-ref="tx-advice"/>
</aop:config>
<tx:adviceid="tx-advice">
<tx:attributes>
<tx:methodname="*"propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
6.3“SchemaAOP” <aop:config><aop:advisor> 9
6.2.3.4.SpringAOP execution
executionmodifiers-pattern?ret-type-patterndeclaring-type-pattern?name-patternparam-pattern
throws-pattern?
ret-type-pattern (*) (*,String)
executionpublic**..
“set”
execution*set*..
AccountService
execution*com.xyz.service.AccountService.*..
service
execution*com.xyz.service.*.*..
service
execution*com.xyz.service..*.*..
serviceSpringAOP
withincom.xyz.service.*
serviceSpringAOP
withincom.xyz.service..*
AccountService SpringAOP
thiscom.xyz.service.AccountService
'this'-AccountService SpringAOP
targetcom.xyz.service.AccountService
'target'-SerializableSpringAOP
argsjava.io.Serializable
'args'- execution(**(java.io.Serializable))argsSerializableexecution Serializable
@Transactional SpringAOP
@targetorg.springframework.transaction.annotation.Transactional
'@target'- @Transactional SpringAOP
@withinorg.springframework.transaction.annotation.Transactional
'@within'- @Transactional SpringAOP
@annotationorg.springframework.transaction.annotation.Transactional
'@annotation'-@ClassifiedSpringAOP
@argscom.xyz.security.Classified
'@args'-' tradeService'Springbean SpringAOP
beantradeService
' *Service'Springbean SpringAOP
bean*Service
6.2.4.
6.2.4.1. @Before
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.Before;
@Aspect
publicclassBeforeExample{
@Before"com.xyz.myapp.SystemArchitecture.dataAccessOperation"
publicvoiddoAccessCheck{
//...
}
}
in-place
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.Before;
@Aspect
publicclassBeforeExample{
@Before"execution*com.xyz.myapp.dao.*.*.."
publicvoiddoAccessCheck{
//...
}
}
6.2.4.2.Afterreturningadvice @AfterReturning
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.AfterReturning;
@Aspect
publicclassAfterReturningExample{
@AfterReturning"com.xyz.myapp.SystemArchitecture.dataAccessOperation"
publicvoiddoAccessCheck{
//...
}
}
@AfterReturning
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.AfterReturning;
@Aspect
publicclassAfterReturningExample{
@AfterReturning
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation",
returning="retVal"
publicvoiddoAccessCheckObjectretVal{
//...
}
}
returning
6.2.4.3.Afterthrowingadvice@AfterThrowing
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.AfterThrowing;
@Aspect
publicclassAfterThrowingExample{
@AfterThrowing"com.xyz.myapp.SystemArchitecture.dataAccessOperation"
publicvoiddoRecoveryActions{
//...
}
}
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.AfterThrowing;
@Aspect
publicclassAfterThrowingExample{
@AfterThrowing
pointcut="com.xyz.myapp.SystemArchitecture.dataAccessOperation",
throwing="ex"
publicvoiddoRecoveryActionsDataAccessExceptionex{
//...
}
}
throwing
6.2.4.4.After(finally)advice@After
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.After;
@Aspect
publicclassAfterFinallyExample{
@After"com.xyz.myapp.SystemArchitecture.dataAccessOperation"
publicvoiddoReleaseLock{
//...
}
}
6.2.4.5. @Around ProceedingJoinPoint
proceed Object[]-Object[]AspectJ AspectJ
based AspectJSpring@AspectJ
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.Around;
importorg.aspectj.lang.ProceedingJoinPoint;
@Aspect
publicclassAroundExample{
@Around"com.xyz.myapp.SystemArchitecture.businessService"
publicObjectdoBasicProfilingProceedingJoinPointpjpthrowsThrowable{
//startstopwatch
ObjectretVal=pjp.proceed;
//stopstopwatch
returnretVal;
}
}
proceed()
6.2.4.6.AdviceparametersSpring2.0- Object[]
6.2.4.6.1.
org.aspectj.lang.JoinPoint ProceedingJoinPoint
JoinPoint getArgs() getThis()
getSignature() toString()JavaDoc
6.2.4.6.2.
@Before"com.xyz.myapp.SystemArchitecture.dataAccessOperation&&"+
"argsaccount,.."
publicvoidvalidateAccountAccountaccount{
//...
}
args(account,..)“” Account
@Pointcut"com.xyz.myapp.SystemArchitecture.dataAccessOperation&&"+
"argsaccount,.."
privatevoidaccountDataAccessOperationAccountaccount{}
@Before"accountDataAccessOperationaccount"
publicvoidvalidateAccountAccountaccount{
//...
}
AspectJthis target @within,@target,@annotation,@argsAudit@Auditable
@RetentionRetentionPolicy.RUNTIME
@TargetElementType.METHOD
public@interfaceAuditable{
AuditCodevalue;
}
@Auditable
@Before"com.xyz.lib.Pointcuts.anyPublicMethod&&"+
"@annotationauditable"
publicvoidauditAuditableauditable{
AuditCodecode=auditable.value;
//...
}
6.2.4.6.3.
"argNames"-
@Before
value="com.xyz.lib.Pointcuts.anyPublicMethod&&targetbean&&@annotationauditable",
argNames="bean,auditable"
publicvoidauditObjectbean,Auditableauditable{
AuditCodecode=auditable.value;
//...usecodeandbean
}
JoinPoint ProceedingJoinPoint JoinPoint.StaticPart“argNames”
@Before
value="com.xyz.lib.Pointcuts.anyPublicMethod&&targetbean&&@annotationauditable",
argNames="bean,auditable"
publicvoidauditJoinPointjp,Objectbean,Auditableauditable{
AuditCodecode=auditable.value;
//...usecode,bean,andjp
}
JoinPointProceedingJoinPoint JoinPoint.StaticPart“argNames” “argNames”
@Before
"com.xyz.lib.Pointcuts.anyPublicMethod"
publicvoidauditJoinPointjp{
//...usejp
}
'argNames' 'argNames'SpringAOPdebugdebugg:vars' 1@AspectJAspectJajcdebug
debugSpringAOPAmbiguousBindingException
IllegalArgumentException
6.2.4.6.4.
proceed() SpringAOPAspectJ
@Around"executionList<Account>find*..&&"+
"com.xyz.myapp.SystemArchitecture.inDataAccessLayer&&"+
"argsaccountHolderNamePattern"
publicObjectpreProcessQueryPatternProceedingJoinPointpjp,StringaccountHolderNamePattern
throwsThrowable{
StringnewPattern=preProcessaccountHolderNamePattern;
returnpjp.proceednewObject[]{newPattern};
}
6.2.4.7.SpringAOPAspectJ
Ordered.getValue()
javac
6.2.5.IntroductionAspectJinter-type@DeclareParentsservice UsageTracked JMX
@Aspect
publicclassUsageTracking{
@DeclareParentsvalue="com.xzy.myapp.service.*+",
defaultImpl=DefaultUsageTracked.class
publicstaticUsageTrackedmixin;
@Before"com.xyz.myapp.SystemArchitecture.businessService&&"+
"thisusageTracked"
publicvoidrecordUsageUsageTrackedusageTracked{
usageTracked.incrementUseCount;
}
}
@DeclareParents valueAspectJ-beanservicebeans UsageTrackedbean
UsageTrackedusageTracked=UsageTrackedcontext.getBean"myService";
6.2.6.AOPapplicationcontextAspectJpertarget percflowpercflowbelow pertypewithin"perthis" @Aspectperthis
@Aspect"perthiscom.xyz.myapp.SystemArchitecture.businessService"
publicclassMyAspect{
privateintsomeState;
@Beforecom.xyz.myapp.SystemArchitecture.businessService
publicvoidrecordServiceUsage{
//...
}
}
'perthis'service 'this'
service AspectJper-clauses'pertarget'“perthis”
6.2.7.
businessservicesPessimisticLockingFailureExceptionproceed()
@Aspect
publicclassConcurrentOperationExecutorimplementsOrdered{
privatestaticfinalintDEFAULT_MAX_RETRIES=2;
privateintmaxRetries=DEFAULT_MAX_RETRIES;
privateintorder=1;
publicvoidsetMaxRetriesintmaxRetries{
this.maxRetries=maxRetries;
}
publicintgetOrder{
returnthis.order;
}
publicvoidsetOrderintorder{
this.order=order;
}
@Around"com.xyz.myapp.SystemArchitecture.businessService"
publicObjectdoConcurrentOperationProceedingJoinPointpjpthrowsThrowable{
intnumAttempts=0;
PessimisticLockingFailureExceptionlockFailureException;
do{
numAttempts++;
try{
returnpjp.proceed;
}
catchPessimisticLockingFailureExceptionex{
lockFailureException=ex;
}
}
whilenumAttempts<=this.maxRetries;
throwlockFailureException;
}
}
OrdereddoConcurrentOperation businessService()
PessimisticLockingFailureExceptionSpring
<aop:aspectj-autoproxy/>
<beanid="concurrentOperationExecutor"
class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">
<propertyname="maxRetries"value="3"/>
<propertyname="order"value="100"/>
</bean>
idempotent Idempotent
@RetentionRetentionPolicy.RUNTIME
public@interfaceIdempotent{
//markerannotation
}
serviceidempotent
@Around"com.xyz.myapp.SystemArchitecture.businessService&&"+
"@annotationcom.xyz.myapp.service.Idempotent"
publicObjectdoConcurrentOperationProceedingJoinPointpjpthrowsThrowable{
...
}
6.3.SchemaAOP
Java5XMLSpring2.0"aop"
aop A,XMLSchema-basedconfigurationspring-aopschema A.2.7“Theschema”aop
Spring <aop:config> applicationcontext <aop:config>
<aop:config>pointcutadvisoraspect
<aop:config>Spring auto-proxyingauto-proxying
6.3.1.
schemaJavaapplicationcontextbean
<aop:aspect>backingbeanbean ref
<aop:config>
<aop:aspectid="myAspect"ref="aBean">
...
</aop:aspect>
</aop:config>
<beanid="aBean"class="...">
...
</bean>
bean" aBean"Springbean
6.3.2.
<aop:config>
serviceservice
<aop:config>
<aop:pointcutid="businessService"
expression="execution*com.xyz.myapp.service.*.*.."/>
</aop:config>
6.2“@AspectJ” AspectJ Java5schema@AspectsJDK1.4Java5AspectJAPIJDK1.5
<aop:config>
<aop:pointcutid="businessService"
expression="com.xyz.myapp.SystemArchitecture.businessService"/>
</aop:config>
6.2.3.3“” SystemArchitecture
<aop:config>
<aop:aspectid="myAspect"ref="aBean">
<aop:pointcutid="businessService"
expression="execution*com.xyz.myapp.service.*.*.."/>
...
</aop:aspect>
</aop:config>
@AspectJschema(collect)
<aop:config>
<aop:aspectid="myAspect"ref="aBean">
<aop:pointcutid="businessService"
expression="execution*com.xyz.myapp.service.*.*..&&thisservice"/>
<aop:beforepointcut-ref="businessService"method="monitor"/>
...
</aop:aspect>
</aop:config>
publicvoidmonitorObjectservice{
...
}
'&&'XML'and','or''not''&&','||''!'
<aop:config>
<aop:aspectid="myAspect"ref="aBean">
<aop:pointcutid="businessService"
expression="execution*com.xyz.myapp.service.*.*..
<aop:beforepointcut-ref="businessService"method="monitor"/>
...
</aop:aspect>
</aop:config>
XMLidschema
6.3.3.
@AspectJschema5
6.3.3.1.
<aop:aspect><aop:before>
<aop:aspectid="beforeExample"ref="aBean">
<aop:before
pointcut-ref="dataAccessOperation"
method="doAccessCheck"/>
...
</aop:aspect>
dataAccessOperation<aop:config>id pointcut-refpointcut
<aop:aspectid="beforeExample"ref="aBean">
<aop:before
pointcut="execution*com.xyz.myapp.dao.*.*.."
method="doAccessCheck"/>
...
</aop:aspect>
@AspectJMethoddoAccessCheck bean
6.3.3.2.
<aop:aspect>
<aop:aspectid="afterReturningExample"ref="aBean">
<aop:after-returning
pointcut-ref="dataAccessOperation"
method="doAccessCheck"/>
...
</aop:aspect>
@AspectJreturning
<aop:aspectid="afterReturningExample"ref="aBean">
<aop:after-returning
pointcut-ref="dataAccessOperation"
returning="retVal"
method="doAccessCheck"/>
...
</aop:aspect>
doAccessCheck retVal @AfterReturning
publicvoiddoAccessCheckObjectretVal{...
6.3.3.3.<aop:aspect> after-throwing
<aop:aspectid="afterThrowingExample"ref="aBean">
<aop:after-throwing
pointcut-ref="dataAccessOperation"
method="doRecoveryActions"/>
...
</aop:aspect>
@AspectJthrowing
<aop:aspectid="afterThrowingExample"ref="aBean">
<aop:after-throwing
pointcut-ref="dataAccessOperation"
throwing="dataAccessEx"
method="doRecoveryActions"/>
...
</aop:aspect>
doRecoveryActionsdataAccessEx @AfterThrowing
publicvoiddoRecoveryActionsDataAccessExceptiondataAccessEx{...
6.3.3.4.after
<aop:aspectid="afterFinallyExample"ref="aBean">
<aop:after
pointcut-ref="dataAccessOperation"
method="doReleaseLock"/>
...
</aop:aspect>
6.3.3.5.“” Aroundaop:around ProceedingJoinPoint
proceed() proceedObject[]-
<aop:aspectid="aroundExample"ref="aBean">
<aop:around
pointcut-ref="businessService"
method="doBasicProfiling"/>
...
</aop:aspect>
doBasicProfiling@AspectJ
publicObjectdoBasicProfilingProceedingJoinPointpjpthrowsThrowable{
//startstopwatch
ObjectretVal=pjp.proceed;
//stopstopwatch
returnretVal;
}
6.3.3.6.Schema-based@AspectJ
arg-names 6.2.4.6.3“” "argNames"
<aop:before
pointcut="com.xyz.lib.Pointcuts.anyPublicMethodand@annotationauditable"
method="audit"
arg-names="auditable"/>
arg-names
XSD
packagex.y.service;
publicinterfaceFooService{
FoogetFooStringfooName,intage;
}
publicclassDefaultFooServiceimplementsFooService{
publicFoogetFooStringname,intage{
returnnewFooname,age;
}
}
profile.. profile..
packagex.y;
importorg.aspectj.lang.ProceedingJoinPoint;
importorg.springframework.util.StopWatch;
publicclassSimpleProfiler{
publicObjectprofileProceedingJoinPointcall,Stringname,intagethrowsThrowable{
StopWatchclock=newStopWatch
"Profilingfor'"+name+"'and'"+age+"'";
try{
clock.startcall.toShortString;
returncall.proceed;
}finally{
clock.stop;
System.out.printlnclock.prettyPrint;
}
}
}
XML
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--thisistheobjectthatwillbeproxiedbySpring'sAOPinfrastructure-->
<beanid="fooService"class="x.y.service.DefaultFooService"/>
<!--thisistheactualadviceitself-->
<beanid="profiler"class="x.y.SimpleProfiler"/>
<aop:config>
<aop:aspectref="profiler">
<aop:pointcutid="theExecutionOfSomeFooServiceMethod"
expression="execution*x.y.service.FooService.getFooString,int
andargsname,age"/>
<aop:aroundpointcut-ref="theExecutionOfSomeFooServiceMethod"
method="profile"/>
</aop:aspect>
</aop:config>
</beans>
importorg.springframework.beans.factory.BeanFactory;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
importx.y.service.FooService;
publicfinalclassBoot{
publicstaticvoidmainfinalString[]argsthrowsException{
BeanFactoryctx=newClassPathXmlApplicationContext"x/y/plain.xml";
FooServicefoo=FooServicectx.getBean"fooService";
foo.getFoo"Pengo",12;
}
}
StopWatch'Profilingfor'Pengo'and'12'':runningtimemillis=0
-----------------------------------------
ms%Taskname
-----------------------------------------
00000?executiongetFoo
6.3.3.7. 6.2.4.7“” bean
6.3.4.AspectJinter-typeaop:aspectaop:declare-parents DefaultUsageTrackedservice UsageTracked
<aop:aspectid="usageTrackerAspect"ref="usageTracking">
<aop:declare-parents
types-matching="com.xzy.myapp.service.*+"
implement-interface="com.xyz.myapp.service.tracking.UsageTracked"
default-impl="com.xyz.myapp.service.tracking.DefaultUsageTracked"/>
<aop:before
pointcut="com.xyz.myapp.SystemArchitecture.businessService
andthisusageTracked"
method="recordUsage"/>
</aop:aspect>
usageTrackingbean
publicvoidrecordUsageUsageTrackedusageTracked{
usageTracked.incrementUseCount;
}
implement-interface types-matchingAspectJbean serevicebean UsageTracked bean
UsageTrackedusageTracked=UsageTrackedcontext.getBean"myService";
6.3.5.Schemasinglton
6.3.6.Advisor"advisor"Spring1.2AOPAspectJ advisorbean“Spring” AdvisorAspectJ
Spring2.0<aop:advisor>advisor transactionaladviceSpring2.0
<aop:config>
<aop:pointcutid="businessService"
expression="execution*com.xyz.myapp.service.*.*.."/>
<aop:advisor
pointcut-ref="businessService"
advice-ref="tx-advice"/>
</aop:config>
<tx:adviceid="tx-advice">
<tx:attributes>
<tx:methodname="*"propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
pointcut-ref pointcutadvisor orderadvisor Ordered
6.3.7.6.2.7“” schemabusinessservicesIdempotentproceed() schemaJava
publicclassConcurrentOperationExecutorimplementsOrdered{
privatestaticfinalintDEFAULT_MAX_RETRIES=2;
privateintmaxRetries=DEFAULT_MAX_RETRIES;
privateintorder=1;
publicvoidsetMaxRetriesintmaxRetries{
this.maxRetries=maxRetries;
}
publicintgetOrder{
returnthis.order;
}
publicvoidsetOrderintorder{
this.order=order;
}
publicObjectdoConcurrentOperationProceedingJoinPointpjpthrowsThrowable{
intnumAttempts=0;
PessimisticLockingFailureExceptionlockFailureException;
do{
numAttempts++;
try{
returnpjp.proceed;
}
catchPessimisticLockingFailureExceptionex{
lockFailureException=ex;
}
}
whilenumAttempts<=this.maxRetries;
throwlockFailureException;
}
}
Ordered doConcurrentOperation OptimisticLockingFailureException
@AspectJ
Spring
<aop:config>
<aop:aspectid="concurrentOperationRetry"ref="concurrentOperationExecutor">
<aop:pointcutid="idempotentOperation"
expression="execution*com.xyz.myapp.service.*.*.."/>
<aop:around
pointcut-ref="idempotentOperation"
method="doConcurrentOperation"/>
</aop:aspect>
</aop:config>
<beanid="concurrentOperationExecutor"
class="com.xyz.myapp.service.impl.ConcurrentOperationExecutor">
<propertyname="maxRetries"value="3"/>
<propertyname="order"value="100"/>
</bean>
bussinessservicesidempotent
@RetentionRetentionPolicy.RUNTIME
public@interfaceIdempotent{
//markerannotation
}
serviceidempotent
<aop:pointcutid="idempotentOperation"
expression="execution*com.xyz.myapp.service.*.*..and
@annotationcom.xyz.myapp.service.Idempotent"/>
6.4.AOPSpringAOPAspectJ
6.4.1.SpringAOPAspectJSpringAOPAspectJ AspectJdomainSpringAspectJ getsetAspectJAspectJ“”@AspectJAspectJDevelopmentTools(AJDT)AspectJ:-@AspectJ IDEJava
6.4.2.SpringAOP@AspectJXMLSpringAOP@AspectJXMLXMLSpringJava Java5+XMLXML DRY@AspectJ"singleton" XML@AspectJ
@Pointcut(execution(*get*()))
publicvoidpropertyAccess(){}
@Pointcut(execution(org.xyz.Account+*(..))
publicvoidoperationReturningAnAccount(){}
@Pointcut(propertyAccess()&&operationReturningAnAccount())
publicvoidaccountPropertyAccess(){}
XML
<aop:pointcutid="propertyAccess"
expression="execution(*get*())"/>
<aop:pointcutid="operationReturningAnAccount"
expression="execution(org.xyz.Account+*(..))"/>
accountPropertyAccess
@AspectJ @AspectJ“”
6.5.@AspectJ schema-definedadvisorSpring1.2
6.6.SpringAOPJDKCGLIBJDKJDKCGLIB
advise Final
CGLIB2classpathJDK
CGLIBCGLIB <aop:config>proxy-target-classtrue:
<aop:configproxy-target-class="true">
<!--otherbeansdefinedhere...-->
</aop:config>
@AspectJCGLIB <aop:aspectj-autoproxy>proxy-target-classtrue:
<aop:aspectj-autoproxyproxy-target-class="true"/>
<aop:config/> <aop:config/>
<tx:annotation-driven/><aop:aspectj-autoproxy/><tx:annotation-driven/> <aop:aspectj-autoproxy/>
<aop:config/>' proxy-target-class="true"'CGLIB
6.6.1.AOPSpringAOP SpringSpringAOPPOJO
publicclassSimplePojoimplementsPojo{
publicvoidfoo(){
//thisnextmethodinvocationisadirectcallonthe'this'reference
this.bar();
}
publicvoidbar(){
//somelogic...
}
}
publicclassMain{
publicstaticvoidmain(String[]args){
Pojopojo=newSimplePojo();
//thisisadirectmethodcallonthe'pojo'reference
pojo.foo();
}
}
publicclassMain{
publicstaticvoidmain(String[]args){
ProxyFactoryfactory=newProxyFactory(newSimplePojo());
factory.addInterface(Pojo.class);
factory.addAdvice(newRetryAdvice());
Pojopojo=(Pojo)factory.getProxy();
//thisisamethodcallontheproxy!
pojo.foo();
}
}
Mainmain(..)
publicclassSimplePojoimplementsPojo{
publicvoidfoo(){
//thisworks,but...gah!
((Pojo)AopContext.currentProxy()).bar();
}
publicvoidbar(){
//somelogic...
}
}
SpringAOP AOP AOP
publicclassMain{
publicstaticvoidmain(String[]args){
ProxyFactoryfactory=newProxyFactory(newSimplePojo());
factory.adddInterface(Pojo.class);
factory.addAdvice(newRetryAdvice());
factory.setExposeProxy(true);
Pojopojo=(Pojo)factory.getProxy();
//thisisamethodcallontheproxy!
pojo.foo();
}
}
AspectJAOP
6.7.@AspectJ<aop:config><aop:aspectj-autoproxy> SpringAOPAPIorg.springframework.aop.aspectj.annotation.AspectJProxyFactory
@AspectJJavadoc
//createafactorythatcangenerateaproxyforthegiventargetobject
AspectJProxyFactoryfactory=newAspectJProxyFactory(targetObject);
//addanaspect,theclassmustbean@AspectJaspect
//youcancallthisasmanytimesasyouneedwithdifferentaspects
factory.addAspect(SecurityManager.class);
//youcanalsoaddexistingaspectinstances,thetypeoftheobjectsuppliedmustbean@AspectJaspect
factory.addAspect(usageTracker);
//nowgettheproxyobject...
MyInterfaceTypeproxy=factory.getProxy();
6.8.SpringAspectJSpringAOPAspectJcompiler/weaverSpringAspectJaspectlibrary spring-aspects.jar
“SpringAspectJdomainobject” 6.8.2“SpringAspectJ” AspectJ” AspectJcompilerAspectJ 6.8.4“SpringAspectJLTW”Springload-timeweaving
6.8.1.SpringAspectJdomainobjectSpringapplicationcontextbeanbeanfactoryaspects.jarannotation-driven @ConfigurableSpring-driven
packagecom.xyz.myapp.domain;
importorg.springframework.beans.factory.annotation.Configurable;
@Configurable
publicclassAccount{
//...
}
Spring Account
id
<beanclass="com.xyz.myapp.domain.Account"scope="prototype">
<propertyname="fundsTransferService"ref="fundsTransferService"/>
</bean>
bean
packagecom.xyz.myapp.domain;
importorg.springframework.beans.factory.annotation.Configurable;
@Configurable("account")
publicclassAccount{
//...
}
Spring"account"bean Account
@Configurable autowire
@Configurable(autowire=Autowire.BY_TYPE)
@Configurable(autowire=Autowire.BY_NAME Spring2.5@Resource@Configurablebeans 3.11“Annotation-based”
dependencyCheckSpring@Configurable(autowire=Autowire.BY_NAME,dependencyCheck=true)
trueSpringprimitivescollectionsspring-aspects.jar AnnotationBeanConfigurerAspect
@Configurable Spring” readResolve()
“ inessence”“ ”...@Configurable
@Configurable(preConstruction=true)
AspectJProgrammingGuideAspectJAspectJweaver-ant/maven 6.8.4“SpringAspectJLTW” AnnotationBeanConfigurerAspect
SpringbeanfactorybeanfactorySpringcontext
<context:spring-configured/>
DTDSchema
<bean
class="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"
factory-method="aspectOf"/>
@Configurablelogwarningbean"depends-on"beanconfiguration
<beanid="myService"
class="com.xzy.myapp.service.MyService"
depends-on="org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect">
<!--...-->
</bean>
6.8.1.1.@Configurable@Configurabledomainobject
stub @ConfigurableAspectJ
6.8.1.2.Workingwithmultipleapplicationcontexts
6.8.1.2.WorkingwithmultipleapplicationcontextsAnnotationBeanConfigurerAspectAspectJsingleton @Configurable
singleton classloader<aop:spring-configured/>beanclasspath spring-aspects.jar
Springwebapplicationcontextbusinessservicecontextcontext classloader AnnotationBeanConfigurerAspect
contextapplicationcontext <aop:spring-configured/>
service domainobjectapplicationcontextobjectbeanweb-appweb-applicationclassloaderaspects.jarWEB-INF/lib spring-aspects.jarclasspathclassloader webapplicationaspect
6.8.2.SpringAspectJ@Configurable spring-aspects.jarAspectJ
SpringSpring@Transactional AnnotationTransactionAspectAspectJJava
@Transactional public@Transactional publicprotecteddefault
AspectJSpringAbstractBeanConfigurerAspectAbstractTransactionAspectJavadocbean domianobject
publicaspectDomainObjectConfigurationextendsAbstractBeanConfigurerAspect{
publicDomainObjectConfiguration(){
setBeanWiringInfoResolver(newClassNameBeanWiringInfoResolver());
}
//thecreationofanewbean(anyobjectinthedomainmodel)
protectedpointcutbeanCreation(ObjectbeanInstance):
initialization(new(..))&&
SystemArchitecture.inDomainModel()&&
this(beanInstance);
}
6.8.3.SpringIoCAspectJSpringapplicationAspectJSpringAspectJAspectJinstantiationmodel(per-clause)AspectJ singleton beanbeanSpringAspectJ
<beanid="profiler"class="com.xyz.profiler.Profiler"
factory-method="aspectOf">
<propertyname="profilingStrategy"ref="jamonProfilingStrategy"/>
</bean>
non-singletonbean spring-aspects.jar
runtime@AspectJAspectJload-timedomainobjectSpringSpringAOP @AspectJ beanSpringAOP
<aop:aspectj-autoproxy>
<aop:includename="thisBean"/>
<aop:includename="thatBean"/>
</aop:aspectj-autoproxy>
<aop:aspectj-autoproxy/> SpringAOP@AspectJAspectJ
6.8.4.SpringAspectJLTWLoad-timeweavingLTWAspectJLTWLTW LTWAspectJLTWSpringDevelopmentEnvironmentGuide
SpringAspectJLTWJava5+JVMSpringLTW
LTW -javaagent:path/to/aspectjweaver.jar()-javaagent:path/to/spring-agent.jar LTWSpringAspectJLTW
6.8.4.1. @AspectJ
packagefoo;
importorg.aspectj.lang.ProceedingJoinPoint;
importorg.aspectj.lang.annotation.Aspect;
importorg.aspectj.lang.annotation.Around;
importorg.aspectj.lang.annotation.Pointcut;
importorg.springframework.util.StopWatch;
importorg.springframework.core.annotation.Order;
@Aspect
publicclassProfilingAspect{
@Around("methodsToBeProfiled()")
publicObjectprofile(ProceedingJoinPointpjp)throwsThrowable{
StopWatchsw=newStopWatch(getClass().getSimpleName());
try{
sw.start(pjp.getSignature().getName());
returnpjp.proceed();
}finally{
sw.stop();
System.out.println(sw.prettyPrint());
}
}
@Pointcut("execution(public*foo..*.*(..))")
publicvoidmethodsToBeProfiled(){}
}
“ META-INF/aop.xml”AspectJweaver ProfilingAspectJavaclasspath“ META-INF/aop.xml”AspectJ
<!DOCTYPEaspectjPUBLIC
"-//AspectJ//DTD//EN""http://www.eclipse.org/aspectj/dtd/aspectj.dtd">
<aspectj>
<weaver>
<!--onlyweaveclassesinourapplication-specificpackages-->
<includewithin="foo.*"/>
</weaver>
<aspects>
<!--weaveinjustthisaspect-->
<aspectname="foo.ProfilingAspect"/>
</aspects>
</aspectj>
Spring LoadTimeWeaver“ META-INF/aop.xml
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">
<!--aserviceobject;wewillbeprofilingit'smethods-->
<beanid="entitlementCalculationService"
class="foo.StubEntitlementCalculationService"/>
<!--thisswitchesontheload-timeweaving-->
<context:load-time-weaver/>
</beans>
- META-INF/aop.xmlSpring- main(..)LTW
packagefoo;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
publicfinalclassMain{
publicstaticvoidmain(String[]args){
ApplicationContextctx=newClassPathXmlApplicationContext("beans.xml",Main.class);
EntitlementCalculationServiceentitlementCalculationService
=(EntitlementCalculationService)ctx.getBean("entitlementCalculationService");
//theprofilingaspectis'woven'aroundthismethodexecution
entitlementCalculationService.calculateEntitlement();
}
}
Spring per-ClassLoaderLTW
java-javaagent:C:/projects/foo/lib/global/spring-agent.jarfoo.Main
-javaagentJava5+ JVM SpringInstrumentationSavingAgentjavaagent spring-agent.jar
Main calculateEntitlement()Thread.sleep(..)AOP
Calculatingentitlement
StopWatch'ProfilingAspect':runningtime(millis)=1234
---------------------------------------
ms%Taskname
---------------------------------------
01234100%calculateEntitlement
LTWAspectJSpringbeans
packagefoo;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
publicfinalclassMain{
publicstaticvoidmain(String[]args){
newClassPathXmlApplicationContext("beans.xml",Main.class);
EntitlementCalculationServiceentitlementCalculationService=
newStubEntitlementCalculationService();
//theprofilingaspectwillbe'woven'aroundthismethodexecution
entitlementCalculationService.calculateEntitlement();
}
}
SpringSpring StubEntitlementCalculationService
SpringLTW
ProfilingAspect
6.8.4.2.LTWAspectJAspectJ@AspectJ
classpath
6.8.4.3.'META-INF/aop.xml'AspectJLTWJavaclasspathAspectJ
6.8.4.4.JARSSpringAspectJLTW
spring.jar2.5
aspectjrt.jar1.5
aspectjweaver.jar1.5Springinstrumentation
spring-agent.jar
6.8.4.5.SpringSpring LTW LoadTimeWeaver
org.springframework.instrument.classloading SpringLoadTimeWeaver java.lang.instrument.ClassFileTransformers
ClassLoaderLTW
java.lang.instrument
XML ApplicationContext LoadTimeWeaverSpring- BeanFactory LTW BeanFactoryPostProcessors
SpringLTW LoadTimeWeaver <context:load-time-weaver/>
<context:load-time-weaver/>
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:load-time-weaver/>
</beans>
<context:load-time-weaver/>bean LTWbeansAspectJWeavingEnabler <context:load-time-weaver/>contextXMLSchemaSpring2.5
LoadTimeWeaverbean LoadTimeWeaver
LoadTimeWeaver LoadTimeWeaver“”
6.1. DefaultContextLoadTimeWeaver
LoadTimeWeaversDefaultContextLoadTimeWeaver
LoadTimeWeavers
LoadTimeWeaver
BEA'sWeblogic10 WebLogicLoadTimeWeaver
Oracle'sOC4J OC4JLoadTimeWeaver
GlassFish GlassFishLoadTimeWeaver
SpringInstrumentationSavingAgent
JVM(java-javaagent:path/to/spring-agent.jar)
InstrumentationLoadTimeWeaver
( TomcatInstrumentableClassLoaderResin)ReflectiveLoadTimeWeaver
DefaultContextLoadTimeWeaver LoadTimeWeaverstime-weaver/> weaver-class LoadTimeWeaver
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:load-time-weaver
weaver-class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"
</beans>
<context:load-time-weaver/> LoadTimeWeaverSpringLoadTimeWeaverSpringLTW ClassFileTransformers
ClassFileTransformer ClassPreProcessorAgentAdapter
org.aspectj.weaver.loadtimeLTW ClassPreProcessorAgentAdapter
javadoc<context:load-time-weaver/> aspectj-weavingLTW
autodetect
6.2.aspectj-weaving
on AspectJ
off LTW...
autodetect SpringLTW META-INF/aop.xmlAspectJ
6.8.4.6.webSpringLTW
6.8.4.6.1.Java
JavaSpringSpringLTW agent.jar
6.8.4.6.2.Tomcat
ApacheTomcat5.0webSpring TomcatInstrumentableClassLoader
TomcatTomcatWAR server.xml
spring-tomcat-weaver.jarTomcat commonlib
<Contextpath="/myWebApp"docBase="/my/webApp/location">
<LoaderloaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
useSystemClassLoaderAsParent="false"/>
</Context>
LTWTomcat5.5.20 ClassLoader
TomcatSpring webTomcatTomcat 12.6.1.3.1“Tomcat5.0”Tomcat
6.8.4.6.3.WebLogic,OC4J,Resin,GlassFish
BEAWebLogic10OracleJavaEEOC4J10.1.3.1 SrpingLTWAspectJjavaagent:path/to/spring-agent.jar
GlassFishEAR GlassFishwebtomcat
6.9.AspectJ AspectJwebsite
EclipseAspectJAdrianColyer(Addison-Wesley,2005) AspectJAspectJinActionRamnivasLaddad(Manning,2003)AOPAOP
7SpringAOPAPIs
7.1.7.2.SpringAPI
7.2.1.7.2.2.7.2.3.AspectJ7.2.4.7.2.5.7.2.6.
7.3.SpringAPI7.3.1.7.3.2.Spring
7.4.SpringAdvisorAPI7.5.ProxyFactoryBeanAOP
7.5.1.7.5.2.JavaBean7.5.3.JDKCGLIB7.5.4.7.5.5.7.5.6.“”
7.6.7.7.ProxyFactoryAOP7.8.7.9.“autoproxy”
7.9.1.bean7.9.2.
7.10.TargetSource7.10.1.7.10.2.7.10.3.7.10.4.ThreadLocal
7.11.Advice7.12.
7.1.Spring2.0@AspectJSchemaAOPSpringAOPAPISpring2.0AOP Spring1.2Spring2.0Spring1.2Spring2.0
7.2.SpringAPISpring
7.2.1.Springadvicepointcutorg.springframework.aop.Pointcut
publicinterfacePointcut{
ClassFiltergetClassFilter();
MethodMatchergetMethodMatcher();
}
Pointcut “”ClassFilter matches()true
publicinterfaceClassFilter{
booleanmatches(Classclazz);
}
MethodMatcher
publicinterfaceMethodMatcher{
booleanmatches(Methodm,ClasstargetClass);
booleanisRuntime();
booleanmatches(Methodm,ClasstargetClass,Object[]args);
}
matches(Method,Class) AOPisRuntime()true matches(Method,Class,Object[])MethodMatcher isRuntime()false matches(Method,Class,
Object[])
AOPAOP
7.2.2.Spring
org.springframework.aop.support.PointcutsAspectJ
7.2.3.AspectJ2.0Springorg.springframework.aop.aspectj.AspectJExpressionPointcutAspectJAspectJAspectJ
7.2.4.Spring
7.2.4.1.Spring
7.2.4.1.1.
SpringAOPorg.springframework.aop.support.Perl5RegexpMethodPointcut
Perl5RegexpMethodPointcutJakartaORO SpringJdkRegexpMethodPointcutJDK1.4Perl5RegexpMethodPointcut true
<beanid="settersAndAbsquatulatePointcut"
class="org.springframework.aop.support.Perl5RegexpMethodPointcut">
<propertyname="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
Spring RegexpMethodPointcutAdvisorbeforeadvicethrowsadvice J2SE1.4Spring JdkRegexpMethodPointcut
Perl5RegexpMethodPointcut perl5truePerl5RegexpMethodPointcutRegexpMethodPointcutAdvisorbeanadvisor
<beanid="settersAndAbsquatulateAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor">
<propertyname="advice">
<reflocal="beanNameOfAopAllianceInterceptor"/>
</property>
<propertyname="patterns">
<list>
<value>.*set.*</value>
<value>.*absquatulate</value>
</list>
</property>
</bean>
RegexpMethodPointcutAdvisor
7.2.4.1.2.
(metadata-driven)
7.2.4.2.
7.2.4.2.1.
SpringAspectJcflow SomeCallerorg.springframework.aop.support.ControlFlowPointcut
Java1.4
7.2.5.SpringStaticMethodMatcherPointcut
classTestStaticPointcutextendsStaticMethodMatcherPointcut{
publicbooleanmatches(Methodm,ClasstargetClass){
//returntrueifcustomcriteriamatch
}
}
Spring1.0RC2
7.2.6.SpringAOPJavaAspectJ
Spring“”JAC“”
7.3.SpringAPISPringAOP
7.3.1.SpringbeanadvisormixinAOP
7.3.2.SpringSpring
7.3.2.1.SpringinterceptionaroundadviceSpringAOPMethodInterceptor
publicinterfaceMethodInterceptorextendsInterceptor{
Objectinvoke(MethodInvocationinvocation)throwsThrowable;
}
invoke()MethodInvocation AOPMethodInterceptor
publicclassDebugInterceptorimplementsMethodInterceptor{
publicObjectinvoke(MethodInvocationinvocation)throwsThrowable{
System.out.println("Before:invocation=["+invocation+"]");
Objectrval=invocation.proceed();
System.out.println("Invocationreturned");
returnrval;
}
}
MethodInvocationproceed() proceed()MethodInterceptorproceed
MethodInterceptorAOPMethodInterceptorAOP AOP
7.3.2.2.beforeadvice MethodInvocation
proceed()MethodBeforeAdvice SpringAPISpring
publicinterfaceMethodBeforeAdviceextendsBeforeAdvice{
voidbefore(Methodm,Object[]args,Objecttarget)throwsThrowable;
}
void Spring
publicclassCountingBeforeAdviceimplementsMethodBeforeAdvice{
privateintcount;
publicvoidbefore(Methodm,Object[]args,Objecttarget)throwsThrowable{
++count;
}
publicintgetCount(){
returncount;
}
}
7.3.2.3.throwsadvice Springtypedthrowsadvice
org.springframework.aop.ThrowsAdvice :
afterThrowing([Method,args,target],subclassOfThrowable)
RemoteException
publicclassRemoteThrowsAdviceimplementsThrowsAdvice{
publicvoidafterThrowing(RemoteExceptionex)throwsThrowable{
//Dosomethingwithremoteexception
}
}
ServletException 4
publicclassServletThrowsAdviceWithArgumentsimplementsThrowsAdvice{
publicvoidafterThrowing(Methodm,Object[]args,Objecttarget,ServletExceptionex){
//Dosomethingwithallarguments
}
}
RemoteExceptionServletException
publicstaticclassCombinedThrowsAdviceimplementsThrowsAdvice{
publicvoidafterThrowing(RemoteExceptionex)throwsThrowable{
//Dosomethingwithremoteexception
}
publicvoidafterThrowing(Methodm,Object[]args,Objecttarget,ServletExceptionex){
//Dosomethingwithallarguments
}
}
7.3.2.4.
SpringAfter Returning adviceorg.springframework.aop.AfterReturningAdvice
publicinterfaceAfterReturningAdviceextendsAdvice{
voidafterReturning(ObjectreturnValue,Methodm,Object[]args,Objecttarget)
throwsThrowable;
}
publicclassCountingAfterReturningAdviceimplementsAfterReturningAdvice{
privateintcount;
publicvoidafterReturning(ObjectreturnValue,Methodm,Object[]args,Objecttarget)
throwsThrowable{
++count;
}
publicintgetCount(){
returncount;
}
}
7.3.2.5.SpringintroductionadviceIntroductionAdvisor, IntroductionInterceptor,
publicinterfaceIntroductionInterceptorextendsMethodInterceptor{
booleanimplementsInterface(Classintf);
}
AOPMethodInterceptorinvoke() -- IntroductionAdvisor
publicinterfaceIntroductionAdvisorextendsAdvisor,IntroductionInfo{
ClassFiltergetClassFilter();
voidvalidateInterfaces()throwsIllegalArgumentException;
}
publicinterfaceIntroductionInfo{
Class[]getInterfaces();
}
MethodMatcher Pointcut
getInterfaces()
validateInterfaces()IntroductionInterceptor
Spring
publicinterfaceLockable{
voidlock();
voidunlock();
booleanlocked();
}
mixinLockablelockunlockLockedException AOP
IntroductionInterceptor
org.springframework.aop.support.DelegatingIntroductionInterceptor
IntroductionInterceptor DelegatingIntroductionInterceptor
DelegatingIntroductionInterceptor ()DelegatingIntroductionInterceptor LockMixin
DelegatingIntroductionInterceptor IntroductionInterceptorLockMixin suppressInterface(Classintf)
IntroductionInterceptor IntroductionAdvisorLockMixinDelegatingIntroductionInterceptorLockable Lockable
locked
publicclassLockMixinextendsDelegatingIntroductionInterceptor
implementsLockable{
privatebooleanlocked;
publicvoidlock(){
this.locked=true;
}
publicvoidunlock(){
this.locked=false;
}
publicbooleanlocked(){
returnthis.locked;
}
publicObjectinvoke(MethodInvocationinvocation)throwsThrowable{
if(locked()&&invocation.getMethod().getName().indexOf("set")==0)
thrownewLockedException();
returnsuper.invoke(invocation);
}
}
invoke() DelegatingIntroductionInterceptor
lockedsetterLockMixin - Lockable
publicclassLockMixinAdvisorextendsDefaultIntroductionAdvisor{
publicLockMixinAdvisor(){
super(newLockMixin(),Lockable.class);
}
}
IntroductionAdvisorIntroductionInterceptor
LockMixinAdvisorLockMixinAdvised.addAdvisor()XML“”
7.4.SpringAdvisorAPISpringAdvisoradvisororg.springframework.aop.support.DefaultPointcutAdvisor
MethodInterceptorBeforeAdvice ThrowsAdvice
SpringAOP Spring
7.5.ProxyFactoryBeanAOPSpringIoCApplicationContextBeanFactory----SpringAOPFactoryBean bean
Spring2.0AOPbeanSpringAOPorg.springframework.aop.framework.ProxyFactoryBean
7.5.1.FactoryBean ProxyFactoryBean fooProxyFactoryBean foo
ProxyFactoryBean ProxyFactoryBeangetObject() AOPProxyFactoryBeanIoCAOPIoC
7.5.2.JavaBeanSpring FactoryBean ProxyFactoryBeanJavaBean
CGLIB 7.5.3“JDKCGLIB”
org.springframework.aop.framework.ProxyConfigSpringAOP
proxyTargetClasstrue trueCGLIB 7.5.3“JDKCGLIB”
optimizeCGLIB AOPCGLIB
frozenfrozen
exposeProxyThreadLocal exposeProxy
AopContext.currentProxy()
aopProxyFactoryAopProxyFactoryCGLIB1.1
ProxyFactoryBean
proxyInterfaces CGLIB
interceptorNamesAdvisorbeanbeanbean
*
getObject() FactoryBean
7.5.3.JDKCGLIBProxyFactryBean
ProxyFactoryBeanJDKCGLIB1.2.x2.0TransactionProxyFactoryBean
CGLIBCGLIB ProxyFactoryBeanproxyTargetClassfalsebean
ProxyFactoryBean
ProxyFactoryBeanproxyTargetClasstrueCGLIBProxyFactoryBeanproxyInterfaces proxyTargetClass
ProxyFactoryBeanproxyInterfacesJDKproxyInterfaces
ProxyFactoryBeanproxyInterfaces ProxyFactoryBean
proxyInterfaces
7.5.4.ProxyFactoryBean
beanbean“personTarget”
AOPbeanpersonTargetbean
<beanid="personTarget"class="com.mycompany.PersonImpl">
<propertyname="name"><value>Tony</value></property>
<propertyname="age"><value>51</value></property>
</bean>
<beanid="myAdvisor"class="com.mycompany.MyAdvisor">
<propertyname="someProperty"><value>Customstringpropertyvalue</value></property>
</bean>
<beanid="debugInterceptor"class="org.springframework.aop.interceptor.DebugInterceptor">
</bean>
<beanid="person"
class="org.springframework.aop.framework.ProxyFactoryBean">
<propertyname="proxyInterfaces"><value>com.mycompany.Person</value></property>
<propertyname="target"><reflocal="personTarget"/></property>
<propertyname="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean>
interceptorNamesbean ,
beanProxyFactoryBeansingletonfalse“person”beanPerson
Personperson=(Person)factory.getBean("person");
IoCbeanbeanJava
<beanid="personUser"class="com.mycompany.PersonUser">
<propertyname="person"><reflocal="person"/></property>
</bean>
PersonUserPersonAOP“”person
bean ProxyFactoryBean
<beanid="myAdvisor"class="com.mycompany.MyAdvisor">
<propertyname="someProperty"><value>Customstringpropertyvalue</value></property>
</bean>
<beanid="debugInterceptor"class="org.springframework.aop.interceptor.DebugInterceptor"/>
<beanid="person"class="org.springframework.aop.framework.ProxyFactoryBean">
<propertyname="proxyInterfaces"><value>com.mycompany.Person</value></property>
<!--Useinnerbean,notlocalreferencetotarget-->
<propertyname="target">
<beanclass="com.mycompany.PersonImpl">
<propertyname="name"><value>Tony</value></property>
<propertyname="age"><value>51</value></property>
</bean>
</property>
<propertyname="interceptorNames">
<list>
<value>myAdvisor</value>
<value>debugInterceptor</value>
</list>
</property>
</bean>
PersonSpringIoC ProxyFactoryBean
7.5.5.
Person Person SpringCGLIBProxyFactoryBeanproxyTargetClasstrue CGLIBCGLIB SpringCGLIB
Final
CGLIB2JDKCGLIBSpring1.0
7.5.6.“”bean“”
<beanid="proxy"class="org.springframework.aop.framework.ProxyFactoryBean">
<propertyname="target"ref="service"/>
<propertyname="interceptorNames">
<list>
<value>globa*</value>
</list>
</property>
</bean>
<beanid="global_debug"class="org.springframework.aop.interceptor.DebugInterceptor"/>
<beanid="global_performance"class="org.springframework.aop.interceptor.PerformanceMonitorInterceptor"/>
7.6.beanbeanbeanbeanbean
<beanid="txProxyTemplate"abstract="true"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<propertyname="transactionManager"ref="transactionManager"/>
<propertyname="transactionAttributes">
<props>
<propkey="*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
beanbeanbeanbean
<beanid="myService"parent="txProxyTemplate">
<propertyname="target">
<beanclass="org.springframework.samples.MyServiceImpl">
</bean>
</property>
</bean>
<beanid="mySpecialService"parent="txProxyTemplate">
<propertyname="target">
<beanclass="org.springframework.samples.MySpecialServiceImpl">
</bean>
</property>
<propertyname="transactionAttributes">
<props>
<propkey="get*">PROPAGATION_REQUIRED,readOnly</prop>
<propkey="find*">PROPAGATION_REQUIRED,readOnly</prop>
<propkey="load*">PROPAGATION_REQUIRED,readOnly</prop>
<propkey="store*">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
abstractbeanabstract beanabstracttrue
7.7.ProxyFactoryAOPSpringAOPSpringAOPSpringIoC
ProxyFactoryfactory=newProxyFactory(myBusinessInterfaceImpl);
factory.addInterceptor(myMethodInterceptor);
factory.addAdvisor(myAdvisor);
MyBusinessInterfacetb=(MyBusinessInterface)factory.getProxy();
org.springframework.aop.framework.ProxyFactoryProxyFactoryIntroductionInterceptionAroundAdvisorProxyFactory AdvisedSupport AdvisedSupportProxyFactoryProxyFactoryBean
AOPIoCJavaAOP
7.8.AOP org.springframework.aop.framework.Advised AOP
Advisor[]getAdvisors();
voidaddAdvice(Adviceadvice)throwsAopConfigException;
voidaddAdvice(intpos,Adviceadvice)
throwsAopConfigException;
voidaddAdvisor(Advisoradvisor)throwsAopConfigException;
voidaddAdvisor(intpos,Advisoradvisor)throwsAopConfigException;
intindexOf(Advisoradvisor);
booleanremoveAdvisor(Advisoradvisor)throwsAopConfigException;
voidremoveAdvisor(intindex)throwsAopConfigException;
booleanreplaceAdvisor(Advisora,Advisorb)throwsAopConfigException;
booleanisFrozen();
getAdvisors()DefaultPointcutAdvisorMethodInterceptor
addAdvisor() DefaultPointcutAdvisor
AOP Advised
Advisedadvised=(Advised)myObject;
Advisor[]advisors=advised.getAdvisors();
intoldAdvisorCount=advisors.length;
System.out.println(oldAdvisorCount+"advisors");
//Addanadvicelikeaninterceptorwithoutapointcut
//Willmatchallproxiedmethods
//Canuseforinterceptors,before,afterreturningorthrowsadvice
advised.addAdvice(newDebugInterceptor());
//Addselectiveadviceusingapointcut
advised.addAdvisor(newDefaultPointcutAdvisor(mySpecialPointcut,myAdvice));
assertEquals("Addedtwoadvisors",
oldAdvisorCount+2,advised.getAdvisors().length);
frozen AdvisedisFrozen()trueSpring1.1
7.9.“autoproxy”ProxyFactoryBeanbeanAOPSpring“”beanbean Spring“beanpostprocessor”bean
XMLbeanbean
bean
7.9.1.beanorg.springframework.aop.framework.autoproxy
7.9.1.1.BeanNameAutoProxyCreatorBeanNameAutoProxyCreatorbeanAOP
<beanclass="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<propertyname="beanNames"><value>jdk*,onlyJdk</value></property>
<propertyname="interceptorNames">
<list>
<value>myInterceptor</value>
</list>
</property>
</bean>
ProxyFactoryBean interceptorNamesprototype“”BeanNameAutoProxyCreator
Bean“jdkMyBean”“onlyJdk”beanAOPBeanNameAutoProxyCreator beanbean
7.9.1.2.DefaultAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreatorbeanbeanBeanNameAutoProxyCreator
SpecifyingaDefaultAdvisorAutoProxyCreatorbeandefinition.
DefaultAdvisorAutoProxyCreatorbean
beanDefaultAdvisorAutoProxyCreator“businessObject1”“businessObject2” bean ApplicationContextgetBean("businessObject1")AOP“bean”
<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<beanclass="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<propertyname="transactionInterceptor"ref="transactionInterceptor"/>
</bean>
<beanid="customAdvisor"class="com.mycompany.MyAdvisor"/>
<beanid="businessObject1"class="com.mycompany.BusinessObject1">
<!--Propertiesomitted-->
</bean>
<beanid="businessObject2"class="com.mycompany.BusinessObject2"/>
DefaultAdvisorAutoProxyCreator ----DefaultAdvisorAutoProxyCreatorAdvisorAutoProxyCreatororg.springframework.core.OrderedTransactionAttributeSourceAdvisor
7.9.1.3.AbstractAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreator DefaultAdvisorAutoProxyCreator
7.9.2..NET ServicedComponents EJBXML
DefaultAdvisorAutoProxyCreatorDefaultAdvisorAutoProxyCreatorAOP
JPetStore/attributes TransactionProxyFactoryBeanINF/declarativeServices.xmlbeanJPetStore
<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<beanclass="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<propertyname="transactionInterceptor"ref="transactionInterceptor"/>
</bean>
<beanid="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<propertyname="transactionManager"ref="transactionManager"/>
<propertyname="transactionAttributeSource">
<beanclass="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource">
<propertyname="attributes"ref="attributes"/>
</bean>
</property>
</bean>
<beanid="attributes"class="org.springframework.metadata.commons.CommonsAttributes"/>
DefaultAdvisorAutoProxyCreatorbeanTransactionAttributeSourceAdvisor“transactionAdvisor”bean
TransactionAttributeSourceAdvisorTransactionInterceptorAttributesTransactionAttributeSource
org.springframework.metadata.Attributes “attributes”beanJakartaCommonsAttributesAPICommonsAttributesJPetStore /annotationJDK1.5+ Spring
<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<beanclass="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<propertyname="transactionInterceptor"ref="transactionInterceptor"/>
</bean>
<beanid="transactionInterceptor"
class="org.springframework.transaction.interceptor.TransactionInterceptor">
<propertyname="transactionManager"ref="transactionManager"/>
<propertyname="transactionAttributeSource">
<beanclass="org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"/>
</property>
</bean>
TransactionInterceptorPlatformTransactionManager JTAHibernateJDOJDBC
<beanid="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/>
XMLSpringAOP
mixinsbeanDefaultPointcutAdvisorJavaBean
<beanid="lockMixin"class="org.springframework.aop.LockMixin"
scope="prototype"/>
<beanid="lockableAdvisor"class="org.springframework.aop.support.DefaultPointcutAdvisor"
scope="prototype">
<propertyname="pointcut"ref="myAttributeAwarePointcut"/>
<propertyname="advice"ref="lockMixin"/>
</bean>
<beanid="anyBean"class="anyclass"...
anyBeanbeanmixin lockMixinlockableAdvisor
myAttributeAwarePointcut
7.10.TargetSourceSpringTargetSource org.springframework.aop.TargetSource “targetobject”AOP TargetSource
SpringAOPTargetSourcepoolinghotswappableTargetSourceTargetSourceSpringtargetsource
beanSpring
7.10.1.org.springframework.aop.target.HotSwappableTargetSourceAOP HotSwappableTargetSource
HotSwappableTargetSource swap()
HotSwappableTargetSourceswapper=
(HotSwappableTargetSource)beanFactory.getBean("swapper");
ObjectoldTarget=swapper.swap(newTarget);
XML
<beanid="initialTarget"class="mycompany.OldTarget"/>
<beanid="swapper"class="org.springframework.aop.target.HotSwappableTargetSource">
<constructor-argref="initialTarget"/>
</bean>
<beanid="swappable"class="org.springframework.aop.framework.ProxyFactoryBean">
<propertyname="targetSource"ref="swapper"/>
</bean>
swap()swappablebeanbean-- TargetSource-- TargetSource
7.10.2.sessionEJBSpringSLSBSpringPOJOSpringSpringJakartaCommonsPool1.3commons-poolJarorg.springframework.aop.target.AbstractPoolingTargetSourceAPI
<beanid="businessObjectTarget"class="com.mycompany.MyBusinessObject"
scope="prototype">
...propertiesomitted
</bean>
<beanid="poolTargetSource"class="org.springframework.aop.target.CommonsPoolTargetSource">
<propertyname="targetBeanName"value="businessObjectTarget"/>
<propertyname="maxSize"value="25"/>
</bean>
<beanid="businessObject"class="org.springframework.aop.framework.ProxyFactoryBean">
<propertyname="targetSource"ref="poolTargetSource"/>
<propertyname="interceptorNames"value="myInterceptor"/>
</bean>
--“businessObjectTarget”-- PoolingTargetSourceAbstractPoolingTargetSourceJavadocmaxSize“myInterceptor”IoCSpringorg.springframework.aop.target.PoolingConfig introduction
<beanid="poolConfigAdvisor"class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
<propertyname="targetObject"ref="poolTargetSource"/>
<propertyname="targetMethod"value="getPoolingConfigMixin"/>
</bean>
AbstractPoolingTargetSourceMethodInvokingFactoryBean“poolConfigAdvisor”ProxyFactoryBean
PoolingConfigconf=(PoolingConfig)beanFactory.getBean("businessObject");
System.out.println("Maxpoolsizeis"+conf.getMaxSize());
TargetSource
7.10.3.“”TargetSource
poolTargetSourcebean
<beanid="prototypeTargetSource"class="org.springframework.aop.target.PrototypeTargetSource">
<propertyname="targetBeanName"ref="businessObjectTarget"/>
</bean>
beanTargetSourcebeanbean
7.10.4.ThreadLocalThreadLocal ThreadLocalJDK
ThreadLocalTargetSource
<beanid="threadlocalTargetSource"class="org.springframework.aop.target.ThreadLocalTargetSource">
<propertyname="targetBeanName"value="businessObjectTarget"/>
</bean>
ThreadLocalthreadlocal setunset SpringThreadLocal
7.11. Advice
SpringAOPorg.springframework.aop.framework.adapterSPIorg.aopalliance.aop.Advice
org.springframework.aop.framework.adapterJavadoc
7.12.SpringSpringAOP
JPetStoreTransactionProxyFactoryBean
JPetStore/attributes
8
8.1.8.2.
8.2.1.Mock8.2.2.
8.3.8.3.1.8.3.2.8.3.3.8.3.4.JDBC8.3.5.8.3.6.JUnit3.88.3.7.SpringTestContextFramework8.3.8.PetClinic
8.4.
8.1.SpringIoC Spring
8.2.J2EE Spring new,POJOJUnitTestNG Mock()Spring
stub()mock()DAORepository()ORMIoC“” Springmock
8.2.1.Mock8.2.1.1.JNDIorg.springframework.mock.jndi JNDI SPIJNDIJNDI <font></font>JDBCDataSourceJ2EE
8.2.1.2.ServletAPIorg.springframework.mock.webServletAPImockSpringWebMVCwebmockmock
8.2.1.3.PortletAPIorg.springframework.mock.web.portletPortletAPImockSpringPortletMVC
8.2.2.8.2.2.1.org.springframework.test.utilReflectionTestUtilspublicsetter
ORMJPAHibernate publicSetterprivateprotected
Spring@Autowired@Resourceprivateprotectedsetter
8.2.2.2.SpringMVCorg.springframework.test.webAbstractModelAndViewTestsJUnit3.8SpringMVCModelAndViewJava1.4JUnit4+,TestNGModelAndViewAssert ModelAndView
: AbstractModelAndViewTests ModelAndViewAssert
MockHttpServletRequest,MockHttpSession org.springframework.mock.web
SpringMVC Controller.
8.3.
8.3.1.
SpringIoC
JDBCORMSQLHibernatequeryJPASpring spring-test.jar org.springframework.testSpringCactusApacheJavahttp://jakarta.apache.org/cactus/index.html2.5Spring JUnit3.8.2.5,Spring SpringTestContext4.4,TestNG SpringTestContextJava5+.
8.3.2.SpringSpringTestContext ApplicationContext
JPA shadowclassJPA(classinstrumentation)JUnit3.8instrumentationTestContext
8.3.3.Spring
SpringIoC
fixture()
()
Spring
8.3.3.1.SpringApplicationContext ——SpringHibernate10-20 fixtureXML——classpath—— web.xml
, ApplicationContext fixture——Springfixture
JUnit3.8
TestContext
8.3.3.2.fixturesSpring beanfixture
HibernateTitleDao Title
Spring: HibernateTitleDaobean
Hibernate:lazy-loading
HibernateTitleDao
fixturesJUnit3.8
TestContext
8.3.3.3. ——Spring bean——,——Spring:
JUnit3.8
TestContext
8.3.3.4.Springabstract
ApplicationContext:bean
JdbcTemplateSimpleJdbcTemplate: ORMORM'flush' Hibernate Sessionflush()
JUnit3.8
TestContext
8.3.4.JDBCorg.springframework.test.jdbcSimpleJdbcTestUtils Java5JDBC
AbstractTransactionalJUnit38SpringContextTests,AbstractTransactionalJUnit4SpringContextTests,AbstractTransactionalTestNGSpringContextTests SimpleJdbcTestUtils
8.3.5.Springorg.springframework.test.annotation SpringJava5
@IfProfileValue
ProfileValueSource
@IfProfileValue(name="java.vendor",value="SunMicrosystemsInc.")
publicvoidtestProcessWhichRunsOnlyOnSunJvm(){
//somelogicthatshouldrunonlyonJavaVMsfromSunMicrosystems
}
@IfProfileValue ( OR)JUnitTestNG
@IfProfileValue(name="test-groups",values={"unit-tests","integration-tests"})
publicvoidtestProcessWhichRunsForUnitOrIntegrationTestGroups(){
//somelogicthatshouldrunonlyforunitandintegrationtestgroups
}
@ProfileValueSourceConfiguration
@IfProfileValueprofileProfileValueSource@ProfileValueSourceConfiguration SystemProfileValueSource
@ProfileValueSourceConfiguration(CustomProfileValueSource.class)
publicclassCustomProfileValueSourceTests{
//classbody...
}
@DirtiesContext
Spring“”
@DirtiesContext
publicvoidtestProcessWhichDirtiesAppCtx(){
//somelogicthatresultsintheSpringcontainerbeingdirtied
}
@ExpectedException
@ExpectedException(SomeBusinessException.class)
publicvoidtestProcessRainyDayScenario(){
//somelogicthatshouldresultinanExceptionbeingthrown
}
@Timed
@Repeatfixture setupteardown
@Timed(millis=1000)
publicvoidtestProcessWithOneSecondTimeout(){
//somelogicthatshouldnottakelongerthan1secondtoexecute
}
@Repeat
fixture setupteardown
@Repeat(10)
publicvoidtestProcessRepeatedly(){
//...
}
@Rollback
true @Rollback
@Rollback(false)
publicvoidtestProcessWithoutRollback(){
//...
}
@NotTransactional
@NotTransactional
publicvoidtestProcessWithoutTransaction(){
//...
}
JUnit3.8 AbstractAnnotationAwareTransactionalTests
TestContext TestContext (@ContextConfiguration@BeforeTransaction) JUnit(SpringJUnit4ClassRunnerJUnit3.8JUnit4.4) TestContext
8.3.6.JUnit3.8SpringJUnit3.8org.springframework.test JUnit TestCase
ApplicationContext
8.3.6.1.AbstractSingleSpringContextTestsJUnit3.8
protectedString[]getConfigLocations()
XML————
protectedString[]getConfigPaths()
protectedStringgetConfigPath()
fixtureAbstractSingleSpringContextTests setDirty()fixtureAbstractAnnotationAwareTransactionalTests @DirtiesContext
8.3.6.2.fixture
AbstractDependencyInjectionSpringContextTests() AbstractDependencyInjectionSpringContextTests
getConfigLocations()
HibernateTitleDao( ) JUnit3.8()
publicfinalclassHibernateTitleDaoTestsextendsAbstractDependencyInjectionSpringContextTests
//thisinstancewillbe(automatically)dependencyinjected
privateHibernateTitleDaotitleDao;
//asettermethodtoenableDIofthe'titleDao'instancevariable
publicvoidsetTitleDao(HibernateTitleDaotitleDao){
this.titleDao=titleDao;
}
publicvoidtestLoadTitle()throwsException{
Titletitle=this.titleDao.loadTitle(newLong(10));
assertNotNull(title);
}
//specifiestheSpringconfigurationtoloadforthistestfixture
protectedString[]getConfigLocations(){
returnnewString[]{"classpath:com/foo/daos.xml"};
}
}
getConfigLocations()( "classpath:com/foo/daos.xml")
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--thisbeanwillbeinjectedintotheHibernateTitleDaoTests
<beanid="titleDao"class="com.foo.dao.hibernate.HibernateTitleDao
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
<beanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!--dependencieselidedforclarity-->
</bean>
</beans>
AbstractDependencyInjectionSpringContextTestsbeanbeanapplicationContext applicationContext.getBean("titleDao")
publicsetter AbstractSpringContextTests
org.springframework.testJUnit3.8-Springfixture
8.3.6.2.1.FieldLevel
fixturesetterSpring protected SpringXMLfixture
publicfinalclassHibernateTitleDaoTestsextendsAbstractDependencyInjectionSpringContextTests
publicHibernateTitleDaoTests(){
//switchonfieldlevelinjection
setPopulateProtectedVariables(true);
}
//thisinstancewillbe(automatically)dependencyinjected
protectedHibernateTitleDaotitleDao;
publicvoidtestLoadTitle()throwsException{
Titletitle=this.titleDao.loadTitle(newLong(10));
assertNotNull(title);
}
//specifiestheSpringconfigurationtoloadforthistestfixture
protectedString[]getConfigLocations(){
returnnewString[]{"classpath:com/foo/daos.xml"};
}
}
protectedSpringbean
8.3.6.3.
AbstractTransactionalSpringContextTests PlatformTransactionManager
bean .AbstractTransactionalDataSourceSpringContextTests) JdbcTemplate———— AbstractTransactionalSpringContextTests
Java5 AbstractAnnotationAwareTransactionalTests
@Rollback(false)
endTransaction()Hibernate UI endTransaction()
8.3.6.4.JUnit3.8 AbstractTransactionalDataSourceSpringContextTests protected:
applicationContext(ConfigurableApplicationContext):AbstractSingleSpringContextTestsbean
jdbcTemplate:AbstractTransactionalDataSourceSpringContextTestsORMSpringORM‘’Hibernateflush()
8.3.6.5.Java5+
8.3.6.5.1.
org.springframework.test.annotationJUnitTestCaseAbstractAnnotationAwareTransactionalTests
AbstractTransactionalDataSourceSpringContextTests fixtureSpringAbstractAnnotationAwareTransactionalTests
@Transactional
8.3.6.5.2.JPA
org.springframework.test.jpaJavaAPI(JPA)
AbstractJpaTestsJPA
AbstractTransactionalDataSourceSpringContextTestsJPAEntityManagerFactoryEntityManager EntityManagerFactory
DataSourceJpaTransactionManager
AbstractAspectjJpaTestsAbstractJpaTests AspectJAspectJaop.xml
8.3.7.SpringTestContextFrameworkSpringTestContextFramework( org.springframework.test.context)JUnit3.8JUnit4.4,TestNG5.5TestContext JUnit3.8JUnit4.4TestNG5.5TestContext (
8.3.7.1.TestContextTestContextManagerTestExecutionListenerTestContextManagerTestContextManagerTestContext
TestContextManagerTestContextTestExecutionListenerJavaDocSpring
TestContext
TestContextManagerSpringTestContextFrameworkTestExecutionListener
TestExecutionListenerAPITestContextManagerTestContextManager
SpringTestExecutionListener ( @TestExecutionListeners
DependencyInjectionTestExecutionListenerDirtiesContextTestExecutionListener
TransactionalTestExecutionListenerTestContext
8.3.7.2.TestContextApplicationContext DependencyInjectionTestExecutionListener
AbstractJUnit38SpringContextTests AbstractJUnit4SpringContextTests
AbstractTestNGSpringContextTestsApplicationContextAwareJUnit3.8TestContext protected @ContextConfiguration
ContextLoader GenericXmlContextLoader
com.example.MyTestGenericXmlContextLoader
"classpath:/com/example/MyTest-context.xml"
packagecom.example;
@RunWith(SpringJUnit4ClassRunner.class)
//ApplicationContextwillbeloadedfrom"classpath:/com/example/MyTest-context.xml"
@ContextConfiguration
publicclassMyTest{
//classbody...
}
XML @ContextConfigurationlocations XMLclasspath web.xml
@RunWith(SpringJUnit4ClassRunner.class)
//ApplicationContextwillbeloadedfrom"/applicationContext.xml"
//intherootoftheclasspath
@ContextConfiguration(locations={"/applicationContext.xml","/applicationContext-test.xml"})
publicclassMyTest{
//classbody...
}
@ContextConfigurationbooleaninheritLocationslocations true
"/base-context.xml" "/extended-context.xml"ApplicationContext"/extended-context.xml"Beans"/base-context.xml"Beans
@RunWith(SpringJUnit4ClassRunner.class)
//ApplicationContextwillbeloadedfrom"/base-context.xml"
@ContextConfiguration(locations={"/base-context.xml"})
publicclassBaseTest{
//classbody...
}
//ApplicationContextwillbeloadedfrom"/base-context.xml"
//intherootoftheclasspath
@ContextConfiguration(locations={"/extended-context.xml"})
publicclassExtendedTestextendsBaseTest{
//classbody...
}
inheritLocationsfalse
, ApplicationContextfixture@DirtiesContext DirtiesContextTestExecutionListenerfixture
8.3.7.3.fixtureDependencyInjectionTestExecutionListener - -@TestExecutionListeners bean bean@ContextConfigurationField setterSpring2.5Spring @Autowiredsettter
TestContext @Autowired
@AutowiredbeanbeanApplicationContextAware ApplicationContext
applicationContext.getBean("titleDao")
@Autowired@ResourcesetterDependencyInjectionTestExecutionListener.class
HibernateTitleDao JUnit4.4JUnit4.4
@RunWith(SpringJUnit4ClassRunner.class)
//specifiestheSpringconfigurationtoloadforthistestfixture
@ContextConfiguration(locations={"daos.xml"})
publicfinalclassHibernateTitleDaoTests{
//thisinstancewillbedependencyinjectedbytype
@Autowired
privateHibernateTitleDaotitleDao;
publicvoidtestLoadTitle()throwsException{
Titletitle=this.titleDao.loadTitle(newLong(10));
assertNotNull(title);
}
}
@Autowiredsetter
@RunWith(SpringJUnit4ClassRunner.class)
//specifiestheSpringconfigurationtoloadforthistestfixture
@ContextConfiguration(locations={"daos.xml"})
publicfinalclassHibernateTitleDaoTests{
//thisinstancewillbedependencyinjectedbytype
privateHibernateTitleDaotitleDao;
@Autowired
publicvoidsetTitleDao(HibernateTitleDaotitleDao){
this.titleDao=titleDao;
}
publicvoidtestLoadTitle()throwsException{
Titletitle=this.titleDao.loadTitle(newLong(10));
assertNotNull(title);
}
}
@Resource
@RunWith(SpringJUnit4ClassRunner.class)
//specifiestheSpringconfigurationtoloadforthistestfixture
@ContextConfiguration(locations={"daos.xml"})
publicfinalclassHibernateTitleDaoTests{
//thisinstancewillbedependencyinjectedbyname
@Resource
privateHibernateTitleDaotitleDao;
publicvoidtestLoadTitle()throwsException{
Titletitle=this.titleDao.loadTitle(newLong(10));
assertNotNull(title);
}
}
@Resourcesetter
@RunWith(SpringJUnit4ClassRunner.class)
//specifiestheSpringconfigurationtoloadforthistestfixture
@ContextConfiguration(locations={"daos.xml"})
publicfinalclassHibernateTitleDaoTests{
//thisinstancewillbedependencyinjectedbyname
privateHibernateTitleDaotitleDao;
@Resource
publicvoidsetTitleDao(HibernateTitleDaotitleDao){
this.titleDao=titleDao;
}
publicvoidtestLoadTitle()throwsException{
Titletitle=this.titleDao.loadTitle(newLong(10));
assertNotNull(title);
}
}
XML @ContextConfiguration( "daos.xml")
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--thisbeanwillbeinjectedintotheHibernateTitleDaoTests
<beanid="titleDao"class="com.foo.dao.hibernate.HibernateTitleDao
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
<beanid="sessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<!--dependencieselidedforclarity-->
</bean>
</beans>
8.3.7.4.TestContext TransactionalTestExecutionListener@TestExecutionListeners @TestExecutionListeners
@ContextConfigurationPlatformTransactionManagerbean@Transactional
TestContext@TransactionConfigurationbean@Transactional @NotTransactional
AbstractTransactionalJUnit38SpringContextTests
AbstractTransactionalJUnit4SpringContextTestsAbstractTransactionalTestNGSpringContextTests
TransactionalTestExecutionListenerTransactionalTestExecutionListener
(JUnit4@Before) (JUnit4@After) @NotTransactional@BeforeTransaction@AfterTransaction
JUnit4 TestContext
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
@TransactionConfiguration(transactionManager="txMgr",defaultRollback=false)
@Transactional
publicclassFictitiousTransactionalTest{
@BeforeTransaction
publicvoidverifyInitialDatabaseState(){
//logictoverifytheinitialstatebeforeatransactionisstarted
}
@Before
publicvoidsetUpTestDataWithinTransaction(){
//setuptestdatawithinthetransaction
}
@Test
//overridestheclass-leveldefaultRollbacksetting
@Rollback(true)
publicvoidmodifyDatabaseWithinTransaction(){
//logicwhichusesthetestdataandmodifiesdatabasestate
}
@After
publicvoidtearDownWithinTransaction(){
//execute"teardown"logicwithinthetransaction
}
@AfterTransaction
publicvoidverifyFinalDatabaseState(){
//logictoverifythefinalstateaftertransactionhasrolledback
}
@Test
@NotTransactional
publicvoidperformNonDatabaseRelatedAction(){
//logicwhichdoesnotmodifydatabasestate
}
}
8.3.7.5.TestContext
8.3.7.5.1.JUnit3.8
org.springframework.test.context.junit38JUnit3.8
AbstractJUnit38SpringContextTests
SpringTestContextFrameworkJUnit3.8ApplicationContextTestCase AbstractJUnit38SpringContextTests protected
applicationContextbean
AbstractTransactionalJUnit38SpringContextTests
JDBCAbstractJUnit38SpringContextTests ApplicationContext
javax.sql.DataSourcebeanPlatformTransactionManagerbeanAbstractTransactionalJUnit38SpringContextTests protected
applicationContextAbstractJUnit38SpringContextTestsbean
simpleJdbcTemplateORM‘flush’Hibernate Sessionflush()
8.3.7.5.2.JUnit4.4
org.springframework.test.context.junit4JUnit4.4
AbstractJUnit4SpringContextTests
SpringTestContextFrameworkJUnit4.4ApplicationContextAbstractJUnit4SpringContextTests protected
applicationContextbean
AbstractTransactionalJUnit4SpringContextTests
JDBCAbstractJUnit4SpringContextTests ApplicationContext
javax.sql.DataSourcebeanPlatformTransactionManagerbeanAbstractTransactionalJUnit4SpringContextTests protected
applicationContextAbstractJUnit4SpringContextTestsbean
simpleJdbcTemplateORM‘flush’ Hibernate Sessionflush()
Spring - -@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration@TestExecutionListeners
8.3.7.5.3.JUnit4.4
SpringTestContextFrameworkJUnit4.4@Runwith(SpringJUnit4ClassRunner.class)JUnit4.4 SpringRunner@ContextConfiguration ApplicationContext
@RunWith(SpringJUnit4ClassRunner.class)
@TestExecutionListeners({})
publicclassSimpleTest{
@Test
publicvoidtestMethod(){
//executetestlogic...
}
}
8.3.7.5.4.TestNG
org.springframework.test.context.testngTestNG
AbstractTestNGSpringContextTests
SpringTestContextFrameworkTestNGApplicationContext
AbstractTestNGSpringContextTests protected
applicationContextbean
AbstractTransactionalTestNGSpringContextTests
JDBCAbstractTestNGSpringContextTests ApplicationContext
javax.sql.DataSourcebeanPlatformTransactionManagerbeanAbstractTransactionalTestNGSpringContextTests protected
applicationContextAbstractTestNGSpringContextTestsbean
simpleJdbcTemplateORM‘flush’Hibernate Sessionflush()
Spring--@ContextConfiguration@TestExecutionListenersTestContextManager AbstractTestNGSpringContextTests
8.3.7.6.TestContextSpringTestContextFramework JUnit SpringJUnit4ClassRunnerJUnit4.4
@IfProfileValue
@ProfileValueSourceConfiguration
@ExpectedException
Spring@ExpectedExceptionJUnit4@Test(expected=...)
JUnit4@Timed
Spring@TimedJUnit4@Test(timeout=...) JUnit4JUnit @Test(timeout=...) Spring@Test(timeout=...)
@Repeat
SpringTestContextFramework@Autowired
@Qualifier
@Resource(javax.annotation)JSR-250
@PersistenceContext(javax.persistence)JPA
@PersistenceUnit(javax.persistence)JPA
@Required
@Transactional
SpringTestContextFrameworkJavaDoc@ContextConfiguration
ApplicationContext @ContextConfiguration
@ContextConfiguration(locations={"example/test-context.xml"},loader=CustomContextLoader.class)
publicclassCustomConfiguredApplicationContextTests{
//classbody...
}
@ContextConfiguration JavaDoc
@TestExecutionListeners
TestExecutionListenersTestContextManager@TestExecutionListeners@ContextConfiguration
@ContextConfiguration
@TestExecutionListeners({CustomTestExecutionListener.class,AnotherTestExecutionListener.class})
publicclassCustomTestExecutionListenerTests{
//classbody...
}
@TestExecutionListenersJavaDoc
@TransactionConfiguration
PlatformTransactionManager“transactionManager”PlatformTransactionManagerbean defaultRollbackfalse
@TransactionConfiguration@ContextConfiguration
@ContextConfiguration
@TransactionConfiguration(transactionManager="txMgr",defaultRollback=false)
publicclassCustomConfiguredTransactionalTests{
//classbody...
}
@BeforeTransaction
publicvoid @Transactional
@BeforeTransaction
publicvoidbeforeTransaction(){
//logictobeexecutedbeforeatransactionisstarted
}
@AfterTransaction
publicvoid @Transactional
@AfterTransaction
publicvoidafterTransaction(){
//logictobeexecutedafteratransactionhasended
}
8.3.8.PetClinicSpringPetClinicJUnit4.4 SpringTestContextFrameworkAbstractClinicTests
@ContextConfiguration
publicabstractclassAbstractClinicTestsextendsAbstractTransactionalJUnit4SpringContextTests
@Autowired
protectedClinicclinic;
@Test
publicvoidgetVets(){
Collection<Vet>vets=this.clinic.getVets();
assertEquals("JDBCquerymustshowthesamenumberofvets",
super.countRowsInTable("VETS"),vets.size());
Vetv1=EntityUtils.getById(vets,Vet.class,2);
assertEquals("Leary",v1.getLastName());
assertEquals(1,v1.getNrOfSpecialties());
assertEquals("radiology",(v1.getSpecialties().get(0)).getName());
//...
}
//...
}
AbstractTransactionalJUnit4SpringContextTestsDependencyInjectionTestExecutionListener
TransactionalTestExecutionListener
clinic-- @Autowired
testGetVets()countRowsInTable()
AbstractClinicTestsPetClinic-JDBCHibernateJPAAbstractClinicTests "AbstractClinicTests-context.xml"
PlatformTransactionManagerClinic
PetClinicHibernate HibernateClinicTests@ContextConfigurationAbstractClinicTestsSpringTestContextFramework"AbstractClinicTests-context.xml"()"HibernateClinicTests-context.xml" "HibernateClinicTests-
context.xml"bean"AbstractClinicTests-context.xml"bean
@ContextConfiguration
publicclassHibernateClinicTestsextendsAbstractClinicTests{}
PetClinicSpringSpringDataSourceJtaTransactionManagerJNDIJTABasicDataSourceDataSourceTransactionManager
HibernateTransactionManagerXML''
8.4.
JUnitSpringJUnit3.8
TestNGTestNGJUnit3.8Java5
MockObjectsMockObjects
“MockObjects”
EasyMockSpringEasyMock
JMockJMockmockJava
DbUnitDbUnitJUnitAnt
GrinderGrinderJava
II.
SpringSpringFramework9
10 DAO
11 JDBC
12 ORM
9.9.1.9.2.9.3.9.4.
9.4.1.9.4.2.9.4.3.TransactionAwareDataSourceProxy
9.5.9.5.1.Spring9.5.2.9.5.3.9.5.4.bean9.5.5.<tx:advice/>9.5.6. @Transactional
9.5.7.9.5.8.9.5.9.AspectJ @Transactional
9.6.9.6.1.TransactionTemplate9.6.2.PlatformTransactionManager
9.7.9.8.
9.8.1.IBMWebSphere9.8.2.BEAWebLogic9.8.3.OracleOC4J
9.9.9.9.1. DataSource
9.10.
10.DAO10.1.10.2.10.3.DAO
11.JDBC11.1.
11.1.1.11.1.2.SpringJDBC
11.2.JDBCJDBC11.2.1.JdbcTemplate11.2.2.NamedParameterJdbcTemplate11.2.3.SimpleJdbcTemplate11.2.4.DataSource11.2.5.SQLExceptionTranslator11.2.6.SQL11.2.7.11.2.8.11.2.9.
11.3.11.3.1.DataSourceUtils11.3.2.SmartDataSource11.3.3.AbstractDataSource11.3.4.SingleConnectionDataSource11.3.5.DriverManagerDataSource11.3.6.TransactionAwareDataSourceProxy11.3.7.DataSourceTransactionManager11.3.8.NativeJdbcExtractor
11.4.JDBC11.4.1.JdbcTemplate11.4.2.SimpleJdbcTemplate
11.5.SimpleJdbcJDBC11.5.1.SimpleJdbcInsert11.5.2.SimpleJdbcInsert11.5.3.SimpleJdbcInsert11.5.4.SqlParameterSource11.5.5.SimpleJdbcCall11.5.6.SimpleJdbcCall11.5.7.SqlParameters11.5.8.SimpleJdbcCall11.5.9.SimpleJdbcCallResultSet/REFCursor
11.6.JavaJDBC11.6.1.SqlQuery11.6.2.MappingSqlQuery11.6.3.SqlUpdate11.6.4.StoredProcedure11.6.5.SqlFunction
11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.
12.ORM12.1.12.2.Hibernate
12.2.1.12.2.2.Spring SessionFactory
12.2.3.TheHibernateTemplate12.2.4.SpringDAO12.2.5.Hibernate3APIDAO12.2.6.12.2.7.12.2.8.12.2.9.vs12.2.10.Hibernate
12.3.JDO12.3.1.PersistenceManagerFactory12.3.2.JdoTemplateJdoDaoSupport12.3.3.JDOAPIDAO12.3.4.12.3.5.JdoDialect
12.4.OracleTopLink12.4.1.SessionFactory12.4.2.TopLinkTemplateandTopLinkDaoSupport12.4.3.TopLinkAPIDAO12.4.4.
12.5.iBATISSQLMaps12.5.1.SqlMapClient12.5.2. SqlMapClientTemplate SqlMapClientDaoSupport
12.5.3.iBATISAPIDAO12.6.JPA
12.6.1.SpringJPA12.6.2.JpaTemplate JpaDaoSupport
12.6.3.JPADAO12.6.4.
12.7.12.8.JpaDialect
9
9.1.9.2.9.3.9.4.
9.4.1.9.4.2.9.4.3.TransactionAwareDataSourceProxy
9.5.9.5.1.Spring9.5.2.9.5.3.9.5.4.bean9.5.5.<tx:advice/>9.5.6. @Transactional
9.5.7.9.5.8.9.5.9.AspectJ @Transactional
9.6.9.6.1.TransactionTemplate9.6.2.PlatformTransactionManager
9.7.9.8.
9.8.1.IBMWebSphere9.8.2.BEAWebLogic9.8.3.OracleOC4J
9.9.9.9.1. DataSource
9.10.
9.1.SpringSpring
APIJTAJDBCHibernateJPAJDO
APIJTA API
SpringSpring
SpringEJBCMTAPIHibernate
Spring DataSource
Spring
Spring
SpringJ2EEEJBJTASpringEJBCMTJTAOracle9iRACJMSJCASpring EJBCMTJTAJDBCSpring
9.2.J2EE JTAJDBC
. JTAAPIJTAUserTransactionJNDIJTA JNDIJTAJTA EJBCMTJNDIEJBJNDICMTJTAEJBEJBFacadeEJBEJB. JDBCJTASpring Spring
SpringSpringAPI
9.3.Spring org.springframework.transaction.PlatformTransactionManager
publicinterfacePlatformTransactionManager{
TransactionStatusgetTransaction(TransactionDefinitiondefinition)
throwsTransactionException;
voidcommit(TransactionStatusstatus)throwsTransactionException;
voidrollback(TransactionStatusstatus)throwsTransactionException;
}
SPI Spring PlatformTransactionManager JNDIPlatformTransactionManagerSpringIoCJTAJTA
Spring PlatformTransactionManager TransactionExceptionuncheckedexception java.lang.RuntimeException
TransactionException
getTransaction(..) TransactionDefinition TransactionStatus TransactionStatusJ2EE TransactionStatus TransactionDefinition
SpringEJBCMT
:
:HibernateSpringTransactionStatusAPI:
publicinterfaceTransactionStatus{
booleanisNewTransaction();
voidsetRollbackOnly();
booleanisRollbackOnly();
}
Spring PlatformTransactionManagerSpringIoCPlatformTransactionManagerJDBCJTAHibernateSpring
——jPetStore——dataAccessContext-local.xml
PlatformTransactionManagerJDBCJDBCDataSourceSpringDataSourceTransactionManagerDataSource
<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<propertyname="driverClassName"value="${jdbc.driverClassName}"/>
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
</bean>
PlatformTransactionManagerbean
<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"/>
</bean>
J2EEJTA 'dataAccessContext-jta.xml'JNDISpringJtaTransactionManager DataSourceJtaTransactionManagerDataSource
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.0.xsd
http://www.springframework.org/schema/jeehttp://www.springframework.org/schema/jee/spring-jee-2.0.xsd">
<jee:jndi-lookupid="dataSource"jndi-name="jdbc/jpetstore"/>
<beanid="txManager"class="org.springframework.transaction.jta.JtaTransactionManager"/>
<!--other<bean/>definitionshere-->
</beans>
'dataSource'bean 'jee' <jndi-lookup/>, A, XML Schema-based configuration <jee/> A.2.3 “The jee
schema”HibernateSpring PetClinicHibernateLocalSessionFactoryBeanHibernateSessionDataSourcebeanJEE DataSourceJEESpring'txManager' bean HibernateTransactionManager
DataSourceTransactionManager DataSourceHibernateTransactionManager SessionFactory
<beanid="sessionFactory"class="org.springframework.orm.hibernate.LocalSessionFactoryBean">
<propertyname="dataSource"ref="dataSource"/>
<propertyname="mappingResources">
<list>
<value>org/springframework/samples/petclinic/hibernate/petclinic.hbm.xml</value>
</list>
</property>
<propertyname="hibernateProperties">
<value>
hibernate.dialect=${hibernate.dialect}
</value>
</property>
</bean>
<beanid="txManager"class="org.springframework.orm.hibernate.HibernateTransactionManager">
<propertyname="sessionFactory"ref="sessionFactory"/>
</bean>
JtaTransactionManagerHibernateJTAJDBC
<beanid="txManager"class="org.springframework.transaction.jta.JtaTransactionManager"/>
JTA
9.4.DataSourceTransactionManager JDBC DataSource
HibernateTransactionManagerHibernate SessionFactoryAPIJDBCHibernateJDO PlatformTransactionManager
9.4.1.SpringAPIAPIAPI JdbcTemplateHibernateTemplateJdoTemplate
9.4.2.DataSourceUtilsJDBC SessionFactoryUtils
Hibernate PersistenceManagerFactoryUtilsJDOAPISpringbeanAPIJDBC DataSource getConnection() Springorg.springframework.jdbc.datasource.DataSourceUtils
Connectionconn=DataSourceUtils.getConnection(dataSource);
connectionconnectionconnectionSQLExceptionSpring CannotGetJdbcConnectionExceptionSpringuncheckedDataAccessExceptions SQLException
SpringSpringSpringJDBCHibernate DataSourceUtilsSpringAPISpring JdbcTemplate jdbc.objectJDBCSpring
9.4.3.TransactionAwareDataSourceProxy TransactionAwareDataSourceProxy DataSource DataSource
SpringJ2EEJNDI DataSource
JDBC DataSourceSpringSpring
TransactionProxyFactoryBean
Spring2.0TransactionProxyFactoryBean
Spring2.0 <tx:tags/>
TransactionProxyFactoryBean
9.5.Spring SpringSpringAOPSpringEJBCMTSpring
EJBCMTJTASpring
SpringEJB
SpringEJB
SpringAOP
SpringEJBthrowableJavaTransactionStatus setRollbackOnly()
MyApplicationException SpringAPIEJBEJB EJBCMT java.rmi.RemoteExceptioncheckedexception SpringEJBuncheckedexceptions
9.5.1.Spring@Transactional '<tx:annotation-driven/>'Spring
SpringSpringAOP XML AOPPlatformTransactionManager TransactionInterceptor
SpringAOPSpringAOP 6 SpringAOP SpringAOP
9.5.2. Foo Bar
//
packagex.y.service;
publicinterfaceFooService{
FoogetFoo(StringfooName);
FoogetFoo(StringfooName,StringbarName);
voidinsertFoo(Foofoo);
voidupdateFoo(Foofoo);
}
//
packagex.y.service;
publicclassDefaultFooServiceimplementsFooService{
publicFoogetFoo(StringfooName){
thrownewUnsupportedOperationException();
}
publicFoogetFoo(StringfooName,StringbarName){
thrownewUnsupportedOperationException();
}
publicvoidinsertFoo(Foofoo){
thrownewUnsupportedOperationException();
}
publicvoidupdateFoo(Foofoo){
thrownewUnsupportedOperationException();
}
}
DefaultFooService UnsupportedOperationException
UnsupportedOperationExceptionFooServicegetFoo(String) getFoo(String, String) insertFoo(Foo)
updateFoo(Foo)
<!--fromthefile'context.xml'-->
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--thisistheserviceobjectthatwewanttomaketransactional-->
<beanid="fooService"class="x.y.service.DefaultFooService"/>
<!--thetransactionaladvice(what'happens';seethe<aop:advisor/>
<tx:adviceid="txAdvice"transaction-manager="txManager">
<!--thetransactionalsemantics...-->
<tx:attributes>
<!--allmethodsstartingwith'get'areread-only-->
<tx:methodname="get*"read-only="true"/>
<!--othermethodsusethedefaulttransactionsettings(seebelow)-->
<tx:methodname="*"/>
</tx:attributes>
</tx:advice>
<!--ensurethattheabovetransactionaladvicerunsforanyexecution
ofanoperationdefinedbytheFooServiceinterface-->
<aop:config>
<aop:pointcutid="fooServiceOperation"expression="execution(*x.y.service.FooService.*(..))"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="fooServiceOperation"/>
</aop:config>
<!--don'tforgettheDataSource-->
<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<propertyname="driverClassName"value="oracle.jdbc.driver.OracleDriver"/>
<propertyname="url"value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
<propertyname="username"value="scott"/>
<propertyname="password"value="tiger"/>
</bean>
<!--similarly,don'tforgetthePlatformTransactionManager
<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"/>
</bean>
<!--other<bean/>definitionshere-->
</beans>
'fooService'bean” 'transaction-manager' PlatformTransactionManager
'txManager' bean
PlatformTransactionManager bean'transactionManager' <tx:advice/> 'transaction-
manager' <aop:config/> 'txAdvice'bean 'fooServiceOperation'advisor 'txAdvice' 'fooServiceOperation' 'txAdvice'<aop:pointcut/>AspectJSpring2.0 6 SpringAOP
<aop:config>
<aop:pointcutid="fooServiceMethods"expression="execution(*x.y.service.*.*(..))"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="fooServiceMethods"/>
</aop:config>
'x.y.service' 6 SpringAOP “ ”'fooService'bean
publicfinalclassBoot{
publicstaticvoidmain(finalString[]args)throwsException{
ApplicationContextctx=newClassPathXmlApplicationContext("context.xml",Boot.class);
FooServicefooService=(FooService)ctx.getBean("fooService");
fooService.insertFoo(newFoo());
}
}
Log4J DefaultFooService insertFoo(..)UnsupportedOperationException
<!--Spring...-->
[AspectJInvocationContextExposingAdvisorAutoProxyCreator]-Creatingimplicitproxy
forbean'fooService'with0commoninterceptorsand1specificinterceptors
<!--theDefaultFooServiceisactuallyproxied-->
[JdkDynamicAopProxy]-CreatingJDKdynamicproxyfor[x.y.service.DefaultFooService]
<!--...theinsertFoo(..)methodisnowbeinginvokedontheproxy-->
[TransactionInterceptor]-Gettingtransactionforx.y.service.FooService.insertFoo
<!--thetransactionaladvicekicksinhere...-->
[DataSourceTransactionManager]-Creatingnewtransactionwithname[x.y.service.FooService.insertFoo]
[DataSourceTransactionManager]-AcquiredConnection
[org.apache.commons.dbcp.PoolableConnection@a53de4]forJDBCtransaction
<!--theinsertFoo(..)methodfromDefaultFooServicethrowsanexception...-->
[RuleBasedTransactionAttribute]-Applyingrulestodeterminewhethertransactionshould
rollbackonjava.lang.UnsupportedOperationException
[TransactionInterceptor]-Invokingrollbackfortransactiononx.y.service.FooService.insertFoo
duetothrowable[java.lang.UnsupportedOperationException]
<!--andthetransactionisrolledback(bydefault,RuntimeException
[DataSourceTransactionManager]-RollingbackJDBCtransactiononConnection
[org.apache.commons.dbcp.PoolableConnection@a53de4]
[DataSourceTransactionManager]-ReleasingJDBCConnectionaftertransaction
[DataSourceUtils]-ReturningJDBCConnectiontoDataSource
Exceptioninthread"main"java.lang.UnsupportedOperationException
atx.y.service.DefaultFooService.insertFoo(DefaultFooService.java:14)
<!--AOPinfrastructurestacktraceelementsremovedforclarity-->
at$Proxy0.insertFoo(UnknownSource)
atBoot.main(Boot.java:11)
9.5.3.Springcontext ExceptionSpringSpring uncheckedexceptionsErrors--Checkedexceptions Exception XMLchecked
<tx:adviceid="txAdvice"transaction-manager="txManager">
<tx:attributes>
<tx:methodname="get*"read-only="true"rollback-for="NoProductInStockException"
<tx:methodname="*"/>
</tx:attributes>
</tx:advice>
“” Spring
<tx:adviceid="txAdvice">
<tx:attributes>
<tx:methodname="updateStock"no-rollback-for="InstrumentNotFoundException"
<tx:methodname="*"/>
</tx:attributes>
</tx:advice>
Spring InstrumentNotFoundException
<tx:adviceid="txAdvice">
<tx:attributes>
<tx:methodname="*"rollback-for="Throwable"no-rollback-for="InstrumentNotFoundException"/>
</tx:attributes>
</tx:advice>
Spring
publicvoidresolvePosition(){
try{
//somebusinesslogic...
}catch(NoProductInStockExceptionex){
//triggerrollbackprogrammatically
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
}
POJO
9.5.4.bean Spring <aop:advisor/> advisor'advice-ref'
'x.y.service' service 'Service'
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:config>
<aop:pointcutid="serviceOperation"
expression="execution(*x.y.service..*Service.*(..))
<aop:advisorpointcut-ref="serviceOperation"advice-ref="txAdvice"/>
</aop:config>
<!--thesetwobeanswillbetransactional...-->
<beanid="fooService"class="x.y.service.DefaultFooService"/>
<beanid="barService"class="x.y.service.extras.SimpleBarService"/>
<!--...andthesetwobeanswon't-->
<beanid="anotherService"class="org.xyz.SomeService"/><!--(notintherightpackage)-->
<beanid="barManager"class="x.y.service.SimpleBarManager"/>
<tx:adviceid="txAdvice">
<tx:attributes>
<tx:methodname="get*"read-only="true"/>
<tx:methodname="*"/>
</tx:attributes>
</tx:advice>
<!--othertransactioninfrastructurebeanssuchasaPlatformTransactionManager
</beans>
bean
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<aop:config>
<aop:pointcutid="defaultServiceOperation"
expression="execution(*x.y.service.*Service.*(..))
<aop:pointcutid="noTxServiceOperation"
expression="execution(*x.y.service.ddl.DefaultDdlManager.*(..))
<aop:advisorpointcut-ref="defaultServiceOperation"advice-ref="defaultTxAdvice"/>
<aop:advisorpointcut-ref="noTxServiceOperation"advice-ref="noTxAdvice"/>
</aop:config>
<!--thisbeanwillbetransactional(seethe'defaultServiceOperation'
<beanid="fooService"class="x.y.service.DefaultFooService"/>
<!--thisbeanwillalsobetransactional,butwithtotallydifferenttransactionalsettings-->
<beanid="anotherFooService"class="x.y.service.ddl.DefaultDdlManager"/>
<tx:adviceid="defaultTxAdvice">
<tx:attributes>
<tx:methodname="get*"read-only="true"/>
<tx:methodname="*"/>
</tx:attributes>
</tx:advice>
<tx:adviceid="noTxAdvice">
<tx:attributes>
<tx:methodname="*"propagation="NEVER"/>
</tx:attributes>
</tx:advice>
<!--othertransactioninfrastructurebeanssuchasaPlatformTransactionManager
</beans>
9.5.5.<tx:advice/> <tx:advice/> <tx:advice/>
REQUIRED
DEFAULT
/
RuntimeExceptionchecked Exception <tx:advice/> <tx:attributes/> <tx:method/>
9.1.<tx:method/>
name *
propagation REQUIRED
isolation DEFAULT
timeout -1
read-only false
rollback-
for Exception(s)
'com.foo.MyBusinessException,ServletException'
no-
rollback-
for
Exception(s)
'com.foo.MyBusinessException,ServletException'
WebLogic'com.foo.BusinessService.handlePayment'.
9.5.6. @Transactional
@TransactionalJava5TigerXMLJava @Transactional
//theserviceclassthatwewanttomaketransactional
@Transactional
publicclassDefaultFooServiceimplementsFooService{
FoogetFoo(StringfooName);
FoogetFoo(StringfooName,StringbarName);
voidinsertFoo(Foofoo);
voidupdateFoo(Foofoo);
}
POJOSpringIoCbean xml
<!--fromthefile'context.xml'-->
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--thisistheserviceobjectthatwewanttomaketransactional-->
<beanid="fooService"class="x.y.service.DefaultFooService"/>
<!--enabletheconfigurationoftransactionalbehaviorbasedonannotations-->
<tx:annotation-driventransaction-manager="txManager"/>
<!--aPlatformTransactionManagerisstillrequired-->
<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<!--(thisdependencyisdefinedsomewhereelse)-->
@Transactional
@Transactional public protectedprivatepackage-visible@TransactionalAspectJ()
<propertyname="dataSource"ref="dataSource"/>
</bean>
<!--other<bean/>definitionshere-->
</beans>
'transactionManager' PlatformTransactionManager
bean <tx:annotation-driven/> 'transaction-
manager' PlatformTransactionManagerbean'transaction-manager'
@Transactional public@Transactional @Transactionalbeans<tx:annotation-driven/> Spring @Transactional @Transactional
Spring@Transactional‘’ ‘’‘’AspectJ
9.2.<tx:annotation-driven/>
transaction-
managertransactionManager transactionManager
mode proxy
“proxy”SpringAOPbean"aspectj"SpringAspectJAspectJclasspathspring-aspects.jar() (
proxy-
target-classfalse
@Transactional "target-class" "true""proxy-target-class"" false"JDK( 6.6“”
order Ordered.LOWEST_PRECEDENCE @Transactionalbean AOP(6.2.4.7“” ) AOP
<tx:annotation-driven/>" proxy-target-class"@Transactional " proxy-target-class"" true"" proxy-target-class"" false"JDK
DefaultFooService@Transactional
@Transactional(readOnly=true)
publicclassDefaultFooServiceimplementsFooService{
publicFoogetFoo(StringfooName){
//dosomething
}
//thesesettingshaveprecedenceforthismethod
@Transactional(readOnly=false,propagation=Propagation.REQUIRES_NEW)
publicvoidupdateFoo(Foofoo){
//dosomething
}
}
9.5.6.1.@Transactional@Transactional “ ”
PROPAGATION_REQUIRED
ISOLATION_DEFAULT
/
RuntimeExceptionchecked Exception
@Transactional
9.3.@Transactional
propagation Propagation
isolation Isolation ISOLATION_DEFAULT
readOnly vs.
timeout int
rollbackFor ClassThrowable
checkedexceptionsuncheckedexceptions RuntimeException
rollbackForClassname ClassThrowable
noRollbackFor ClassThrowable
noRollbackForClassname ClassThrowable
WebLogichandlePayment(..)
com.foo.BusinessService.handlePayment
9.5.7.Spring SpringSpring
9.5.7.1.required
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED rollback-onlyPROPAGATION_REQUIRED rollback-onlyrollback-only
9.5.7.2.RequiresNew
PROPAGATION_REQUIRES_NEW
PROPAGATION_REQUIRES_NEW
9.5.7.3.NestedPROPAGATION_NESTED Spring DataSourceTransactionManager).
9.5.8. advice profiling <tx:annotation-driven/>
updateFoo(Foo)
profilingaspect
AOP 6 SpringAOP
profilingaspect Ordered
packagex.y;
importorg.aspectj.lang.ProceedingJoinPoint;
importorg.springframework.util.StopWatch;
importorg.springframework.core.Ordered;
publicclassSimpleProfilerimplementsOrdered{
privateintorder;
//allowsustocontroltheorderingofadvice
publicintgetOrder(){
returnthis.order;
}
publicvoidsetOrder(intorder){
this.order=order;
}
//thismethodisthearoundadvice
publicObjectprofile(ProceedingJoinPointcall)throwsThrowable{
ObjectreturnValue;
StopWatchclock=newStopWatch(getClass().getName());
try{
clock.start(call.toShortString());
returnValue=call.proceed();
}finally{
clock.stop();
System.out.println(clock.prettyPrint());
}
returnreturnValue;
}
}
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<beanid="fooService"class="x.y.service.DefaultFooService"/>
<!--thisistheaspect-->
<beanid="profiler"class="x.y.SimpleProfiler">
<!--executebeforethetransactionaladvice(hencethelowerordernumber)-->
<propertyname="order"value="1"/>
</bean>
<tx:annotation-driventransaction-manager="txManager"order="200"
<aop:config>
<!--thisadvicewillexecutearoundthetransactionaladvice-->
<aop:aspectid="profilingAspect"ref="profiler">
<aop:pointcutid="serviceMethodWithReturnValue"
expression="execution(!voidx.y..*Service.*(..))"/>
<aop:aroundmethod="profile"pointcut-ref="serviceMethodWithReturnValue"/>
</aop:aspect>
</aop:config>
<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<propertyname="driverClassName"value="oracle.jdbc.driver.OracleDriver"/>
<propertyname="url"value="jdbc:oracle:thin:@rj-t42:1521:elvis"/>
<propertyname="username"value="scott"/>
<propertyname="password"value="tiger"/>
</bean>
<beanid="txManager"class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<propertyname="dataSource"ref="dataSource"/>
</bean>
</beans>
'fooService'beanXML
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<beanid="fooService"class="x.y.service.DefaultFooService"/>
<!--theprofilingadvice-->
<beanid="profiler"class="x.y.SimpleProfiler">
<!--executebeforethetransactionaladvice(hencethelowerordernumber)-->
<propertyname="order"value="1"/>
</bean>
<aop:config>
<aop:pointcutid="entryPointMethod"expression="execution(*x.y..*Service.*(..))"/>
<!--willexecuteaftertheprofilingadvice(c.f.theorderattribute)-->
<aop:advisor
advice-ref="txAdvice"
pointcut-ref="entryPointMethod"
order="2"/><!--ordervalueishigherthantheprofilingaspect-->
<aop:aspectid="profilingAspect"ref="profiler">
<aop:pointcutid="serviceMethodWithReturnValue"
expression="execution(!voidx.y..*Service.*(..))"/>
<aop:aroundmethod="profile"pointcut-ref="serviceMethodWithReturnValue"/>
</aop:aspect>
</aop:config>
<tx:adviceid="txAdvice"transaction-manager="txManager">
<tx:attributes>
<tx:methodname="get*"read-only="true"/>
<tx:methodname="*"/>
</tx:attributes>
</tx:advice>
<!--other<bean/>definitionssuchasaDataSourceanda
</beans>
'fooService'bean beanorder
9.5.9.AspectJ @Transactional
AspectJSpringSpring @Transactional @Transactional
spring-aspects.jarorg.springframework.transaction.aspectj.AnnotationTransactionAspect
SpringSpring
9.5.6“ @Transactional” 6 SpringAOP
//constructanappropriatetransactionmanager
DataSourceTransactionManagertxManager=newDataSourceTransactionManager(getDataSource());
//configuretheAnnotationTransactionAspecttouseit;thismustbedonebeforeexecutinganytransactionalmethods
AnnotationTransactionAspect.aspectOf().setTransactionManager(txManager);
aspect / AspectJJava @Transactional @Transactional AnnotationTransactionAspect AspectJ AspectJ Development
Guide“”load-timeweaving 6.8.4“SpringAspectJLTW” AspectJ“”
9.6.Spring
TransactionTemplate
PlatformTransactionManagerSpring TransactionTemplateJTA UserTransactionAPI
9.6.1. TransactionTemplate
TransactionTemplateSpring JdbcTemplate
TransactionTemplateSpringAPITransactionTemplate TransactionCallback
TransactionCallbackTransactionTemplateexecute(..)
publicclassSimpleServiceimplementsService{
//singleTransactionTemplatesharedamongstallmethodsinthisinstance
privatefinalTransactionTemplatetransactionTemplate;
//useconstructor-injectiontosupplythePlatformTransactionManager
publicSimpleService(PlatformTransactionManagertransactionManager){
Assert.notNull(transactionManager,"The'transactionManager'argumentmustnotbenull.");
this.transactionTemplate=newTransactionTemplate(transactionManager);
}
publicObjectsomeServiceMethod(){
returntransactionTemplate.execute(newTransactionCallback(){
//thecodeinthismethodexecutesinatransactionalcontext
publicObjectdoInTransaction(TransactionStatusstatus){
updateOperation1();
returnresultOfUpdateOperation2();
}
});
}
}
TransactionCallbackWithoutResult
transactionTemplate.execute(newTransactionCallbackWithoutResult
protectedvoiddoInTransactionWithoutResult(TransactionStatusstatus){
updateOperation1();
updateOperation2();
}
});
TransactionStatus setRollbackOnly()
transactionTemplate.execute(newTransactionCallbackWithoutResult(){
protectedvoiddoInTransactionWithoutResult(TransactionStatusstatus){
try{
updateOperation1();
updateOperation2();
}catch(SomeBusinessExeptionex){
status.setRollbackOnly();
}
}
});
9.6.1.1.TransactionTemplate TransactionTemplate
publicclassSimpleServiceimplementsService{
privatefinalTransactionTemplatetransactionTemplate;
publicSimpleService(PlatformTransactionManagertransactionManager){
Assert.notNull(transactionManager,"The'transactionManager'argumentmustnotbenull.");
this.transactionTemplate=newTransactionTemplate(transactionManager);
//thetransactionsettingscanbesethereexplicitlyifsodesired
this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED);
this.transactionTemplate.setTimeout(30);//30seconds
//andsoforth...
}
}
SpringXML TransactionTemplate 'sharedTransactionTemplate'
<beanid="sharedTransactionTemplate"
class="org.springframework.transaction.support.TransactionTemplate">
<propertyname="isolationLevelName"value="ISOLATION_READ_UNCOMMITTED"/>
<propertyname="timeout"value="30"/>
</bean>"
TransactionTemplate TransactionTemplate
TransactionTemplate TransactionTemplate()TransactionTemplate
9.6.2. PlatformTransactionManager
org.springframework.transaction.PlatformTransactionManagerbean PlatformTransactionManagerbeanTransactionStatus
DefaultTransactionDefinitiondef=newDefaultTransactionDefinition();
//explicitlysettingthetransactionnameissomethingthatcanonlybedoneprogrammatically
def.setName("SomeTxName");
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
TransactionStatusstatus=txManager.getTransaction(def);
try{
//executeyourbusinesslogichere
}
catch(MyExceptionex){
txManager.rollback(status);
throwex;
}
txManager.commit(status);
9.7.Web
9.8.SpringSpring JtaTransactionManager JNDIJTAUserTransaction TransactionManagerTransactionManager JtaTransactionManager
J2EESpring JtaTransactionManagerGeronimoOracleOC4J SpringIBMWebSphereBEAWebLogicOracleOC4J.WebLogicWebSphereOC4J '<tx:jta-transaction-manager/>'
9.8.1.IBMWebSphereWebSphere6.0SpringJTA WebSphereUowTransactionManagerWebSphere6.0.2.196.1.0.9 UOWManager
PROPAGATION_REQUIRES_NEW/IBMWebSphere5.1Spring WebSphereTransactionManagerFactoryBeanWebSphere JTATransactionManager beanJTATransactionManager Spring JtaTransactionManager
UserTransactionjavadocWebSphereTransactionManagerFactoryBeanWAS5.16.0WebSphereUowTransactionManager
9.8.2.BEAWebLogicWebLogic 8.1WebLogic WebLogicJtaTransactionManager JtaTransactionManagerWebLogicSpringJTA
9.8.3.OracleOC4JSpringOC4J10.1.3 OC4JJtaTransactionManager
WebLogicJtaTransactionManager OC4J JTA Spring JtaTransactionManager OC4J OC4JJtaTransactionManagerJTA
9.9.
9.9.1. DataSource PlatformTransactionManager Springorg.springframework.transaction.jta.JtaTransactionManager Spring
9.10.Spring
InfoQ JavaJavaTransactionDesignStrategies Java
10DAO
10.1.10.2.10.3.DAO
10.1.SpringDAO() JDBCHibernateJDO
10.2.Spring SQLExceptionJDBCSpringHibernatechecked DAOcatch/throwSpringORMSessionFactoryUtils convertHibernateAccessException
convertJdoAccessException org.springframework.dao
unchecked DAOSpring DataAccessException
10.3.DAOJDBCJDOHibernate Spring
JdbcDaoSupport-JDBC DataSource
HibernateDaoSupport-Hibernate SessionFactory
HibernateTemplate HibernateTemplateexceptiontranslatorJdoDaoSupport-JDO PersistenceManagerFactory
JpaDaoSupport-JPA EntityManagerFactory
11JDBC
11.1.11.1.1.11.1.2.SpringJDBC
11.2.JDBCJDBC11.2.1.JdbcTemplate11.2.2.NamedParameterJdbcTemplate11.2.3.SimpleJdbcTemplate11.2.4.DataSource11.2.5.SQLExceptionTranslator11.2.6.SQL11.2.7.11.2.8.11.2.9.
11.3.11.3.1.DataSourceUtils11.3.2.SmartDataSource11.3.3.AbstractDataSource11.3.4.SingleConnectionDataSource11.3.5.DriverManagerDataSource11.3.6.TransactionAwareDataSourceProxy11.3.7.DataSourceTransactionManager11.3.8.NativeJdbcExtractor
11.4.JDBC11.4.1.JdbcTemplate11.4.2.SimpleJdbcTemplate
11.5.SimpleJdbcJDBC11.5.1.SimpleJdbcInsert11.5.2.SimpleJdbcInsert11.5.3.SimpleJdbcInsert11.5.4.SqlParameterSource11.5.5.SimpleJdbcCall11.5.6.SimpleJdbcCall11.5.7.SqlParameters11.5.8.SimpleJdbcCall11.5.9.SimpleJdbcCallResultSet/REFCursor
11.6.JavaJDBC11.6.1.SqlQuery11.6.2.MappingSqlQuery
11.6.3.SqlUpdate11.6.4.StoredProcedure11.6.5.SqlFunction
11.7.11.7.1.SQL11.7.2.BLOBCLOB11.7.3.IN11.7.4.
11.1.SpringJDBCSpringJDBC
SQL
SQL
SpringJDBCAPI
11.1.1.SpringJDBCSpringJdbcTemplate,Spring2.5SimpleJdbc;RDBMSObject,JDO .,,
JdbcTemplate-SpringJDBC,JdbcTemplateJdbcTemplateJDK1.4NamedParameterJdbcTemplate-JdbcTemplateJDBC“?”SQLJDK1.4SimpleJdbcTemplate - JdbcTemplateNamedParameterJdbcTemplateJava5varargsautoboxingAPIJava5SimpleJdbcInsertSimpleJdbcCall -MapMapkeySimpleJdbcTemplateJDK5RDBMS MappingSqlQuery, SqlUpdate and StoredProcedure -QueryJDK1.4
11.1.2.SpringJDBC
SpringFrameworkJDBC core dataSourceobjectsupport
org.springframework.jdbc.coreJdbcTemplatecallbackinterfaceorg.springframework.jdbc.core.simple SimpleJdbcTemplateSimpleJdbcInsert SimpleJdbcCallorg.springframework.jdbc.core.namedparamNamedParameterJdbcTemplateorg.springframework.jdbc.datasourceDataSource DataSourceJ2EE JNDI
org.springframework.jdbc.objectRDBMSJDOJDBC org.springframework.jdbc.coreJDBC
org.springframework.jdbc.supportSQLException
JDBC org.springframework.daoSpringJDBCJDBCRDBMSunchecked
11.2.JDBCJDBC
11.2.1.JdbcTemplateJdbcTemplatecoreJDBCSQL SQL
JdbcTemplate PreparedStatementCreator
PreparedStatementSQL CallableStatementCreateor
CallableStatement RowCallbackHandler
DAO DataSourceJdbcTemplateSpringIoCJdbcTemplatebeanDAODataSourceSpringIoCbean DataSourcebeanservice DataSourcebeanJdbcTemplatebeanJdbcTemplateSQL“DEBUG”categoryJdbcTemplate
11.2.1.1.JdbcTemplate JdbcTemplateJavadoc
11.2.1.1.1.SELECT
introwCount=this.jdbcTemplate.queryForInt("selectcount(0)fromt_accrual");
intcountOfActorsNamedJoe=this.jdbcTemplate.queryForInt(
"selectcount(0)fromt_actorswherefirst_name=?",newObject[]{"Joe"});
String
Stringsurname=(String)this.jdbcTemplate.queryForObject(
"selectsurnamefromt_actorwhereid=?",
newObject[]{newLong(1212)},String.class);
Actoractor=(Actor)this.jdbcTemplate.queryForObject(
"selectfirst_name,surnamefromt_actorwhereid=?",
newObject[]{newLong(1212)},
newRowMapper(){
publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{
Actoractor=newActor();
actor.setFirstName(rs.getString("first_name"));
actor.setSurname(rs.getString("surname"));
returnactor;
}
});
Collectionactors=this.jdbcTemplate.query(
"selectfirst_name,surnamefromt_actor",
newRowMapper(){
publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{
Actoractor=newActor();
actor.setFirstName(rs.getString("first_name"));
actor.setSurname(rs.getString("surname"));
returnactor;
}
});
2 RowMapper
publicCollectionfindAllActors(){
returnthis.jdbcTemplate.query("selectfirst_name,surnamefromt_actor",newActorMapper());
}
privatestaticfinalclassActorMapperimplementsRowMapper{
publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{
Actoractor=newActor();
actor.setFirstName(rs.getString("first_name"));
actor.setSurname(rs.getString("surname"));
returnactor;
}
}
11.2.1.1.2.INSERT/UPDATE/DELETE
this.jdbcTemplate.update(
"insertintot_actor(first_name,surname)values(?,?)",
newObject[]{"Leonor","Watling"});
this.jdbcTemplate.update(
"updatet_actorsetweapon=?whereid=?",
newObject[]{"Banjo",newLong(5276)});
this.jdbcTemplate.update(
"deletefromactorwhereid=?",
newObject[]{newLong.valueOf(actorId)});
11.2.1.1.3.
execute(..)SQLDDL
this.jdbcTemplate.execute("createtablemytable(idinteger,namevarchar(100))");
this.jdbcTemplate.update(
"callSUPPORT.REFRESH_ACTORS_SUMMARY(?)",
newObject[]{Long.valueOf(unionId)});
11.2.1.2.JdbcTemplateJdbcTemplate JdbcTemplate“”“”DAOJdbcTemplate DataSourceJdbcTemplate SimpleJdbcTemplateNamedParameterJdbcTemplateSpringDataSource DataSourceDAO JdbcTemplateDataSourcesetter
DAO
publicclassJdbcCorporateEventDaoimplementsCorporateEventDao{
privateJdbcTemplatejdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.jdbcTemplate=newJdbcTemplate(dataSource);
}
//JDBC-backedimplementationsofthemethodsontheCorporateEventDao
}
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanid="corporateEventDao"class="com.example.JdbcCorporateEventDao">
<propertyname="dataSource"ref="dataSource"/>
</bean>
<!--theDataSource(parameterizedforconfigurationviaa
<beanid="dataSource"destroy-method="close"class="org.apache.commons.dbcp.BasicDataSource">
<propertyname="driverClassName"value="${jdbc.driverClassName}"/>
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
</bean>
</beans>
Spring JdbcDaoSupportJDBCDAO JdbcDaoSupportsetDataSource(..)
DAOSQL JdbcTemplate
DataSourcesJdbcTemplates
11.2.2.NamedParameterJdbcTemplateNamedParameterJdbcTemplateJDBC '?' NamedParameterJdbcTemplate
JdbcTemplate JdbcTemplate NamedParameterJdbcTemplate
JdbcTemplateJDBC
//someJDBC-backedDAOclass...
privateNamedParameterJdbcTemplatenamedParameterJdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.namedParameterJdbcTemplate=newNamedParameterJdbcTemplate(dataSource);
}
publicintcountOfActorsByFirstName(StringfirstName){
Stringsql="selectcount(0)fromT_ACTORwherefirst_name=:first_name";
SqlParameterSourcenamedParameters=newMapSqlParameterSource("first_name",firstName);
returnnamedParameterJdbcTemplate.queryForInt(sql,namedParameters);
}
'sql' 'namedParameters' MapSqlParameterSource
Map NamedParameterJdbcTemplate
NamedParameterJdbcOperationsNamedParameterJdbcTemplate
//someJDBC-backedDAOclass...
privateNamedParameterJdbcTemplatenamedParameterJdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.namedParameterJdbcTemplate=newNamedParameterJdbcTemplate(dataSource);
}
publicintcountOfActorsByFirstName(StringfirstName){
Stringsql="selectcount(0)fromT_ACTORwherefirst_name=:first_name";
MapnamedParameters=Collections.singletonMap("first_name",firstName);
returnthis.namedParameterJdbcTemplate.queryForInt(sql,namedParameters);
}
NamedParameterJdbcTemplateSqlParameterSource()MapSqlParameterSource SqlParameterSourceNamedParameterJdbcTemplate MapSqlParameterSource java.util.Map
MapKeyMapValueSqlParameterSourceBeanPropertySqlParameterSourceJava JavaBean
JavaBean
publicclassActor{
privateLongid;
privateStringfirstName;
privateStringlastName;
publicStringgetFirstName(){
returnthis.firstName;
}
publicStringgetLastName(){
returnthis.lastName;
}
publicLonggetId(){
returnthis.id;
}
//settersomitted...
}
//someJDBC-backedDAOclass...
privateNamedParameterJdbcTemplatenamedParameterJdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.namedParameterJdbcTemplate=newNamedParameterJdbcTemplate(dataSource);
}
publicintcountOfActors(ActorexampleActor){
//noticehowthenamedparametersmatchthepropertiesoftheabove'
Stringsql="selectcount(0)fromT_ACTORwherefirst_name=:firstNameandlast_name=:lastName";
SqlParameterSourcenamedParameters=newBeanPropertySqlParameterSource(exampleActor);
returnthis.namedParameterJdbcTemplate.queryForInt(sql,namedParameters);
}
NamedParameterJdbcTemplateJdbcTemplateJdbcTemplate getJdbcOperations()
11.2.1.2“ JdbcTemplate” NamedParameterJdbcTemplate
11.2.3.SimpleJdbcTemplate
SimpleJdbcTemplateJava5SimpleJdbcTemplateJdbcTemplateJava5varargsautoboxingSimpleJdbcTemplateJava5Java5Java5JDK“beforeandafter”SimpleJdbcTemplateSimpleJdbcTemplate
//classicJdbcTemplate-style...
privateJdbcTemplatejdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.jdbcTemplate=newJdbcTemplate(dataSource);
}
publicActorfindActor(longid){
Stringsql="selectid,first_name,last_namefromT_ACTORwhereid=?";
RowMappermapper=newRowMapper(){
publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{
Actoractor=newActor();
actor.setId(rs.getLong("id"));
actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
returnactor;
}
};
//noticethecast,thewrappingupofthe'id'argument
//inanarray,andtheboxingofthe'id'argumentasareferencetype
return(Actor)jdbcTemplate.queryForObject(sql,mapper,newObject[]{Long.valueOf(id)});
}
SimpleJdbcTemplate“”
//SimpleJdbcTemplate-style...
privateSimpleJdbcTemplatesimpleJdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
}
publicActorfindActor(longid){
Stringsql="selectid,first_name,last_namefromT_ACTORwhereid=?";
ParameterizedRowMapper<Actor>mapper=newParameterizedRowMapper<Actor>(){
//noticethereturntypewithrespecttoJava5covariantreturntypes
publicActormapRow(ResultSetrs,introwNum)throwsSQLException{
Actoractor=newActor();
actor.setId(rs.getLong("id"));
actor.setFirstName(rs.getString("first_name"));
actor.setLastName(rs.getString("last_name"));
returnactor;
}
};
returnthis.simpleJdbcTemplate.queryForObject(sql,mapper,id);
}
11.2.1.2“ JdbcTemplate” SimpleJdbcTemplate
SimpleJdbcTemplateJdbcTemplate JdbcTemplate
SimpleJdbcTemplate getJdbcOperations()
JdbcOperations
11.2.4.DataSourceSpring DataSourceContainerFrameworkSpringJDBCJNDISpringDataSourceWebDriverManagerDataSourceDataSource DriverManagerDataSource
JDBC JDBC DriverManager
DriverManagerDataSource
DriverManagerDataSourcedataSource=newDriverManagerDataSource();
dataSource.setDriverClassName("org.hsqldb.jdbcDriver");
dataSource.setUrl("jdbc:hsqldb:hsql://localhost:");
dataSource.setUsername("sa");
dataSource.setPassword("");
11.2.5.SQLExceptionTranslatorSQLExceptionTranslator SQLException
org.springframework.dao.DataAccessException (JDBCSQLStatecode)OracleerrorcodeSQLErrorCodeSQLExceptionTranslatorSQLExceptionTranslator errorcode SQLStateJavaBean SQLErrorCodeserrorcode JavaBeanSQLErrorCodesFactory “sql-error-codes.xml”DatabaseProductNameSQLErrorCodeSQLExceptionTranslator
SQLErrorCodeSQLExceptionTranslator
SQLExceptionerrorcodeerrorcodeclasspathsql-error-codes.xmlmetadatadatabasenamefallback SQLStateSQLExceptionTranslatorfallback
SQLErrorCodeSQLExceptionTranslator
publicclassMySQLErrorCodesTranslatorextendsSQLErrorCodeSQLExceptionTranslator{
protectedDataAccessExceptioncustomTranslate(Stringtask,Stringsql,SQLExceptionsqlex){
if(sqlex.getErrorCode()==-12345){
returnnewDeadlockLoserDataAccessException(task,sqlex);
}
returnnull;
}
}
errorcode '-12345'SQLExceptionerrorcodesetExceptionTranslator JdbcTemplate
//createaJdbcTemplateandsetdatasource
JdbcTemplatejt=newJdbcTemplate();
jt.setDataSource(dataSource);
//createacustomtranslatorandsettheDataSourceforthedefaulttranslationlookup
MySQLErrorCodesTransalatortr=newMySQLErrorCodesTransalator();
tr.setDataSource(dataSource);
jt.setExceptionTranslator(tr);
//usetheJdbcTemplateforthisSqlUpdate
SqlUpdatesu=newSqlUpdate();
su.setJdbcTemplate(jt);
su.setSql("updateorderssetshipping_charge=shipping_charge*1.05");
su.compile();
su.update();
sql-error-codes.xml
11.2.6.SQLSQL DataSourceJdbcTemplate
importjavax.sql.DataSource;
importorg.springframework.jdbc.core.JdbcTemplate;
publicclassExecuteAStatement{
privateJdbcTemplatejdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.jdbcTemplate=newJdbcTemplate(dataSource);
}
publicvoiddoExecute(){
this.jdbcTemplate.execute("createtablemytable(idinteger,namevarchar(100))");
}
}
11.2.7.execute JdbcTemplate countqueryForLong(..)queryForObject(..) queryForObjectJDBCJavaInvalidDataAccessApiUsageException
importjavax.sql.DataSource;
importorg.springframework.jdbc.core.JdbcTemplate;
publicclassRunAQuery{
privateJdbcTemplatejdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.jdbcTemplate=newJdbcTemplate(dataSource);
}
publicintgetCount(){
returnthis.jdbcTemplate.queryForInt("selectcount(*)frommytable");
}
publicStringgetName(){
return(String)this.jdbcTemplate.queryForObject("selectnamefrommytable",String.class);
}
publicvoidsetDataSource(DataSourcedataSource){
this.dataSource=dataSource;
}
}
JdbcTemplateList List
privateJdbcTemplatejdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.jdbcTemplate=newJdbcTemplate(dataSource);
}
publicListgetList(){
returnthis.jdbcTemplate.queryForList("select*frommytable");
}
[{name=Bob,id=1},{name=Mary,id=2}]
11.2.8.JdbcTemplate
importjavax.sql.DataSource;
importorg.springframework.jdbc.core.JdbcTemplate;
publicclassExecuteAnUpdate{
privateJdbcTemplatejdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.jdbcTemplate=newJdbcTemplate(dataSource);
}
publicvoidsetName(intid,Stringname){
this.jdbcTemplate.update(
"updatemytablesetname=?whereid=?",
newObject[]{name,newInteger(id)});
}
}
11.2.9.JdbcTemplateupdateJDBC3.0-13.6PreparedStatementCreatorInsert KeyHolderupdatePreparedStatementOracle
finalStringINSERT_SQL="insertintomy_test(name)values(?)";
finalStringname="Rob";
KeyHolderkeyHolder=newGeneratedKeyHolder();
jdbcTemplate.update(
newPreparedStatementCreator(){
publicPreparedStatementcreatePreparedStatement(Connectionconnection)throwsSQLException{
PreparedStatementps=
connection.prepareStatement(INSERT_SQL,newString[]{"id"});
ps.setString(1,name);
returnps;
}
},
keyHolder);
//keyHolder.getKey()nowcontainsthegeneratedkey
11.3.
11.3.1.DataSourceUtilsDataSourceUtils JNDI
11.3.2.SmartDataSourceSmartDataSourceDataSource
11.3.3.AbstractDataSourceAbstractDataSourceDataSource abstract DataSource
11.3.4.SingleConnectionDataSourceSingleConnectionDataSourceSmartDataSourcecloseConnectionSingleConnectionDataSourceJNDI
11.3.5.DriverManagerDataSourceDriverManagerDataSourceSmartDataSourcebeanpropertiesJDBCDriver
J2EEapplicationcontextConnection.close() DataSourceJavaBean
DriverManagerDataSource
11.3.6.TransactionAwareDataSourceProxyTransactionAwareDataSourceProxyDataSource DataSourceSpringJ2EEJNDI DataSource
JDBC DataSource
DataSourceUtils
TransactionAwareDataSourceProxyJavaDocs
11.3.7.DataSourceTransactionManagerDataSourceTransactionManager PlatformTransactionManagerJDBCDataSourceJDBC
DataSourceUtils.getConnection(DataSource) JDBCJ2EEDataSource.getConnection unchecked org.springframework.dao
checkedSQLExceptionSpringFramework JdbcTemplate
DataSourceTransactionManagerDataSourceUtilsDataSourceTransactionManagerSQLDataSourceUtils.applyTransactionTimeout(..)
DataSourceTransactionManagerJtaTransactionManager
DataSourceTransactionManagerJTADataSourceUtils.getConnection(DataSource) JDBCJtaTransactionManager
11.3.8.NativeJdbcExtractorJDBCAPIJDBC Connection,StatementResultSetDataSource
NativeJdbcExtractorJdbcTemplateOracleLobHandler
NativeJdbcExtractorSimpleNativeJdbcExtractor
C3P0NativeJdbcExtractor
CommonsDbcpNativeJdbcExtractor
JBossNativeJdbcExtractor
WebLogicNativeJdbcExtractor
WebSphereNativeJdbcExtractor
XAPoolNativeJdbcExtractorSimpleNativeJdbcExtractor ConnectionJavaDocs
11.4.JDBCJDBCpreparedstatement
11.4.1.JdbcTemplateJdbcTemplate BatchPreparedStatementSetter,getBatchSize setValuespreparedstatementactorlist
publicclassJdbcActorDaoimplementsActorDao{
privateJdbcTemplatejdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.jdbcTemplate=newJdbcTemplate(dataSource);
}
publicint[]batchUpdate(finalListactors){
int[]updateCounts=jdbcTemplate.batchUpdate(
"updatet_actorsetfirst_name=?,last_name=?whereid=?",
newBatchPreparedStatementSetter(){
publicvoidsetValues(PreparedStatementps,inti)throwsSQLException{
ps.setString(1,((Actor)actors.get(i)).getFirstName());
ps.setString(2,((Actor)actors.get(i)).getLastName());
ps.setLong(3,((Actor)actors.get(i)).getId().longValue());
}
publicintgetBatchSize(){
returnactors.size();
}
});
returnupdateCounts;
}
//...additionalmethods
}
isBatchExhausted
11.4.2.SimpleJdbcTemplateSimpleJdbcTemplatepreparedstatementAPISqlParameterSource, SqlParameterSource.createBatch
JavaBeanMap
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
}
publicint[]batchUpdate(finalList<Actor>actors){
SqlParameterSource[]batch=SqlParameterSourceUtils.createBatch(actors.toArray());
int[]updateCounts=simpleJdbcTemplate.batchUpdate(
"updatet_actorsetfirst_name=:firstName,last_name=:lastNamewhereid=:id",
batch);
returnupdateCounts;
}
//...additionalmethods
}
“?”ListSQLStatementSQLStatement“?”
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
}
publicint[]batchUpdate(finalList<Actor>actors){
List<Object[]>batch=newArrayList<Object[]>();
for(Actoractor:actors){
Object[]values=newObject[]{
actor.getFirstName(),
actor.getLastName(),
actor.getId()};
batch.add(values);
}
int[]updateCounts=simpleJdbcTemplate.batchUpdate(
"updatet_actorsetfirst_name=?,last_name=?whereid=?",
batch);
returnupdateCounts;
}
//...additionalmethods
}
int JDBCJDBC-2
11.5.SimpleJdbcJDBCSimpleJdbcInsertSimpleJdbcCallJDBC
11.5.1.SimpleJdbcInsertSimpleJdbcInsert SimpleJdbcInsert
SimpleJdbcInsert withTableNametable “fluid”SimpleJdbcInsert
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
privateSimpleJdbcInsertinsertActor;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
this.insertActor=
newSimpleJdbcInsert(dataSource).withTableName("t_actor");
}
publicvoidadd(Actoractor){
Map<String,Object>parameters=newHashMap<String,Object>(3);
parameters.put("id",actor.getId());
parameters.put("first_name",actor.getFirstName());
parameters.put("last_name",actor.getLastName());
insertActor.execute(parameters);
}
//...additionalmethods
}
java.utils.Map MapkeyInsert
11.5.2.SimpleJdbcInsertidActor
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
privateSimpleJdbcInsertinsertActor;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
this.insertActor=
newSimpleJdbcInsert(dataSource)
.withTableName("t_actor")
.usingGeneratedKeyColumns("id");
}
publicvoidadd(Actoractor){
Map<String,Object>parameters=newHashMap<String,Object>(2);
parameters.put("first_name",actor.getFirstName());
parameters.put("last_name",actor.getLastName());
NumbernewId=insertActor.executeAndReturnKey(parameters);
actor.setId(newId.longValue());
}
//...additionalmethods
}
insertidMapJava java.lang.Number
11.5.3.SimpleJdbcInsertSimpleJdbcInsertinsert
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
privateSimpleJdbcInsertinsertActor;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
this.insertActor=
newSimpleJdbcInsert(dataSource)
.withTableName("t_actor")
.usingColumns("first_name","last_name")
.usingGeneratedKeyColumns("id");
}
publicvoidadd(Actoractor){
Map<String,Object>parameters=newHashMap<String,Object>(2);
parameters.put("first_name",actor.getFirstName());
parameters.put("last_name",actor.getLastName());
NumbernewId=insertActor.executeAndReturnKey(parameters);
actor.setId(newId.longValue());
}
//...additionalmethods
}
insert
11.5.4.SqlParameterSourceMapSpring SqlParameterSourceBeanPropertySqlParameterSourceJavaBeangetter
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
privateSimpleJdbcInsertinsertActor;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
this.insertActor=
newSimpleJdbcInsert(dataSource)
.withTableName("t_actor")
.usingGeneratedKeyColumns("id");
}
publicvoidadd(Actoractor){
SqlParameterSourceparameters=newBeanPropertySqlParameterSource(actor);
NumbernewId=insertActor.executeAndReturnKey(parameters);
actor.setId(newId.longValue());
}
//...additionalmethods
}
MapSqlParameterSourceMap addValue
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
privateSimpleJdbcInsertinsertActor;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
this.insertActor=
newSimpleJdbcInsert(dataSource)
.withTableName("t_actor")
.usingGeneratedKeyColumns("id");
}
publicvoidadd(Actoractor){
SqlParameterSourceparameters=newMapSqlParameterSource()
.addValue("first_name",actor.getFirstName())
.addValue("last_name",actor.getLastName());
NumbernewId=insertActor.executeAndReturnKey(parameters);
actor.setId(newId.longValue());
}
//...additionalmethods
}
11.5.5.SimpleJdbcCall SimpleJdbcCall VARCHARDATEfirst_namelast_namebirth_date MySQL
CREATEPROCEDUREread_actor(
INin_idINTEGER,
OUTout_first_nameVARCHAR(100),
OUTout_last_nameVARCHAR(100),
OUTout_birth_dateDATE)
BEGIN
SELECTfirst_name,last_name,birth_date
INTOout_first_name,out_last_name,out_birth_date
FROMt_actorwhereid=in_id;
END;
“in_id”ActorSimpleJdbcCallSimpleJdbcInsert
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
privateSimpleJdbcCallprocReadActor;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
this.procReadActor=
newSimpleJdbcCall(dataSource)
.withProcedureName("read_actor");
}
publicActorreadActor(Longid){
SqlParameterSourcein=newMapSqlParameterSource()
.addValue("in_id",id);
Mapout=procReadActor.execute(in);
Actoractor=newActor();
actor.setId(id);
actor.setFirstName((String)out.get("out_first_name"));
actor.setLastName((String)out.get("out_last_name"));
actor.setBirthDate((Date)out.get("out_birth_date"));
returnactor;
}
//...additionalmethods
}
SimpleJdbcCall SqlParameterSourceexecuteMapMapkeyout_birth_date
executeActor MapkeyCaseInsensitiveMap JdbcTemplate setResultsMapCaseInsensitive
True JdbcTemplateSimpleJdbcCall commons-collections.jar
classpath
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcCallprocReadActor;
publicvoidsetDataSource(DataSourcedataSource){
JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
this.procReadActor=
newSimpleJdbcCall(jdbcTemplate)
.withProcedureName("read_actor");
}
//...additionalmethods
}
11.5.6.SimpleJdbcCallSimpleJdbcCall declareParameters SqlParameter
SqlParameter
useInParameterNames
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcCallprocReadActor;
publicvoidsetDataSource(DataSourcedataSource){
JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
this.procReadActor=
newSimpleJdbcCall(jdbcTemplate)
.withProcedureName("read_actor")
.withoutProcedureColumnMetaDataAccess()
.useInParameterNames("in_id")
.declareParameters(
newSqlParameter("in_id",Types.NUMERIC),
newSqlOutParameter("out_first_name",Types.VARCHAR),
newSqlOutParameter("out_last_name",Types.VARCHAR),
newSqlOutParameter("out_birth_date",Types.DATE)
);
}
//...additionalmethods
}
ServerOracleSybaseMySQLMicrosoftSQLServerOracle
11.5.7.SqlParametersSimpleJdbcRDBMS SqlParameterjava.sql.Types
newSqlParameter("in_id",Types.NUMERIC),
newSqlOutParameter("out_first_name",Types.VARCHAR),
SqlParameter SqlQuery
SqlOutParameter SqlInOutParameterSQLnumeric
11.5.8.SimpleJdbcCallMap executeObject
CREATEFUNCTIONget_actor_name(in_idINTEGER)
RETURNSVARCHAR(200)READSSQLDATA
BEGIN
DECLAREout_nameVARCHAR(200);
SELECTconcat(first_name,'',last_name)
INTOout_name
FROMt_actorwhereid=in_id;
RETURNout_name;
END;
SimpleJdbcCall
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
privateSimpleJdbcCallfuncGetActorName;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
this.funcGetActorName=
newSimpleJdbcCall(jdbcTemplate)
.withFunctionName("get_actor_name");
}
publicStringgetActorName(Longid){
SqlParameterSourcein=newMapSqlParameterSource()
.addValue("in_id",id);
Stringname=funcGetActorName.executeFunction(String.class,in);
returnname;
}
//...additionalmethods
}
String
11.5.9.SimpleJdbcCallResultSet/REFCursorResultSetJDBCreturningResultSet RowMappert_actorMySQL
CREATEPROCEDUREread_all_actors()
BEGIN
SELECTa.id,a.first_name,a.last_name,a.birth_dateFROMt_actora;
END;
RowMapperJavaBean ParameterizedBeanPropertyRowMapper
classnewInstance
publicclassJdbcActorDaoimplementsActorDao{
privateSimpleJdbcTemplatesimpleJdbcTemplate;
privateSimpleJdbcCallprocReadAllActors;
publicvoidsetDataSource(DataSourcedataSource){
this.simpleJdbcTemplate=newSimpleJdbcTemplate(dataSource);
JdbcTemplatejdbcTemplate=newJdbcTemplate(dataSource);
jdbcTemplate.setResultsMapCaseInsensitive(true);
this.procReadAllActors=
newSimpleJdbcCall(jdbcTemplate)
.withProcedureName("read_all_actors")
.returningResultSet("actors",
ParameterizedBeanPropertyRowMapper.newInstance(Actor.class));
}
publicListgetActorsList(){
Mapm=procReadAllActors.execute(newHashMap<String,Object>(0));
return(List)m.get("actors");
}
//...additionalmethods
}
MapActors
11.6.JavaJDBCorg.springframework.jdbc.object list
SpringRDBMS StoredProcedure
JdbcTemplate
RDBMS
11.6.1.SqlQuerySqlQuerySQL newResultReader()
MappingSqlQueryJava SqlQueryUpdatableSqlQuery
11.6.2.MappingSqlQueryMappingSqlQuery mapRow(ResultSet,int)
privateclassCustomerMappingQueryextendsMappingSqlQuery{
publicCustomerMappingQuery(DataSourceds){
super(ds,"SELECTid,nameFROMcustomerWHEREid=?");
super.declareParameter(newSqlParameter("id",Types.INTEGER));
compile();
}
publicObjectmapRow(ResultSetrs,introwNumber)throwsSQLException{
Customercust=newCustomer();
cust.setId((Integer)rs.getObject("id"));
cust.setName(rs.getString("name"));
returncust;
}
}
DataSourcedeclareParameter SqlParametercompile()SQL
publicCustomergetCustomer(Integerid){
CustomerMappingQuerycustQry=newCustomerMappingQuery(dataSource);
Object[]parms=newObject[1];
parms[0]=id;
Listcustomers=custQry.execute(parms);
if(customers.size()>0){
return(Customer)customers.get(0);
}
else{
returnnull;
}
}
getCustomeridCustomerMappingQueryexecute ListList Customer
11.6.3.SqlUpdateSqlUpdateSQL RdbmsOperationSqlUpdateSQLSqlQuery execute() SqlUpdateSQL
importjava.sql.Types;
importjavax.sql.DataSource;
importorg.springframework.jdbc.core.SqlParameter;
importorg.springframework.jdbc.object.SqlUpdate;
publicclassUpdateCreditRatingextendsSqlUpdate{
publicUpdateCreditRating(DataSourceds){
setDataSource(ds);
setSql("updatecustomersetcredit_rating=?whereid=?");
declareParameter(newSqlParameter(Types.NUMERIC));
declareParameter(newSqlParameter(Types.NUMERIC));
compile();
}
/**
*@paramidfortheCustomertobeupdated
*@paramratingthenewvalueforcreditrating
*@returnnumberofrowsupdated
*/
publicintrun(intid,intrating){
Object[]params=
newObject[]{
newInteger(rating),
newInteger(id)};
returnupdate(params);
}
}
11.6.4.StoredProcedureStoredProcedureRDBMS execute(..)
sqlRDBMS JDBC3.0JDBC3.0Oracle sysdate() StoredProcedure
execute()mapmapentrykeyvalue
importjava.sql.Types;
importjava.util.HashMap;
importjava.util.Iterator;
importjava.util.Map;
importjavax.sql.DataSource;
importorg.springframework.jdbc.core.SqlOutParameter;
importorg.springframework.jdbc.datasource.*;
importorg.springframework.jdbc.object.StoredProcedure;
publicclassTestStoredProcedure{
publicstaticvoidmain(String[]args){
TestStoredProceduret=newTestStoredProcedure();
t.test();
System.out.println("Done!");
}
voidtest(){
DriverManagerDataSourceds=newDriverManagerDataSource();
ds.setDriverClassName("oracle.jdbc.OracleDriver");
ds.setUrl("jdbc:oracle:thin:@localhost:1521:mydb");
ds.setUsername("scott");
ds.setPassword("tiger");
MyStoredProceduresproc=newMyStoredProcedure(ds);
Mapresults=sproc.execute();
printMap(results);
}
privateclassMyStoredProcedureextendsStoredProcedure{
privatestaticfinalStringSQL="sysdate";
publicMyStoredProcedure(DataSourceds){
setDataSource(ds);
setFunction(true);
setSql(SQL);
declareParameter(newSqlOutParameter("date",Types.DATE));
compile();
}
publicMapexecute(){
//the'sysdate'sprochasnoinputparameters,soanemptyMapissupplied...
returnexecute(newHashMap());
}
}
privatestaticvoidprintMap(Mapresults){
for(Iteratorit=results.entrySet().iterator();it.hasNext();){
System.out.println(it.next());
}
}
}
StoredProcedureOracle
importoracle.jdbc.driver.OracleTypes;
importorg.springframework.jdbc.core.SqlOutParameter;
importorg.springframework.jdbc.object.StoredProcedure;
importjavax.sql.DataSource;
importjava.util.HashMap;
importjava.util.Map;
publicclassTitlesAndGenresStoredProcedureextendsStoredProcedure{
privatestaticfinalStringSPROC_NAME="AllTitlesAndGenres";
publicTitlesAndGenresStoredProcedure(DataSourcedataSource){
super(dataSource,SPROC_NAME);
declareParameter(newSqlOutParameter("titles",OracleTypes.CURSOR,newTitleMapper()));
declareParameter(newSqlOutParameter("genres",OracleTypes.CURSOR,newGenreMapper()));
compile();
}
publicMapexecute(){
//again,thissprochasnoinputparameters,soanemptyMapissupplied...
returnsuper.execute(newHashMap());
}
}
TitlesAndGenresStoredProcedure declareParameter(..)SqlOutParameter
RowMapperTitleMapper ResultSetTitleDomainObject
importcom.foo.sprocs.domain.Title;
importorg.springframework.jdbc.core.RowMapper;
importjava.sql.ResultSet;
importjava.sql.SQLException;
publicfinalclassTitleMapperimplementsRowMapper{
publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{
Titletitle=newTitle();
title.setId(rs.getLong("id"));
title.setName(rs.getString("name"));
returntitle;
}
}
GenreMapper ResultSetGenreDomainObject
importorg.springframework.jdbc.core.RowMapper;
importjava.sql.ResultSet;
importjava.sql.SQLException;
importcom.foo.domain.Genre;
publicfinalclassGenreMapperimplementsRowMapper{
publicObjectmapRow(ResultSetrs,introwNum)throwsSQLException{
returnnewGenre(rs.getString("name"));
}
}
RDBMS
importoracle.jdbc.driver.OracleTypes;
importorg.springframework.jdbc.core.SqlOutParameter;
importorg.springframework.jdbc.object.StoredProcedure;
importjavax.sql.DataSource;
importjava.util.HashMap;
importjava.util.Map;
publicclassTitlesAfterDateStoredProcedureextendsStoredProcedure{
privatestaticfinalStringSPROC_NAME="TitlesAfterDate";
privatestaticfinalStringCUTOFF_DATE_PARAM="cutoffDate";
publicTitlesAfterDateStoredProcedure(DataSourcedataSource){
super(dataSource,SPROC_NAME);
declareParameter(newSqlParameter(CUTOFF_DATE_PARAM,Types.DATE);
declareParameter(newSqlOutParameter("titles",OracleTypes.CURSOR,newTitleMapper()));
compile();
}
publicMapexecute(DatecutoffDate){
Mapinputs=newHashMap();
inputs.put(CUTOFF_DATE_PARAM,cutoffDate);
returnsuper.execute(inputs);
}
}
11.6.5.SqlFunctionSqlFunctionRDBMSSQL“”wrapperqueryForXxx SqlFunction JdbcTemplate
SQL“selectuser()” “selectsysdatefromdual”StoredProcedureSqlCall
SqlFunction SQLrun
publicintcountRows(){
SqlFunctionsf=newSqlFunction(dataSource,"selectcount(*)frommytable");
sf.compile();
returnsf.run();
}
11.7.SpringJDBC
11.7.1.SQLSpringSQLSQLNULL:
JdbcTemplateupdatequeryint
SqlParameterValueSQL
SqlParameterSourceBeanPropertySqlParameterSource
MapSqlParameterSource SQL
11.7.2.BLOBCLOBBLOBCLOB
LobHandlerLOB LobHandlerLobCreator
LobCreator/LobHandlerLOB
BLOB
byte[]–getBlobAsBytesandsetBlobAsBytesbyte[]–getBlobAsBytessetBlobAsBytesInputStream – getBlobAsBinaryStream andsetBlobAsBinaryStreamInputStream–getBlobAsBinaryStreamsetBlobAsBinaryStream
CLOB
String–getClobAsStringandsetClobAsStringString–getClobAsStringsetClobAsStringInputStream – getClobAsAsciiStream andsetClobAsAsciiStreamInputStream–getClobAsAsciiStreamsetClobAsAsciiStreamReader – getClobAsCharacterStream andsetClobAsCharacterStreamReader – getClobAsCharacterStream
setClobAsCharacterStreamBLOBBLOBJdbcTemplateAbstractLobCreatingPreparedStatementCallback"setValues"LobCreatorLOB“lobHandler” DefaultLobHandler
finalFileblobIn=newFile("spring2004.jpg");
finalInputStreamblobIs=newFileInputStream(blobIn);
finalFileclobIn=newFile("large.txt");
finalInputStreamclobIs=newFileInputStream(clobIn);
finalInputStreamReaderclobReader=newInputStreamReader(clobIs);
jdbcTemplate.execute(
"INSERTINTOlob_table(id,a_clob,a_blob)VALUES(?,?,?)",
newAbstractLobCreatingPreparedStatementCallback(lobhandler){
protectedvoidsetValues(PreparedStatementps,LobCreatorlobCreator)
throwsSQLException{
ps.setLong(1,1L);
lobCreator.setClobAsCharacterStream(ps,2,clobReader,(int)clobIn.length());
lobCreator.setBlobAsBinaryStream(ps,3,blobIs,(int)blobIn.length());
}
}
);
blobIs.close();
clobReader.close();
lobHandlerDefaultLobHandler
setClobAsCharacterStreamCLOB
setBlobAsBinartStreamBLOB
LOBJdbcTempate DefaultLobHandler
Listl=jdbcTemplate.query("selectid,a_clob,a_blobfromlob_table",
newRowMapper(){
publicObjectmapRow(ResultSetrs,inti)throwsSQLException{
Mapresults=newHashMap();
StringclobText=lobHandler.getClobAsString(rs,"a_clob");
results.put("CLOB",clobText);
byte[]blobBytes=lobHandler.getBlobAsBytes(rs,"a_blob");
results.put("BLOB",blobBytes);
returnresults;
}
});
getClobAsStringCLOB
getBlobAsBytesBLOB
11.7.3.INSQL"select*fromT_ACTORwhereidin(1,2,3)" SQL java.util.ListlistSQL
INJDBC100INjava.util.ListIN"select*fromT_ACTORwhere(id,
last_name)in((1,'Johnson'),(2,'Harrop'))".
11.7.4.Spring SqlReturnType SqlTypeValue
OracleSTRUCT“ITEM_TYPE”SqlOutParameter
declareParameter(newSqlOutParameter("item",OracleTypes.STRUCT,"ITEM_TYPE",
newSqlReturnType(){
publicObjectgetTypeValue(CallableStatementcs,intcolIndx,intsqlType,StringtypeName)
throwsSQLException{
STRUCTstruct=(STRUCT)cs.getObject(colIndx);
Object[]attr=struct.getAttributes();
TestItemitem=newTestItem();
item.setId(((Number)attr[0]).longValue());
item.setDescription((String)attr[1]);
item.setExpirationDate((java.util.Date)attr[2]);
returnitem;
}
}));
Java SqlTypeValueTestItem SqlTypeValue" createTypeValue
StructDescriptorArrayDescriptor
SqlTypeValuevalue=newAbstractSqlTypeValue(){
protectedObjectcreateTypeValue(Connectionconn,intsqlType,StringtypeName)throwsSQLException{
StructDescriptoritemDescriptor=newStructDescriptor(typeName,conn);
Structitem=newSTRUCT(itemDescriptor,conn,
newObject[]{
testItem.getId(),
testItem.getDescription(),
newjava.sql.Date(testItem.getExpirationDate().getTime())
});
returnitem;
}
};
SqlTypeValueMap
12ORM
12.1.12.2.Hibernate
12.2.1.12.2.2.Spring SessionFactory
12.2.3.TheHibernateTemplate12.2.4.SpringDAO12.2.5.Hibernate3APIDAO12.2.6.12.2.7.12.2.8.12.2.9.vs12.2.10.Hibernate
12.3.JDO12.3.1.PersistenceManagerFactory12.3.2.JdoTemplateJdoDaoSupport12.3.3.JDOAPIDAO12.3.4.12.3.5.JdoDialect
12.4.OracleTopLink12.4.1.SessionFactory12.4.2.TopLinkTemplateandTopLinkDaoSupport12.4.3.TopLinkAPIDAO12.4.4.
12.5.iBATISSQLMaps12.5.1.SqlMapClient12.5.2. SqlMapClientTemplate SqlMapClientDaoSupport
12.5.3.iBATISAPIDAO12.6.JPA
12.6.1.SpringJPA12.6.2.JpaTemplate JpaDaoSupport
12.6.3.JPADAO12.6.4.
12.7.12.8.JpaDialect
12.1.Spring FrameworkDAO HibernateJDOOracle TopLinkiBATISSQLMappings JPAHibernateSpringIoCHibernateO/RSpringDAOSpringDAOHibernate/JDO/TopLinkAPIDAODAOIoCSpringO/RMappingSpringSpringO/RMappingSpringSpringO/RMappinglibraryJavaBeansSpringIoCSpringSpringFrameworkO/RMappingDAO
SpringIoC Hibernate SessionFactory JDBCDataSource
SpringO/RMappingcheckedruntimeDataAccessExceptioncatch/throwJDBCDBDialectJDBC
SpringapplicationcontextHibernate SessionFactoryJDBCDataSourceiBATISSQLMapsSpringHibernateHibernateHibernate SessionSpringtemplateJavaHibernateHibernateAPIDAOJTASpringHibernate
SpringO/RMappingAOPJavatemplaterollbackHibernate/JDOJTAServiceJDBCO/RBLOBO/RMappingORM
SpringPetClinicDAOapplicationcontextJDBCHibernateOracleTopLinkJPAPetClinicSpringwebHibernateTopLinkJPAJPetStoreiBATISSQLMapsSpringWebSpringWebMVCStrutsSpringSpringO/R Mapping JDOJPOX http://www.jpox.org/Kodo http://www.bea.com/kodo
12.2.HibernateHibernate3http://www.hibernate.org/HibernateSpringSpringO/RMappingDAOSpringO/RMappingO/RMappingSpring2.5Hibernate3.1Hibernate2.1Hibernate3.0
12.2.1.SpringIoCAOPuncheckedexceptionSpringDAOJDBCSQLException DataAccessExceptionSQLSpringJTAJDBCSpringHibernateJDO HibernateTemplate / JdoTemplateJdbcTemplateHibernateInterceptor/JdoInterceptorHibernate/JDOsingletonsSpringSpringXMLSpringJavaBeanapplicationContextSpringJavaBeanstemplatetemplatewebweb
12.2.2.Spring SessionFactory
SpringSpringbeanJDBC DataSourceHibernateSessionFactoryDAOJDBC DataSourceHibernate
<beans>
<beanid="myDataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<propertyname="driverClassName"value="org.hsqldb.jdbcDriver"/>
<propertyname="url"value="jdbc:hsqldb:hsql://localhost:9001"/>
<propertyname="username"value="sa"/>
<propertyname="password"value=""/>
</bean>
<beanid="mySessionFactory"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<propertyname="dataSource"ref="myDataSource"/>
<propertyname="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<propertyname="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.HSQLDialect
</value>
</property>
</bean>
</beans>
JakartaCommonsDBCP BasicDataSourceJNDIDataSource:
<beans>
<beanid="myDataSource"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="java:comp/env/jdbc/myds"/>
</bean>
</beans>
Spring JndiObjectFactoryBeanJNDIHibernate SessionFactoryEJB
12.2.3.TheHibernateTemplate HibernatesetSessionFactory(..)beansetter SpringDAODAO
<beans>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="sessionFactory"ref="mySessionFactory"/>
</bean>
</beans>
publicclassProductDaoImplimplementsProductDao{
privateHibernateTemplatehibernateTemplate;
publicvoidsetSessionFactory(SessionFactorysessionFactory){
this.hibernateTemplate=newHibernateTemplate(sessionFactory);
}
publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{
returnthis.hibernateTemplate.find("fromtest.Productproductwhereproduct.category=?",category);
}
}
HibernateTemplateHibernateSession SessionHibernateTemplate
publicclassProductDaoImplimplementsProductDao{
privateHibernateTemplatehibernateTemplate;
publicvoidsetSessionFactory(SessionFactorysessionFactory){
this.hibernateTemplate=newHibernateTemplate(sessionFactory);
}
publicCollectionloadProductsByCategory(finalStringcategory)throwsDataAccessException{
returnthis.hibernateTemplate.execute(newHibernateCallback(){
publicObjectdoInHibernate(Sessionsession){
Criteriacriteria=session.createCriteria(Product.class);
criteria.add(Expression.eq("category",category));
criteria.setMaxResults(6);
returncriteria.list();
}
};
}
}
Hibernate HibernateTemplateHibernate SessionfindloadsaveOrUpdatedeleteSpring HibernateDaoSupport setSessionFactory(..)
SessionFactory getSessionFactory() getHibernateTemplate() DAO:
publicclassProductDaoImplextendsHibernateDaoSupportimplementsProductDao{
publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{
returnthis.getHibernateTemplate().find(
"fromtest.Productproductwhereproduct.category=?",category);
}
}
12.2.4.SpringDAOSpring HibernateTemplateDAODataAccessException HibernateDaoSupport SessionSessionFactoryUtils ' false
Session
publicclassHibernateProductDaoextendsHibernateDaoSupportimplementsProductDao{
publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException,MyException{
Sessionsession=getSession(false);
try{
Queryquery=session.createQuery("fromtest.Productproductwhereproduct.category=?");
query.setString(0,category);
Listresult=query.list();
if(result==null){
thrownewMyException("Nosearchresults.");
}
returnresult;
}
catch(HibernateExceptionex){
throwconvertHibernateAccessException(ex);
}
}
}
Hibernate checkedexception HibernateTemplateuncheckedexception
12.2.5.Hibernate3APIDAOHibernate3“Session”Hibernate Session SpringHibernate SessionHibernateAPIDAO
publicclassProductDaoImplimplementsProductDao{
privateSessionFactorysessionFactory;
publicvoidsetSessionFactory(SessionFactorysessionFactory){
this.sessionFactory=sessionFactory;
}
publicCollectionloadProductsByCategory(Stringcategory){
returnthis.sessionFactory.getCurrentSession()
.createQuery("fromtest.Productproductwhereproduct.category=?")
.setParameter(0,category)
.list();
}
}
HibernateDAO SessionFactory DAOHibernateHibernateUtil DAOSpring HibernateTemplateSpringIoCUnitTest: setSessionFactory(..)Springbean
<beans>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="sessionFactory"ref="mySessionFactory"/>
</bean>
</beans>
DAOHibernateAPISpringDAO HibernateExceptionuncheckedexceptionHibernate DAOSpring LocalSessionFactoryBeanSpring HibernateSessionFactory.getCurrentSession()SpringHibernateTransactionManager Session JTASpring JtaTransactionManagerEJBCMTJTA SessionDAOHibernate3APISpring
12.2.6.setTransactionManager(..) bean setProductDao productDAO
Springapplicationcontext
<beans>
<beanid="myTxManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory"ref="mySessionFactory"/>
</bean>
<beanid="myProductService"class="product.ProductServiceImpl">
<propertyname="transactionManager"ref="myTxManager"/>
<propertyname="productDao"ref="myProductDao"/>
</bean>
</beans>
publicclassProductServiceImplimplementsProductService{
privateTransactionTemplatetransactionTemplate;
privateProductDaoproductDao;
publicvoidsetTransactionManager(PlatformTransactionManagertransactionManager){
this.transactionTemplate=newTransactionTemplate(transactionManager);
}
publicvoidsetProductDao(ProductDaoproductDao){
this.productDao=productDao;
}
publicvoidincreasePriceOfAllProductsInCategory(finalStringcategory){
this.transactionTemplate.execute(newTransactionCallbackWithoutResult(){
publicvoiddoInTransactionWithoutResult(TransactionStatusstatus){
ListproductsToChange=this.productDao.loadProductsByCategory(category);
//dothepriceincrease...
}
}
);
}
}
12.2.7.
SpringSpringAOPTransactionInterceptor
<beans>
<beanid="myTxManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory"ref="mySessionFactory"/>
</bean>
<beanid="myProductService"class="org.springframework.aop.framework.ProxyFactoryBean">
<propertyname="proxyInterfaces"value="product.ProductService"/>
<propertyname="target">
<beanclass="product.DefaultProductService">
<propertyname="productDao"ref="myProductDao"/>
</bean>
</property>
<propertyname="interceptorNames">
<list>
<value>myTxInterceptor</value><!--thetransactioninterceptor(configuredelsewhere)-->
</list>
</property>
</bean>
</beans>
publicclassProductServiceImplimplementsProductService{
privateProductDaoproductDao;
publicvoidsetProductDao(ProductDaoproductDao){
this.productDao=productDao;
}
//noticetheabsenceoftransactiondemarcationcodeinthismethod
//Spring'sdeclarativetransactioninfrastructurewillbedemarcatingtransactionsonyourbehalf
publicvoidincreasePriceOfAllProductsInCategory(finalStringcategory){
ListproductsToChange=this.productDao.loadProductsByCategory(category);
//...
}
}
Spring TransactionInterceptorcheckedexception
TransactionTemplateuncheckedexception TransactionTemplateuncheckedexception TransactionStatusrollback-onlyTransactionInterceptorrollback ProxyFactoryBean
9.5“”
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--SessionFactory,DataSource,etc.omitted-->
<beanid="myTxManager"class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<propertyname="sessionFactory"ref="mySessionFactory"/>
</bean>
<aop:config>
<aop:pointcutid="productServiceMethods"expression="execution(*product.ProductService.*(..))"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/>
</aop:config>
<tx:adviceid="txAdvice"transaction-manager="myTxManager">
<tx:attributes>
<tx:methodname="increasePrice*"propagation="REQUIRED"/>
<tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/>
<tx:methodname="*"propagation="SUPPORTS"read-only="true"/>
</tx:attributes>
</tx:advice>
<beanid="myProductService"class="product.SimpleProductService">
<propertyname="productDao"ref="myProductDao"/>
</bean>
</beans>
12.2.8.TransactionTemplate TransactionInterceptorPlatformTransactionManager HibernateHibernateTransactionManagerHibernate SessionFactoryThreadLocal Session JtaTransactionManagerJTAPlatformTransactionManagerHibernateJTAHibernateJTAAPIHibernate SessionFacotry JtaTransactionManagerLocalSessionFactoryBeanDAObean SessionFactoryJDBC JtaTransactionManagerDAOsessionfactories
<beans>
<beanid="myDataSource1"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiNamevalue="java:comp/env/jdbc/myds1"/>
</bean>
<beanid="myDataSource2"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="java:comp/env/jdbc/myds2"/>
</bean>
<beanid="mySessionFactory1"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<propertyname="dataSource"ref="myDataSource1"/>
<propertyname="mappingResources">
<list>
<value>product.hbm.xml</value>
</list>
</property>
<propertyname="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
hibernate.show_sql=true
</value>
</property>
</bean>
<beanid="mySessionFactory2"class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<propertyname="dataSource"ref="myDataSource2"/>
<propertyname="mappingResources">
<list>
<value>inventory.hbm.xml</value>
</list>
</property>
<propertyname="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.OracleDialect
</value>
</property>
</bean>
<beanid="myTxManager"class="org.springframework.transaction.jta.JtaTransactionManager"/>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="sessionFactory"ref="mySessionFactory1"/>
</bean>
<beanid="myInventoryDao"class="product.InventoryDaoImpl">
<propertyname="sessionFactory"ref="mySessionFactory2"/>
</bean>
<!--thisshowstheSpring1.xstyleofdeclarativetransactionconfiguration-->
<!--itistotallysupported,100%legalinSpring2.x,butseealsoaboveforthesleeker,Spring2.0style-->
<beanid="myProductService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<propertyname="transactionManager"ref="myTxManager"/>
<propertyname="target">
<beanclass="product.ProductServiceImpl">
<propertyname="productDao"ref="myProductDao"/>
<propertyname="inventoryDao"ref="myInventoryDao"/>
</bean>
</property>
<propertyname="transactionAttributes">
<props>
<propkey="increasePrice*">PROPAGATION_REQUIRED</prop>
<propkey="someOtherBusinessMethod">PROPAGATION_REQUIRES_NEW</prop>
<propkey="*">PROPAGATION_SUPPORTS,readOnly</prop>
</props>
</property>
</bean>
</beans>
HibernateTransactionManager JtaTransactionManagerJVMHibernateJCAEJB DataSourceHibernateTransactionManagerJDBCHibernateConnectionHibernate/JDBCJTAHibernateJDBC DataSourceSessionFactoryLocalSessionFactoryBean “dataSource”HibernateTransactionManager“dataSource” DataSource
12.2.9.vsSpringJNDI SessionFactory SessionFactorySessionFactoryJNDI SessionFactory HibernateJCASessionFactoryJ2EESpringJTAJTAJ2EEJTAJTAJNDI DataSource
HibernateJCAHibernate TransactionManagerLookupJVMSpring SessionFactoryJDBC DataSourceJCAJCA SpringWebWebLogicExpressJCAJ2EEWebJTAJCAEJBTomcatResinJettyEJB SessionFactory Spring HibernateTransactionManagerJtaTransactionManagerJVMJCAHibernateJNDIEJB
12.2.10.Hibernate XADataSourceJTAWebLogicWebSphereHibernateJTAPlatformTransactionManager
java.sql.SQLException:Thetransactionisnolongeractive-status:'Committed'.
NofurtherJDBCaccessisallowedwithinthistransaction.
HibernateJTA PlatformTransactionManagerSpring
application contextJTA PlatformTransactionManager
JndiObjectFactoryBeanJNDISpring JtaTransactionManagerbean LocalSessionFactoryBean jtaTransactionManagerSpringHibernateJTA PlatformTransactionManager SpringJtaTransactionManagerHibernateTransactionManagerLookup
HibernateJTA PlatformTransactionManagerHibernateJTAPlatformTransactionManagerJTA
JTA
Spring JtaTransactionManager JTAJTA afterCompletion
SpringHibernateHibernate afterTransactionCompletionHibernateHibernateSession close()
ConnectionConnection.close()
HibernateJTA PlatformTransactionManagerJTA
JTA
Spring JtaTransactionManagerJTAJTA beforeCompletion
SpringHibernateJTATransactionSpringJTA
HibernateJTAtransactionJTA afterCompletion
12.3.JDOSpringJDO1.0/2.0APISpringHibernateorg.springframework.orm.jdo
12.3.1. PersistenceManagerFactory
Spring LocalPersistenceManagerFactoryBeanSpringapplicationcontextJDO PersistenceManagerFactory
<beans>
<beanid="myPmf"class="org.springframework.orm.jdo.LocalPersistenceManagerFactoryBean">
<propertyname="configLocation"value="classpath:kodo.properties"/>
</bean>
</beans>
PersistenceManagerFactory PersistenceManagerFactory JDOPersistenceManagerFactoryJavaBeansJDBC DataSourceSpringbean SpringJDBC DataSourceconnectionFactorybeanJDOJPOX http://www.jpox.org
<beans>
<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<propertyname="driverClassName"value="${jdbc.driverClassName}"/>
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
</bean>
<beanid="myPmf"class="org.jpox.PersistenceManagerFactoryImpl"destroy-method="close">
<propertyname="connectionFactory"ref="dataSource"/>
<propertyname="nontransactionalRead"value="true"/>
</bean>
</beans>
JDO PersistenceManagerFactoryJ2EEJNDI
JndiObjectFactoryBean PersistenceManagerFactoryEJBJNDIPersistenceManagerFactory
12.3.2.JdoTemplateJdoDaoSupportJDODAOIoC PersistenceManagerFactoryDAOPersistenceManagerFactoryJDOAPI Spring
<beans>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="persistenceManagerFactory"ref="myPmf"/>
</bean>
</beans>
publicclassProductDaoImplimplementsProductDao{
privateJdoTemplatejdoTemplate;
publicvoidsetPersistenceManagerFactory(PersistenceManagerFactorypmf){
this.jdoTemplate=newJdoTemplate(pmf);
}
publicCollectionloadProductsByCategory(finalStringcategory)throwsDataAccessException{
return(Collection)this.jdoTemplate.execute(newJdoCallback(){
publicObjectdoInJdo(PersistenceManagerpm)throwsJDOException{
Queryquery=pm.newQuery(Product.class,"category=pCategory");
query.declareParameters("StringpCategory");
Listresult=query.execute(category);
//dosomefurtherstuffwiththeresultlist
returnresult;
}
});
}
}
JDO JdoTemplate PersistenceManager
findloadmakePersistent delete JdoTemplate JdoDaoSupport setPersistenceManagerFactory(..)PersistenceManagerFactory getPersistenceManagerFactory()
getJdoTemplate() DAO
publicclassProductDaoImplextendsJdoDaoSupportimplementsProductDao{
publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{
returngetJdoTemplate().find(
Product.class,"category=pCategory","Stringcategory",newObject[]{category});
}
}
Spring JdoTemplateDAOJDOAPISpringDAOPersistenceManagerHibernatecheckedexceptions PersistenceManager
12.3.3.JDOAPIDAOJDOAPIDAO PersistenceManagerFactorySpring DAO
publicclassProductDaoImplimplementsProductDao{
privatePersistenceManagerFactorypersistenceManagerFactory;
publicvoidsetPersistenceManagerFactory(PersistenceManagerFactorypmf){
this.persistenceManagerFactory=pmf;
}
publicCollectionloadProductsByCategory(Stringcategory){
PersistenceManagerpm=this.persistenceManagerFactory.getPersistenceManager();
try{
Queryquery=pm.newQuery(Product.class,"category=pCategory");
query.declareParameters("StringpCategory");
returnquery.execute(category);
}
finally{
pm.close();
}
}
}
DAOIoCSpring JdoTemplateSpring
<beans>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="persistenceManagerFactory"ref="myPmf"/>
</bean>
</beans>
DAO PersistenceManagerSpringPersistenceManagerFactory TransactionAwarePersistenceManagerFactoryProxySpring DAO
<beans>
<beanid="myPmfProxy"
class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
<propertyname="targetPersistenceManagerFactory"ref="myPmf"/>
</bean>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="persistenceManagerFactory"ref="myPmfProxy"/>
</bean>
</beans>
PersistenceManagerFactory.getPersistenceManager()
PersistenceManager PersistenceManager
PersistenceManagerclose()
publicclassProductDaoImplimplementsProductDao{
privatePersistenceManagerFactorypersistenceManagerFactory;
publicvoidsetPersistenceManagerFactory(PersistenceManagerFactorypmf){
this.persistenceManagerFactory=pmf;
}
publicCollectionloadProductsByCategory(Stringcategory){
PersistenceManagerpm=this.persistenceManagerFactory.getPersistenceManager();
Queryquery=pm.newQuery(Product.class,"category=pCategory");
query.declareParameters("StringpCategory");
returnquery.execute(category);
}
}
DAO TransactionAwarePersistenceManagerFactoryProxy
"allowCreate"
<beans>
<beanid="myPmfProxy"
class="org.springframework.orm.jdo.TransactionAwarePersistenceManagerFactoryProxy">
<propertyname="targetPersistenceManagerFactory"ref="myPmf"/>
<propertyname="allowCreate"value="false"/>
</bean>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="persistenceManagerFactory"ref="myPmfProxy"/>
</bean>
</beans>
DAOJDOAPISpring JDODAO JDOExceptionuncheckedexceptionDAODAO DAOJDOAPISpring JDOExceptionSpring DataAccessException
12.3.4.ServiceSpring
<?xmlversion="1.0"encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<beanid="myTxManager"class="org.springframework.orm.jdo.JdoTransactionManager">
<propertyname="persistenceManagerFactory"ref="myPmf"/>
</bean>
<beanid="myProductService"class="product.ProductServiceImpl">
<propertyname="productDao"ref="myProductDao"/>
</bean>
<tx:adviceid="txAdvice"transaction-manager="txManager">
<tx:attributes>
<tx:methodname="increasePrice*"propagation="REQUIRED"/>
<tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/>
<tx:methodname="*"propagation="SUPPORTS"read-only="true"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcutid="productServiceMethods"expression="execution(*product.ProductService.*(..))"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/>
</aop:config>
</beans>
JDO HibernateJDOnon-transactionalflushJTA JTASpringSpring JtaTransactionManagerEJBCMTJTAJdoTransactionManagerJDOJDBC DataSourceJDBCJdoDialectJDBCConnectionJDBCJDO2.0JDO1.0JdoDialect JdoDialect
12.3.5.JdoDialectJdoTemplate interfacename JdoDialect“jdoDialect”bean
DAO PersistenceManagerFactory JdoDaoSupport"jdoTemplate" JdoDialectSpring
JDBCConnectionJDBCDAO
Spring
PersistenceManagerJDBC
JDOExceptionsSpring DataAccessExceptionsJDO1.0API JDO2.0Spring1.2JDO2.0APISpringJDO JdoDialectJavadoc
12.4.OracleTopLinkSpringSpring 1.2Oracle TopLinkhttp://www.oracle.com/technology/products/ias/toplinkSpringHibernateSpringTopLink9.0.4Spring1.2TopLink10.1.3Spring1.2betaorg.springframework.orm.toplinkTopLinkSpringOracleTopLink TopLinkJimClark
12.4.1.SessionFactoryTopLinkSessionFactory ServerSession
ClientSession SpringTopLink
Spring LocalSessionFactoryBean beanTopLinkTopLinksessionSpringJDBC DataSource
<beans>
<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<propertyname="driverClassName"value="${jdbc.driverClassName}"/>
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
</bean>
<beanid="mySessionFactory"class="org.springframework.orm.toplink.LocalSessionFactoryBean">
<propertyname="configLocation"value="toplink-sessions.xml"/>
<propertyname="dataSource"ref="dataSource"/>
</bean>
</beans>
<toplink-configuration>
<session>
<name>Session</name>
<project-xml>toplink-mappings.xml</project-xml>
<session-type>
<server-session/>
</session-type>
<enable-logging>true</enable-logging>
<logging-options/>
</session>
</toplink-configuration>
LocalSessionFactoryBeanTopLink ServerSession
Session—— ClientSession SessionSpringTopLinkLocalSessionFactoryBeanTopLink DatabaseSession
12.4.2.TopLinkTemplateandTopLinkDaoSupportTopLinkDAOIoC SessionFactorySetterDAOTopLinkAPISessionFactory SessionSpring TopLinkTemplate
<beans>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="sessionFactory"ref="mySessionFactory"/>
</bean>
</beans>
publicclassTopLinkProductDaoimplementsProductDao{
privateTopLinkTemplatetlTemplate;
publicvoidsetSessionFactory(SessionFactorysessionFactory){
this.tlTemplate=newTopLinkTemplate(sessionFactory);
}
publicCollectionloadProductsByCategory(finalStringcategory)throwsDataAccessException{
return(Collection)this.tlTemplate.execute(newTopLinkCallback(){
publicObjectdoInTopLink(Sessionsession)throwsTopLinkException{
ReadAllQueryfindOwnersQuery=newReadAllQuery(Product.class);
findOwnersQuery.addArgument("Category");
ExpressionBuilderbuilder=this.findOwnersQuery.getExpressionBuilder();
findOwnersQuery.setSelectionCriteria(
builder.get("category").like(builder.getParameter("Category")));
Vectorargs=newVector();
args.add(category);
Listresult=session.executeQuery(findOwnersQuery,args);
//dosomefurtherstuffwiththeresultlist
returnresult;
}
});
}
}
TopLink TopLinkTemplateexecuteQueryreadAllreadById merge TopLinkTemplateJdoTemplate SpringsetSessionFactory(..) SessionFactory getSessionFactory()
getTopLinkTemplate()DAO
publicclassProductDaoImplextendsTopLinkDaoSupportimplementsProductDao{
publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{
ReadAllQueryfindOwnersQuery=newReadAllQuery(Product.class);
findOwnersQuery.addArgument("Category");
ExpressionBuilderbuilder=this.findOwnersQuery.getExpressionBuilder();
findOwnersQuery.setSelectionCriteria(
builder.get("category").like(builder.getParameter("Category")));
returngetTopLinkTemplate().executeQuery(findOwnersQuery,newObject[]{category});
}
}
TopLinkDAOSpring TopLinkTemplateDAO TopLinkAPISpringDAOSessionHibernate checkedexceptionsSession
12.4.3.TopLinkAPIDAOTopLinkAPIDAO SessionSpringSessionFactorySpring TransactionAwareSessionAdapter Session
TopLink Session getActiveSession()ServerSession getActiveUnitOfWork()
null
DAO:
publicclassProductDaoImplimplementsProductDao{
privateSessionsession;
publicvoidsetSession(Sessionsession){
this.session=session;
}
publicCollectionloadProductsByCategory(Stringcategory){
ReadAllQueryfindOwnersQuery=newReadAllQuery(Product.class);
findOwnersQuery.addArgument("Category");
ExpressionBuilderbuilder=this.findOwnersQuery.getExpressionBuilder();
findOwnersQuery.setSelectionCriteria(
builder.get("category").like(builder.getParameter("Category")));
Vectorargs=newVector();
args.add(category);
returnsession.getActiveSession().executeQuery(findOwnersQuery,args);
}
}
DAOIoCSpring TopLinkTemplateapplicationcontextSpringTransactionAwareSessionAdapter SessionbeanDAO
<beans>
<beanid="mySessionAdapter"
class="org.springframework.orm.toplink.support.TransactionAwareSessionAdapter">
<propertyname="sessionFactory"ref="mySessionFactory"/>
</bean>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="session"ref="mySessionAdapter"/>
</bean>
</beans>
DAOTopLinkAPISpring TopLink
DAO TopLinkExceptionuncheckedexceptionDAOTopLinkDAO DAOTopLink getActiveSession()JTATopLinkSpring TransactionAwareSessionAdapterTopLink ServerSession
TopLink Session.getActiveSession()
Session.getActiveUnitOfWork() SpringTopLinkTransactionManager Session JTASpring JtaTransactionManagerEJBCMTJTADAOTopLinkAPISpringTopLinkException TopLinkExceptionSpring
12.4.4.ServiceSpring
<?xmlversion="1.0"encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<beanid="myTxManager"class="org.springframework.orm.toplink.TopLinkTransactionManager">
<propertyname="sessionFactory"ref="mySessionFactory"/>
</bean>
<beanid="myProductService"class="product.ProductServiceImpl">
<propertyname="productDao"ref="myProductDao"/>
</bean>
<aop:config>
<aop:pointcutid="productServiceMethods"expression="execution(*product.ProductService.*(..))"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/>
</aop:config>
<tx:adviceid="txAdvice"transaction-manager="myTxManager">
<tx:attributes>
<tx:methodname="increasePrice*"propagation="REQUIRED"/>
<tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/>
<tx:methodname="*"propagation="SUPPORTS"read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
TopLink UnitOfWork TopLinkTopLinknon-transactionalflush TopLinkJTASession UnitOfWork Spring TopLinkTransactionManager
Spring JtaTransactionManagerEJBCMTJTATopLinkDAO Session.getActiveUnitOfWork()SpringJTA UnitOfWorkTopLinkTransactionManagerTopLink JDBC DataSource
TopLinkJDBCJDBC Connection
12.5.iBATISSQLMapsSpringiBatisJDBCHibernateJDBCHibernateIocSpringiBATISJDBCDataSourceTransactionManager JtaTransactionManager
SpringiBatis1.x2.x.iBatis2.xSpringSpringModulesproject
12.5.1.SqlMapClientiBATIS2.xAccountSQLmap
<sqlMapnamespace="Account">
<resultMapid="result"class="examples.Account">
<resultproperty="name"column="NAME"columnIndex="1"/>
<resultproperty="email"column="EMAIL"columnIndex="2"/>
</resultMap>
<selectid="getAccountByEmail"resultMap="result">
selectACCOUNT.NAME,ACCOUNT.EMAIL
fromACCOUNT
whereACCOUNT.EMAIL=#value#
</select>
<insertid="insertAccount">
insertintoACCOUNT(NAME,EMAIL)values(#name#,#email#)
</insert>
</sqlMap>
iBATIS2
<sqlMapConfig>
<sqlMapresource="example/Account.xml"/>
</sqlMapConfig>
iBATISCLASSPATH Account.xmlCLASSPATHSpringcontainer SqlMapClientFactoryBeaniBATISSQLMap2.xJDBCDataSource SqlMapClientFactoryBean
<beans>
<beanid="dataSource"class="org.apache.commons.dbcp.BasicDataSource"destroy-method="close">
<propertyname="driverClassName"value="${jdbc.driverClassName}"/>
<propertyname="url"value="${jdbc.url}"/>
<propertyname="username"value="${jdbc.username}"/>
<propertyname="password"value="${jdbc.password}"/>
</bean>
<beanid="sqlMapClient"class="org.springframework.orm.ibatis.SqlMapClientFactoryBean">
<propertyname="configLocation"value="WEB-INF/sqlmap-config.xml"/>
<propertyname="dataSource"ref="dataSource"/>
</bean>
</beans>
12.5.2. SqlMapClientTemplateSqlMapClientDaoSupport
SqlMapClientDaoSupport SqlMapDaoSupportDAO
publicclassSqlMapAccountDaoextendsSqlMapClientDaoSupportimplementsAccountDao{
publicAccountgetAccount(Stringemail)throwsDataAccessException{
return(Account)getSqlMapClientTemplate().queryForObject("getAccountByEmail",email);
}
publicvoidinsertAccount(Accountaccount)throwsDataAccessException{
getSqlMapClientTemplate().update("insertAccount",account);
}
}
applicationcontext SqlMapAccountDao SqlMapClientDAOSqlMapClientTemplate
<beans>
<beanid="accountDao"class="example.SqlMapAccountDao">
<propertyname="sqlMapClient"ref="sqlMapClient"/>
</bean>
</beans>
SqlMapTemplate SqlMapClient SqlMapClientDaoSupport
SqlMapClientTemplateSqlMapClientTemplate execute SqlMapClientCallback
publicclassSqlMapAccountDaoextendsSqlMapClientDaoSupportimplementsAccountDao{
publicvoidinsertAccount(Accountaccount)throwsDataAccessException{
getSqlMapClientTemplate().execute(newSqlMapClientCallback(){
publicObjectdoInSqlMapClient(SqlMapExecutorexecutor)throwsSQLException{
executor.startBatch();
executor.update("insertAccount",account);
executor.update("insertAddress",account.getAddress());
executor.executeBatch();
}
});
}
}
SqlMapExecutorAPI DataAccessException
12.5.3.iBATISAPIDAOiBATISAPISpring SqlMapClient
publicclassSqlMapAccountDaoimplementsAccountDao{
privateSqlMapClientsqlMapClient;
publicvoidsetSqlMapClient(SqlMapClientsqlMapClient){
this.sqlMapClient=sqlMapClient;
}
publicAccountgetAccount(Stringemail){
try{
return(Account)this.sqlMapClient.queryForObject("getAccountByEmail",email);
}
catch(SQLExceptionex){
thrownewMyDaoException(ex);
}
}
publicvoidinsertAccount(Accountaccount)throwsDataAccessException{
try{
this.sqlMapClient.update("insertAccount",account);
}
catch(SQLExceptionex){
thrownewMyDaoException(ex);
}
}
}
iBATISAPI SQLException DAOapplicationcontextiBATISDAOIoC
<beans>
<beanid="accountDao"class="example.SqlMapAccountDao">
<propertyname="sqlMapClient"ref="sqlMapClient"/>
</bean>
</beans>
12.6.JPAorg.springframework.orm.jpaSpringJPAHibernateJDOPersistenceAPI
12.6.1.SpringJPASpringJPAJPAEntityManagerFactory
12.6.1.1.LocalEntityManagerFactoryBeanLocalEntityManagerFactoryBeanJPA EntityManager
PersistenceProviderJPA JavaSEpersistenceunit
<beans>
<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalEntityManagerFactoryBean">
<propertyname="persistenceUnitName"value="myPersistenceUnit"/>
</bean>
</beans>
JPAJDBC DataSourceJVM
12.6.1.2.JNDI EntityManagerFactory
JNDI EntityManagerFactoryJavaEE5XML
<beans>
<jee:jndi-lookupid="entityManagerFactory"jndi-name="persistence/myPersistenceUnit"/>
</beans>
JavaEE5JavaEE META-INF/persistence.xmlJavaEEpersistence-unit-ref web.xml
JavaEEJNDIEntityManagerJTASpringJtaTransactionManager
JPAJVM(Hibernate)(ant)
JNDIbeanJavaEE5JPAJPA
12.6.1.3.LocalContainerEntityManagerFactoryBeanLocalContainerEntityManagerFactoryBeanJPAEntityManagerFactory
LocalContainerEntityManagerFactoryBeanPersistenceUnitInfo dataSourceLookup loadTimeWeaverJNDI
<beans>
<beanid="entityManagerFactory"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<propertyname="dataSource"ref="someDataSource"/>
<propertyname="loadTimeWeaver">
<beanclass="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
</beans>
JPAJDBC DataSource ClassLoaderJavaEE5JPAJavaEE5LocalContainerEntityManagerFactoryBean“persistenceXmlLocation” “META-INF/my-persistence.xml”JavaEE5INF/persistence.xmlSpring JPARdsin3.1SpringJPAwebTomcatLoadTimeWeaver SpringJPAClassTransformer web/ Java5 ClassTransformers—— ——Spring LoadTimeWeaver ClassTransformerclassloaderTomcatSpringVMJPAWebLogicOC4JGlassFishResin
12.6.1.3.1.Tomcat5.0
ApacheTomcatClassLoader SpringTomcatInstrumentableClassLoader
org.springframework.instrument.classloading.tomcatTomcatWebappClassLoaderJPAClassTransformer“” JPAJPAtransformer TomcatInstrumentableClassLoaderweb
spring-tomcat-weaver.jar $CATALINA_HOME/server/lib$CATALINA_HOMETomcat
webapplicationcontextTomcat
<Contextpath="/myWebApp"docBase="/my/webApp/location">
<LoaderloaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>
Tomcat5.0.x5.5.xcontextlocations($CATALINA_HOME/conf/server.xml)$CATALINA_HOME/conf/context.xmlweb Serverweb$CATALINA_HOME/conf/[enginename]/[hostname]/my-webapp-context.xmlweb your-webapp.war/META-INF/context.xmlweb-appJPA5.5.20XMLbug server.xml Loaderclassloaderclassloader
Tomcat 5.5.20 useSystemClassLoaderAsParentfalse
<Contextpath="/myWebApp"docBase="/my/webApp/location">
<LoaderloaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"
useSystemClassLoaderAsParent="false"/>
</Context>
spring-tomcat-weaver.jar$CATALINA_HOME/lib (where$CATALINA_HOMETomcatwebTomcatClassLoaderClassLoader
<Contextpath="/myWebApp"docBase="/my/webApp/location">
<LoaderloaderClass="org.springframework.instrument.classloading.tomcat.TomcatInstrumentableClassLoader"/>
</Context>
Tomcat6.0.x(5.0.x/5.5.x)contextlocations($CATALINA_HOME/conf/server.xml)$CATALINA_HOME/conf/context.xmlweb Serverweb$CATALINA_HOME/conf/[enginename]/[hostname]/my-webapp-context.xmlweb your-webapp.war/META-INF/context.xmlweb-appJPATomcat5.0.x/5.5.x
Tomcat6.0.xTomcat LocalContainerEntityManagerFactoryBean LoadTimeWeaver
<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<propertyname="loadTimeWeaver">
<beanclass="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
</property>
</bean>
JPATomcatJPA
TomcatTopLinkJPAtoplinkjar $CATALINA_HOME/shared/libwar
12.6.1.3.2.VM
LoadTimeWeaverJDKSpringagent.jarInstrumentationLoadTimeWeaver
<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<propertyname="loadTimeWeaver">
<beanclass="org.springframework.instrument.classloading.InstrumentationLoadTimeWeaver"/>
</property>
</bean>
SpringJVM
-javaagent:/path/to/spring-agent.jar
12.6.1.3.3.
Spring2.5 context:load-time-weaver LoadTimeWeaver“”JPALocalContainerEntityManagerFactoryBeans
ebLogic,OC4J,GlassFish,Tomcat,Resin,VMagentbean
<context:load-time-weaver/>
<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
...
</bean>
6.8.4.5“Spring” TomcatVMWebLogic,OC4J,GlassFishResin
12.6.1.4.(classpathjar) SpringMETA-INF/persistence.xml)
<beanid="pum"class="org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager">
<propertyname="persistenceXmlLocation">
<list>
<value>org/springframework/orm/jpa/domain/persistence-multi.xml</value>
<value>classpath:/my/package/**/custom-persistence.xml</value>
<value>classpath*:META-INF/persistence.xml</value>
</list>
</property>
<propertyname="dataSources">
<map>
<entrykey="localDataSource"value-ref="local-db"/>
<entrykey="remoteDataSource"value-ref="remote-db"/>
</map>
</property>
<!--ifnodatasourceisspecified,usethisone-->
<propertyname="defaultDataSource"ref="remoteDataSource"/>
</bean>
<beanid="emf"class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<propertyname="persistenceUnitManager"ref="pum"/>
</bean>
JPAprovider PersistenceUnitPostProcessor
persistenceUnitManager LocalContainerEntityManagerFactoryBean
12.6.2.JpaTemplate JpaDaoSupport
JPADAO EntityManagerFactory DAO EntityManagerFactory
JPAAPI Spring JpaTemplate
<beans>
<beanid="myProductDao"class="product.ProductDaoImpl">
<propertyname="entityManagerFactory"ref="entityManagerFactory"/>
</bean>
</beans>
publicclassJpaProductDaoimplementsProductDao{
privateJpaTemplatejpaTemplate;
publicvoidsetEntityManagerFactory(EntityManagerFactoryemf){
this.jpaTemplate=newJpaTemplate(emf);
}
publicCollectionloadProductsByCategory(finalStringcategory)throwsDataAccessException{
return(Collection)this.jpaTemplate.execute(newJpaCallback(){
publicObjectdoInJpa(EntityManagerem)throwsPersistenceException{
Queryquery=em.createQuery("fromProductaspwherep.category=:category");
query.setParameter("category",category);
Listresult=query.getResultList();
//dosomefurtherprocessingwiththeresultlist
returnresult;
}
});
}
}
JpaCallbackJPA JpaTemplate EntityManagerJpaTemplateTemplate JpaTemplatefind
loadmergeSpring JpaDaoSupport get/setEntityManagerFactorygetJpaTemplate()
publicclassProductDaoImplextendsJpaDaoSupportimplementsProductDao{
publicCollectionloadProductsByCategory(Stringcategory)throwsDataAccessException{
Map<String,String>params=newHashMap<String,String>();
params.put("category",category);
returngetJpaTemplate().findByNamedParams("fromProductaspwherep.category=:category",params);
}
}
Spring JpaTemplateJPAAPISpringDAOcheckedexceptions JpaDaoSupport JpaTemplateJdoTemplateHibernateTemplateJPA@PersistenceContext “EntityManager”SpringPersistenceAnnotationBeanPostProcessor
12.6.3.JPADAO
EntityManagerFactory EntityManagerJPAJNDI JPAJPA EntityManager
EntityManager
JPAAPISpringPersistenceAnnotationBeanPostProcessor Spring @PersistenceUnit
@PersistenceContextDAO
publicclassProductDaoImplimplementsProductDao{
privateEntityManagerFactoryemf;
@PersistenceUnit
publicvoidsetEntityManagerFactory(EntityManagerFactoryemf){
this.emf=emf;
}
publicCollectionloadProductsByCategory(Stringcategory){
EntityManagerem=this.emf.createEntityManager();
try{
Queryquery=em.createQuery("fromProductaspwherep.category=?1");
query.setParameter(1,category);
returnquery.getResultList();
}
finally{
if(em!=null){
em.close();
}
}
}
}
DAOSpringSpring JpaTemplate SpringapplicationcontextDAO EntityManagerFactory
<beans>
<!--beanpost-processorforJPAannotations-->
<beanclass="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<beanid="myProductDao"class="product.ProductDaoImpl"/>
</beans>
PersistenceAnnotationBeanPostProcessor Spring2.5context:annotation-configXML SpringCommonAnnotationBeanPostProcessor
<beans>
<!--post-processorsforallstandardconfigannotations-->
<context:annotation-config/>
(@PersistenceUnit@PersistenceContext)/”protected,private)
JEE5
<beanid="myProductDao"class="product.ProductDaoImpl"/>
</beans>
DAO EntityManager EntityManagerfactory
publicclassProductDaoImplimplementsProductDao{
@PersistenceContext
privateEntityManagerem;
publicCollectionloadProductsByCategory(Stringcategory){
Queryquery=em.createQuery("fromProductaspwherep.category=:category");
query.setParameter("category",category);
returnquery.getResultList();
}
}
@PersistenceContexttype PersistenceContextType.TRANSACTION
EntityManager” PersistenceContextType.EXTENDED“EntityManager”, SpringsingletonbeanEntityManager EntityManagerSpring EntityManagerEntityManagerFactory applicationcontextXMLDAOJPASpringJPASpringJPA
12.6.4.DAO PersistenceExceptionunchecked exception IllegalArgumentExceptionIllegalStateException DAOJPADAOJPA Spring
@Repository
publicclassProductDaoImplimplementsProductDao{
//classbodyhere...
}
<beans>
<!--Exceptiontranslationbeanpostprocessor-->
<beanclass="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>
<beanid="myProductDao"class="product.ProductDaoImpl"/>
</beans>
PersistenceExceptionTranslator @RepositorybeanDAOJavaAPISpringIoC
12.7.ServiceSpring
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<beanid="myTxManager"class="org.springframework.orm.jpa.JpaTransactionManager">
<propertyname="entityManagerFactory"ref="myEmf"/>
</bean>
<beanid="myProductService"class="product.ProductServiceImpl">
<propertyname="productDao"ref="myProductDao"/>
</bean>
<aop:config>
<aop:pointcutid="productServiceMethods"expression="execution(*product.ProductService.*(..))"/>
<aop:advisoradvice-ref="txAdvice"pointcut-ref="productServiceMethods"/>
</aop:config>
<tx:adviceid="txAdvice"transaction-manager="myTxManager">
<tx:attributes>
<tx:methodname="increasePrice*"propagation="REQUIRED"/>
<tx:methodname="someOtherBusinessMethod"propagation="REQUIRES_NEW"/>
<tx:methodname="*"propagation="SUPPORTS"read-only="true"/>
</tx:attributes>
</tx:advice>
</beans>
SpringJPAJpaTransactionManagerJPAJDBCDataSourceJDBCJpaDialectJDBCConnectionSpringToplinkHibernateJPADialectJpaDialect
12.8.JpaDialectJpaTemplateJpaTransactionManager
AbstractEntityManagerFactoryBean JpaDialect"jpaDialect"beanDAO EntityManagerFactory JpaDaoSupport"jpaTemplate" JpaDialectSpring
ConnectionJDBCDAO
PersistenceExceptionsSpring DataAccessExceptionsDefaultJpaDialectDialect
SpringJPA JpaDialectJavadoc
III.TheWebSprintFrameworkwebSpringFrameworkweb SpringWebMVCSpringFrameworkweb JSF
SpringMVC Portlet13 WebMVCframeworkWeb
14
15 Web
16 PortletMVC
13.WebMVCframeworkWeb13.1.
13.1.1.MVC13.1.2.SpringWebMVC
13.2.DispatcherServlet13.3.
13.3.1.AbstractController WebContentGenerator
13.3.2.13.3.3.MultiActionController13.3.4.
13.4.handlermapping13.4.1.BeanNameUrlHandlerMapping13.4.2.SimpleUrlHandlerMapping13.4.3.HandlerInterceptor
13.5.13.5.1.ViewResolver13.5.2.13.5.3.Rediret
13.6.13.6.1.AcceptHeaderLocaleResolver13.6.2.CookieLocaleResolver13.6.3.SessionLocaleResolver13.6.4.LocaleChangeInterceptor
13.7.13.7.1.13.7.2.13.7.3.
13.8.Springmultipartfileupload13.8.1.13.8.2.MultipartResolver13.8.3.
13.9.Spring13.9.1.13.9.2.form13.9.3.input13.9.4.checkbox13.9.5.checkboxes13.9.6.radiobutton13.9.7.radiobuttons13.9.8.password13.9.9.select
13.9.10.option13.9.11.options13.9.12.textarea13.9.13.hidden13.9.14.errors
13.10.13.11.conventionoverconfiguration
13.11.1. ControllerClassNameHandlerMapping
13.11.2. ModelMapModelAndView
13.11.3. RequestToViewNameTranslator
13.12.13.12.1.dispatcher13.12.2.@Controller13.12.3.@RequestMapping13.12.4.@RequestParam13.12.5.@ModelAttribute13.12.6.@SessionAttributes13.12.7.WebDataBinder
13.13.
14.14.1.14.2.JSPJSTL
14.2.1.14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTL14.2.3.
14.3.Tiles14.3.1.14.3.2.Tiles
14.4.VelocityFreeMarker14.4.1.14.4.2.Context14.4.3.14.4.4.14.4.5.
14.5.XSLT14.5.1.14.5.2.
14.6.PDF/Excel14.6.1.14.6.2.
14.7.JasperReports14.7.1.14.7.2.14.7.3. ModelAndView
14.7.4.14.7.5.Exporter
15.Web15.1.15.2.15.3.JavaServerFaces
15.3.1.DelegatingVariableResolver15.3.2.FacesContextUtils
15.4.Struts15.4.1.ContextLoaderPlugin15.4.2.ActionSupportClasses
15.5.Tapestry15.5.1.Springbeans
15.6.WebWork15.7.
16.PortletMVC16.1.
16.1.1.-MVCC16.1.2.-MVCV16.1.3.WebBean
16.2.DispatcherPortlet16.3.ViewRendererServlet16.4.
16.4.1.AbstractController PortletContentGenerator
16.4.2.16.4.3.Command16.4.4.PortletWrappingController
16.5.16.5.1.PortletModeHandlerMapping16.5.2.ParameterHandlerMapping16.5.3.PortletModeParameterHandlerMapping16.5.4. HandlerInterceptors16.5.5.HandlerInterceptorAdapter16.5.6.ParameterMappingInterceptor
16.6.16.7.Multipart
16.7.1. PortletMultipartResolver
16.7.2.16.8.16.9.Portlet
13WebMVCframeworkWeb
13.1.13.1.1.MVC13.1.2.SpringWebMVC
13.2.DispatcherServlet13.3.
13.3.1.AbstractController WebContentGenerator
13.3.2.13.3.3.MultiActionController13.3.4.
13.4.handlermapping13.4.1.BeanNameUrlHandlerMapping13.4.2.SimpleUrlHandlerMapping13.4.3.HandlerInterceptor
13.5.13.5.1.ViewResolver13.5.2.13.5.3.Rediret
13.6.13.6.1.AcceptHeaderLocaleResolver13.6.2.CookieLocaleResolver13.6.3.SessionLocaleResolver13.6.4.LocaleChangeInterceptor
13.7.13.7.1.13.7.2.13.7.3.
13.8.Springmultipartfileupload13.8.1.13.8.2.MultipartResolver13.8.3.
13.9.Spring13.9.1.13.9.2.form13.9.3.input13.9.4.checkbox13.9.5.checkboxes13.9.6.radiobutton13.9.7.radiobuttons
13.9.8.password13.9.9.select13.9.10.option13.9.11.options13.9.12.textarea13.9.13.hidden13.9.14.errors
13.10.13.11.conventionoverconfiguration
13.11.1. ControllerClassNameHandlerMapping
13.11.2. ModelMapModelAndView
13.11.3. RequestToViewNameTranslator
13.12.13.12.1.dispatcher13.12.2.@Controller13.12.3.@RequestMapping13.12.4.@RequestParam13.12.5.@ModelAttribute13.12.6.@SessionAttributes13.12.7.WebDataBinder
13.13.
“”SpringwebSpring“ OCP ”SpringWebMVCoverride) bydesign
SethLaddExpertSpringWebMVCandWebFlow117“ALookAtDesign”
Bob Martin, The Open-ClosedPrinciple(PDF)
SpringMVCfinaladviceAbstractController.handleRequest()
AOP finalAOP”
13.1.SpringwebDispatcherServlet DispatcherServlethandlerviewlocal themeSpringWeb
ModelAndViewhandleRequest(request,response)
Spring AbstractControllerAbstractCommandControllerSimpleFormControllerFormController
Spring2.5Java5controller13.12“”
SpringWebMVC- ActionActionForm
WebWorkSpring Controller
CommandObjectFormObjectModel WebWork WebWork Action
ViewWebWork Action
ActionbeanSpringresponse ModelAndViewnullModelAndView MapmodelmodelbeankeybeanformJavaBean valuebeanViewResolver MapmodelMVCM SpringJSPVelocityMapmodelJSPrequestattributeVelocitytemplatemodel
13.1.1.MVCweb
SpringwebMVCSpring webSpringSpringrootapplicationcontext StrutsWebWorkAction ServletContext
Spring“plugins” webrootapplicationcontextSpring
SpringWebFlowSpringWebFlowSWFWeb
SWFservletportletSpringMVCStrutsJSF SWFSWFSWF SpringWebFlow
librarySpringwebMVCSpringbean SpringStrutsWebWorkwebMVC beanSpring
13.1.2.SpringWebMVCSpringweb:
controllervalidatorcommand objectformobjectmodelobject ServletDispatcherServlet handlermappingviewresolver
JavaBeancontextwebvalidator simplecommandformwizardmulti-action Action/ActionForm
bindingvalidation
handlermappingviewresolutionSpringURL webMVCSpringmodelSpringweb Map/
themeJSPSpringJSTLVelocity
JSPSpringTagLibrarytheme
JSPSpring2.0JSP
SpringBeanHTTPRequestHTTPSessionSpringMVCSpingMVCWebApplicationContext 3.4.4“”
13.2.DispatcherServletwebMVCSpringwebMVCwebservletDispatcherServletSpringIoCSpringSpringWebMVCDispatcherServlet DispatcherServlet
Controller”web
SpringWebMVC
DispatcherServletServlet HttpServletServletDispatcherServletwebweb.xml DispatcherServlet web.xml
DispatcherServlet
<web-app>
<servlet>
<servlet-name>example</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>example</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
</web-app>
.formexampleDispatcherServletSpringWebMVCDispatcherServletSpringWebMVCbean3.8“The ApplicationContext”Spring ApplicationContextscopewebMVC DispatcherServletWebApplicationContextcontextWebApplicationContextbeanbeanserlvetoverridebean
SpringWebMVCContext
DispatcherServletweb WEB-INF[servlet-name]-servlet.xml
beanglobalcopebeanweb.xmlDispatcherServlet
<web-app>
...
<servlet>
<servlet-name>golfing</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>golfing</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
</web-app>
servlet /WEB-INF/golfing-servlet.xmlgolfing-servlet.xmlWebMVC beanweb.xmlservletWebApplicationContextweb ApplicationContext
theme 13.7 “” servletServletContext WebApplicationContextServletContext
RequestContextUtilsWebApplicationContext
SpringDispatcherServletbean beanSpringWebApplicationContextbeanbean DispatcherServletbeanSpring
13.1.WebApplicationContextbean
BeanControllers MVCC
Handlermapping pre-processor post-processorURL
Viewresolvers
Localeresolver
Themeresolver web
MultipartFileresolver HTML
(Handlerexceptionresolver(s))
DispatcherServlet DispatcherServlet
WebApplicationContextDispatcherServlet.WEB_APPLICATION_CONTEXT_ATTRIBUTE
localResolver
SpringMultipartResolver”
WebApplicationContext WebApplicationContext
SpringDispatcherServletServletAPIlast-modification-dateDispatcherServlethandlermapping
getLastModified(request)
SpringDispatcherServletweb.xmlcontext servlet
13.2.DispatcherServlet
contextClassWebApplicationContextservlet
XmlWebApplicationContext
contextConfigLocation contextClass
namespaceWebApplicationContext [server-name]-
servlet
13.3.MVCMVC C Springorg.springframework.mvc.Controller
publicinterfaceController{
/**
*ProcesstherequestandreturnaModelAndViewobjectwhichtheDispatcherServlet
*willrender.
*/
ModelAndViewhandleRequest(
HttpServletRequestrequest,
HttpServletResponseresponse)throwsException;
}
ControllerSpringMVCControllerSpringController
13.3.1.AbstractController WebContentGenerator
Spring AbstractControllerAbstractControllermimetype
13.3.AbstractController
supportedMethods GETPOST
requiresSession HTTPsessionsession
synchronizeOnSession controllerHTTPsession
cacheSeconds controller -1
useExpiresHeader ControllerHTTP1.0 Expiresheader true
useCacheHeader ControllerHTTP1.1 Cache-Controlheader true
AbstractController handleRequestInternal(HttpServletRequest,
HttpServletResponse) ModelAndView AbstractController
applicationContext.xml
packagesamples;
publicclassSampleControllerextendsAbstractController{
publicModelAndViewhandleRequestInternal(
HttpServletRequestrequest,
HttpServletResponseresponse)throwsException{
ModelAndViewmav=newModelAndView("hello");
mav.addObject("message","HelloWorld!");
returnmav;
}
}
<beanid="sampleController"class="samples.SampleController">
<propertyname="cacheSeconds"value="120"/>
</bean>
handlermapping 13.4“handlermapping” context controller2
13.3.2.AbstractControllerSpringMVCapplicationcontext JavaUrlFilenameViewControllerURLhttp://www.springframework.org/index.htmlindex
13.3.3.MultiActionControllerSpringMultiActionController StrutsStruts DispatchAction
MultiActionController org.springframework.web.mvc.multiactionMultiActionController
MultiActionController MultiActionController MethodNameResolver
delegate MethodNameResolver
setDelegate
MultiActionController MethodNameResolver
MultiActionController' methodNameResolver' MethodNameResolver
MultiActionController
//'anyMeaningfulName'
public[ModelAndView|Map|void]anyMeaningfulName(HttpServletRequest,HttpServletResponse[,HttpSession][,AnyObject])
MultiActionControllerJavadoc MultiActionControllerJavadocController
publicModelAndViewdisplayCatalog(HttpServletRequest,HttpServletResponse)
Login
publicModelAndViewlogin(HttpServletRequest,HttpServletResponse,Login)
session
publicModelAndViewviewCart(HttpServletRequest,HttpServletResponse,HttpSession)
Product sessionsessionfinalsession
publicModelAndViewupdateCart(HttpServletRequest,HttpServletResponse,HttpSession,Product)
voidresponse
publicvoidhome(HttpServletRequest,HttpServletResponse)
Mapmodel 13.11“conventionoverconfiguration”
publicMaplist(HttpServletRequest,HttpServletResponse)
MethodNameResolverSpring MethodNameResolverSpringInternalPathMethodNameResolver
InternalPathMethodNameResolver-http://www.sf.net/testing.view
testing(HttpServletRequest,HttpServletResponse)
ParameterMethodNameResolver-http://www.sf.net/index.view?method=testIt
testIt(HttpServletRequest,HttpServletResponse)) paramName
PropertiesMethodNameResolver-PropertiesURL/index/welcome.html=doIt /index/welcome.htmldoIt(HttpServletRequest, HttpServletResponse)
PropertiesMethodNameResolver Spring PathMatcherURL/**/welcom?.html
Exceptions HttpServletRequest
ExceptionSpring
publicModelAndViewprocessException(HttpServletRequest,HttpServletResponse,IllegalArgumentException)
MultiActionControllerParameterMethodNameResolver
<beanid="paramMultiController"
class="org.springframework.web.servlet.mvc.multiaction.MultiActionController">
<propertyname="methodNameResolver">
<beanclass="org.springframework.web.servlet.mvc.multiaction.ParameterMethodNameResolver">
<propertyname="paramName"value="method"/>
</bean>
</property>
<propertyname="delegate">
<beanclass="samples.SampleDelegate"/>
</property>
</bean>
}
publicclassSampleDelegate{
publicModelAndViewretrieveIndex(HttpServletRequestreq,HttpServletResponseresp){
returnnewModelAndView("index","date",newLong(System.currentTimeMillis()));
}
}
PropertiesMethodNameResolverURL
<beanid="propsResolver"
class="org....mvc.multiaction.PropertiesMethodNameResolver">
<propertyname="mappings">
<value>
/index/welcome.html=retrieveIndex
/**/notwelcome.html=retrieveIndex
/*/user?.html=retrieveIndex
</value>
</property>
</bean>
<beanid="paramMultiController"class="org....mvc.multiaction.MultiActionController">
<propertyname="methodNameResolver"ref="propsResolver"/>
<propertyname="delegate">
<beanclass="samples.SampleDelegate"/>
</property>
</bean>
13.3.4.SpringcommandcontrollersSpringMVCStruts ActionFormSpring
AbstractCommandController
AbstractFormController AbstractFormController
SimpleFormControllerformcontrollerform
AbstractWizardFormController validatePage()processFinish()processCancel()contractor setPages()setCommandName()setPages()StringsetCommandName()StringAbstractFormController,JavaBeanbeansetCommandClass() formBackingObject()
AbstractWizardFormControlleroverride
Map getTargetPage() onBindAndValidate()
setAllowDirtyBack()setAllowDirtyForward() getTargetPage()
AbstractWizardFormControllerJavaDoc SpringjPetStoreorg.springframework.samples.jpetstore.web.spring.OrderFormController
13.4.handlermappingwebhandler SpringBeanNameUrlHandlerMapping HandlerMapping
HandlerMappingHandlerExecutionChain HandlerExecutionChain DispatcherServlet HandlerExecutionChain
DispatcherServletinterceptorSpring AbstractHandlerMapping
interceptors HandlerInterceptor 13.4.3 “
HandlerInterceptor”
defaultHandler
orderorder( org.springframework.core.Ordered)Spring
alwaysUseFullPathtrueSpringservletcontextservletcontext servletservlet-mappingalwaysUseFullPathtrue URL /testing/viewPage.html
/viewPage.html
urlDecodetrue2.5 false
lazyInitHandlerssingletonprototype)
org.springframework.web.servlet.handler.AbstractUrlHandlerMapping
13.4.1.BeanNameUrlHandlerMappingBeanNameUrlHandlerMappingHTTPbeanbeanwebFormControllerCommandControllerFormController 13.3.4“”Velocity BeanNameUrlHandlerMapping
http://samples.com/editaccount.formFormController
<beans>
<beanid="handlerMapping"class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping"/>
<beanname="/editaccount.form"class="org.springframework.web.servlet.mvc.SimpleFormController">
<propertyname="formView"value="account"/>
<propertyname="successView"value="account-created"/>
<propertyname="commandName"value="account"/>
<propertyname="commandClass"value="samples.Account"/>
</bean>
<beans>
/editaccount.form FormController web.xmlservlet-mapping
<web-app>
...
<servlet>
<servlet-name>sample</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--mapsthesampledispatcherto*.form-->
<servlet-mapping>
<servlet-name>sample</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
...
</web-app>
BeanNameUrlHandlerMappingwebDispatcherServletBeanNameUrlHandlerMapping
13.4.2.SimpleUrlHandlerMappingSimpleUrlHandlerMappingAntorg.springframework.util.PathMatcherJavaDoc
<web-app>
...
<servlet>
<servlet-name>sample</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<!--mapsthesampledispatcherto*.form-->
<servlet-mapping>
<servlet-name>sample</servlet-name>
<url-pattern>*.form</url-pattern>
</servlet-mapping>
<!--mapsthesampledispatcherto*.html-->
<servlet-mapping>
<servlet-name>sample</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
...
</web-app>
web.xml.html.formsampleDispatcherServlet
<beans>
<!--no'id'required,HandlerMappingbeansareautomaticallydetectedbythe
<beanclass="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<propertyname="mappings">
<value>
/*/account.form=editAccountFormController
/*/editaccount.form=editAccountFormController
/ex/view*.html=helpController
/**/help.html=helpController
</value>
</property>
</bean>
<beanid="helpController"
class="org.springframework.web.servlet.mvc.UrlFilenameViewController"/>
<beanid="editAccountFormController"
class="org.springframework.web.servlet.mvc.SimpleFormController">
<propertyname="formView"value="account"/>
<propertyname="successView"value="account-created"/>
<propertyname="commandName"value="Account"/>
<propertyname="commandClass"value="samples.Account"/>
</bean>
<beans>
help.htmlhelpController helpControllerUrlFilenameViewController
13.3“” exview .htmleditAccountFormController
13.4.3. HandlerInterceptor
Springorg.springframework.web.servletHandlerInterceptor
preHandle(..)boolean true
96
<beans>
<beanid="handlerMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<propertyname="interceptors">
<list>
<refbean="officeHoursInterceptor"/>
</list>
</property>
<propertyname="mappings">
<value>
/*.form=editAccountFormController
/*.view=editAccountFormController
</value>
</property>
</bean>
<beanid="officeHoursInterceptor"
class="samples.TimeBasedAccessInterceptor">
<propertyname="openingTime"value="9"/>
<propertyname="closingTime"value="18"/>
</bean>
<beans>
packagesamples;
publicclassTimeBasedAccessInterceptorextendsHandlerInterceptorAdapter{
privateintopeningTime;
privateintclosingTime;
publicvoidsetOpeningTime(intopeningTime){
this.openingTime=openingTime;
}
publicvoidsetClosingTime(intclosingTime){
this.closingTime=closingTime;
}
publicbooleanpreHandle(
HttpServletRequestrequest,
HttpServletResponseresponse,
Objecthandler)throwsException{
Calendarcal=Calendar.getInstance();
inthour=cal.get(HOUR_OF_DAY);
if(openingTime<=hour<closingTime){
returntrue;
}else{
response.sendRedirect("http://host.com/outsideOfficeHours.html");
returnfalse;
}
}
}
TimeBasedAccessInterceptor htmlSpringadapterHandlerInterceptorAdapterHandlerInterceptor
13.5.webMVC SpringViewResolverViewSpring ViewResolver
13.5.1. ViewResolver
13.3“” SpringWeb ModelAndView SprnigSpring
13.4.ViewResolver
AbstractCachingViewResolver
XmlViewResolverXmlViewResolver ViewResolverXMLXMLBeanFactoryDTD /WEB-INF/views.xml
ResourceBundleViewResolver
ResourceBundleViewResolver ViewResolverResourceBundlebean bundleclasspathviews.properties
UrlBasedViewResolverUrlBasedViewResolver ViewResolverURL
InternalResourceViewResolver
UrlBasedViewResolverInternalResourceViewServletJSPJstlViewTilesView setViewClassUrlBasedViewResolverJavadoc
VelocityViewResolver/FreeMarkerViewResolver
UrlBasedViewResolverVelocityViewVelocity FreeMarkerView
JSP UrlBasedViewResolverURLRequestDispatcher
<beanid="viewResolver"
class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<propertyname="prefix"value="/WEB-INF/jsp/"/>
<propertyname="suffix"value=".jsp"/>
</bean>
test RequestDispatcherRequestDispatcher/WEB-INF/jsp/test.jsp
web ResourceBundleViewResolver
<beanid="viewResolver"
class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<propertyname="basename"value="views"/>
<propertyname="defaultParentView"value="parentView"/>
</bean>
ResourceBundleViewResolverbasenameResourceBundleResourceBundle [].class [].url URLparentview AbstractCachingViewResolver Velocity removeFromCache(StringviewName,Localeloc)
13.5.2.Spring InternalResourceViewResolver
InternalResourceViewResolver
<beanid="jspViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>
<propertyname="prefix"value="/WEB-INF/jsp/"/>
<propertyname="suffix"value=".jsp"/>
</bean>
<beanid="excelViewResolver"class="org.springframework.web.servlet.view.XmlViewResolver">
<propertyname="order"value="1"/>
<propertyname="location"value="/WEB-INF/views.xml"/>
</bean>
<!--inviews.xml-->
<beans>
<beanname="report"class="org.springframework.example.ReportExcelView"/>
</beans>
Spring Srpingnull
RequestDispatcherJSP InternalResourceViewResolver
InternalResourceViewResolver
13.5.3.Rediret JSPServlet/JSPInternalResourceViewServletAPI RequestDispatcher.forward(..)
RequestDispatcher.include() VelocityXSLTHTTPredirect HTTPPOST HTTPredirect
GET POST
13.5.3.1.RedirectViewSpringRedirectView DispatcherServletRedirectViewHttpServletResponse.sendRedirect() HTTPredirectHTTP stringHTTPStringStringRedirectView URLSpringIoC
13.5.3.2.redirect:RedirectView RedirectView redirect: redirect: UrlBasedViewResolverURLRedirectView redirect:/my/response/controller.html
context redirect:http://myhost.com/some/arbitrary/path.html
URL
13.5.3.3.forward:forward: UrlBasedViewResolver
RequestDispatcher.forward()forwardURLInternalResourceViewResolver/InternalResourceViewJSPServlet/JSPengineforward forwardforwardredirect:forward
13.6.SpringSpringwebMVC DispatcherServlet
DispatcherServlet RequestContext.getLocale()
13.4.3“ HandlerInterceptor” org.springframework.web.servlet.i18n Spring
13.6.1.AcceptHeaderLocaleResolveraccept-language HTTPHeader
13.6.2.CookieLocaleResolverCookie cookiecookieMaxAge
<beanid="localeResolver"class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
<propertyname="cookieName"value="clientlanguage"/>
<!--inseconds.Ifsetto-1,thecookieisnotpersisted(deletedwhenbrowsershutsdown)-->
<propertyname="cookieMaxAge"value="100000">
</bean>
13.5.CookieLocaleResolver
cookieName classname+LOCALE cookie
cookieMaxAge Integer.MAX_INT cookie-1cookiecookie
cookiePath / cookie (cookiePath)cookie
13.6.3.SessionLocaleResolverSessionLocaleResolversession
13.6.4.LocaleChangeInterceptorLocaleChangeInterceptor 13.4“handlermapping”
LocaleResolversetLocale()
<beanid="localeChangeInterceptor"
class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
<propertyname="paramName"value="siteLanguage"/>
</bean>
<beanid="localeResolver"
class="org.springframework.web.servlet.i18n.CookieLocaleResolver"/>
<beanid="urlMapping"
class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<propertyname="interceptors">
<list>
<refbean="localeChangeInterceptor"/>
</list>
</property>
<propertyname="mappings">
<value>/**/*.view=someController</value>
</property>
</bean>
*.view siteLanguage http://www.sf.net/home.view?
siteLanguage=nl
13.7.
13.7.1.SpingwebMVCtheme
13.7.2.web org.springframework.ui.context.ThemeSource
WebApplicationContextThemeSource ThemeSourceorg.springframework.ui.context.support.ResourceBundleThemeSourceclasspath /WEB-INF/classesResourceBundleThemeSourcebasenameprefix "themeSource"bean webapplicationcontextbeanResourceBundleThemeSource :
styleSheet=/themes/cool/style.css
background=/themes/cool/img/coolBg.jpg
themedelement JSP
<%@taglibprefix="spring"uri="http://www.springframework.org/tags"%>
<html>
<head>
<linkrel="stylesheet"href="<spring:themecode="styleSheet"/>"type="text/css"/>
</head>
<bodybackground="<spring:themecode="background"/>">
...
</body>
</html>
ResourceBundleThemeSourcecool.properties classpath /WEB-INF/classes
ResourceBundleThemeSourceJavaresourcebundle INF/classes/cool_nl.properties
ResourceBundleJavaDocResourceBundle.getBundle(StringbaseName,Localelocale)API baseName cool.properties/WEB-
INF/classes/com/aa/bb/cc baseNamecom.aa.bb.cc.coolcom.aa.bb.cc(basenameprefix) APIgetBundle(
ResourceBundleThemeSource
13.7.3. DispatcherServlet“themeResolver”bean LocaleResolver Spring
13.6.ThemeResolver
JavaFixedThemeResolver “defaultThemeName”
SessionThemeResolver HTTPsessionsessionsession
CookieThemeResolver cookie
SpringThemeChangeInterceptor
13.8.Springmultipartfileupload
13.8.1.Springweb MultipartResolver Spring MultipartResolverCommonsFileUploadhttp://jakarta.apache.org/commons/fileupload COSFileUpload(http://www.servlets.com/cos) SpringSpring Springweb
13.8.2. MultipartResolver
CommonsMultipartResolver
<beanid="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!--oneofthepropertiesavailable;themaximumfilesizeinbytes-->
<propertyname="maxUploadSize"value="100000"/>
</bean>
CosMultipartResolver
<beanid="multipartResolver"class="org.springframework.web.multipart.cos.CosMultipartResolver">
<!--oneofthepropertiesavailable;themaximumfilesizeinbytes-->
<propertyname="maxUploadSize"value="100000"/>
</bean>
classpathjar CommonsMultipartResolver
CosMultipartResolver cos.jar
Spring Spring DispatcherServlet
MultipartHttpServletRequest MultipartHttpServletRequest
13.8.3.MultipartResolver uploadfieldHTMLSpring
<html>
<head>
<title>Uploadafileplease</title>
</head>
<body>
<h1>Pleaseuploadafile</h1>
<formmethod="post"action="upload.form"enctype="multipart/form-data">
<inputtype="file"name="file"/>
<inputtype="submit"/>
</form>
</body>
</html>
input“file”bean
primitivetypebeanbean StringMultipartEditorbyte CustomDateEditor
HTMLURL
<beans>
<!--letsusetheCommons-basedimplementationoftheMultipartResolverinterface-->
<beanid="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver"/>
<beanid="urlMapping"class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<propertyname="mappings">
<value>
/upload.form=fileUploadController
</value>
</property>
</bean>
<beanid="fileUploadController"class="examples.FileUploadController">
<propertyname="commandClass"value="examples.FileUploadBean"/>
<propertyname="formView"value="fileuploadform"/>
<propertyname="successView"value="confirmation"/>
</bean>
</beans>
bean
publicclassFileUploadControllerextendsSimpleFormController{
protectedModelAndViewonSubmit(
HttpServletRequestrequest,
HttpServletResponseresponse,
Objectcommand,
BindExceptionerrors)throwsServletException,IOException{
//castthebean
FileUploadBeanbean=(FileUploadBean)command;
let'sseeifthere'scontentthere
byte[]file=bean.getFile();
if(file==null){
//hmm,that'sstrange,theuserdidnotuploadanything
}
//well,let'sdonothingwiththebeanfornowandreturn
returnsuper.onSubmit(request,response,command,errors);
}
protectedvoidinitBinder(HttpServletRequestrequest,ServletRequestDataBinderbinder)
throwsServletException{
//toactuallybeabletoconvertMultipartinstancetobyte[]
//wehavetoregisteracustomeditor
binder.registerCustomEditor(byte[].class,newByteArrayMultipartFileEditor());
//nowSpringknowshowtohandlemultipartobjectandconvertthem
}
}
publicclassFileUploadBean{
privatebyte[]file;
publicvoidsetFile(byte[]file){
this.file=file;
}
publicbyte[]getFile(){
returnfile;
}
}
FileUploadBeanbyte[] Springmultipartbean
formbackingString
publicclassFileUploadControllerextendsSimpleFormController{
protectedModelAndViewonSubmit(
HttpServletRequestrequest,
HttpServletResponseresponse,
Objectcommand,
BindExceptionerrors)throwsServletException,IOException{
//castthebean
FileUploadBeanbean=(FileUploadBean)command;
let'sseeifthere'scontentthere
Stringfile=bean.getFile();
if(file==null){
//hmm,that'sstrange,theuserdidnotuploadanything
}
//well,let'sdonothingwiththebeanfornowandreturn
returnsuper.onSubmit(request,response,command,errors);
}
protectedvoidinitBinder(HttpServletRequestrequest,ServletRequestDataBinderbinder)
throwsServletException{
//toactuallybeabletoconvertMultipartinstancetoaString
//wehavetoregisteracustomeditor
binder.registerCustomEditor(String.class,newStringMultipartFileEditor());
//nowSpringknowshowtohandlemultipartobjectandconvertthem
}
}
publicclassFileUploadBean{
privateStringfile;
publicvoidsetFile(Stringfile){
this.file=file;
}
publicStringgetFile(){
returnfile;
}
}
formbacking MultipartFile
publicclassFileUploadControllerextendsSimpleFormController{
protectedModelAndViewonSubmit(
HttpServletRequestrequest,
HttpServletResponseresponse,
Objectcommand,
BindExceptionerrors)throwsServletException,IOException{
//castthebean
FileUploadBeanbean=(FileUploadBean)command;
let'sseeifthere'scontentthere
MultipartFilefile=bean.getFile();
if(file==null){
//hmm,that'sstrange,theuserdidnotuploadanything
}
//well,let'sdonothingwiththebeanfornowandreturn
returnsuper.onSubmit(request,response,command,errors);
}
}
publicclassFileUploadBean{
privateMultipartFilefile;
publicvoidsetFile(MultipartFilefile){
this.file=file;
}
publicMultipartFilegetFile(){
returnfile;
}
}
13.9.Spring2.0JSPSpringWebMVCSpringHTML4.01/XHTML1.0/SpringSpringWebMVC commandobjectreferencedataJSP HTML
13.9.1.Springspring.jar descriptor) spring-form.tld
JSP
<%@taglibprefix="form"uri="http://www.springframework.org/tags/form"%>
form
13.9.2.formHTML“form”bindingpath form
UserJavaBean firstNamelastNameobject) form.jsp
<form:form>
<table>
<tr>
<td>FirstName:</td>
<td><form:inputpath="firstName"/></td>
</tr>
<tr>
<td>LastName:</td>
<td><form:inputpath="lastName"/></td>
</tr>
<tr>
<tdcolspan="2">
<inputtype="submit"value="SaveChanges"/>
</td>
</tr>
</table>
</form:form>
firstNamelastNamePageContextHTMLform
<formmethod="POST">
<table>
<tr>
<td>FirstName:</td>
<td><inputname="firstName"type="text"value="Harry"/></td>
</tr>
<tr>
<td>LastName:</td>
<td><inputname="lastName"type="text"value="Potter"/></td>
</tr>
<tr>
<tdcolspan="2">
<inputtype="submit"value="SaveChanges"/>
</td>
</tr>
</table>
</form>
JSPformbacking“ command”
<form:formcommandName="user">
<table>
<tr>
<td>FirstName:</td>
<td><form:inputpath="firstName"/></td>
</tr>
<tr>
<td>LastName:</td>
<td><form:inputpath="lastName"/></td>
</tr>
<tr>
<tdcolspan="2">
<inputtype="submit"value="SaveChanges"/>
</td>
</tr>
</table>
</form:form>
13.9.3.input“text”HTML“input” 13.9.2“ form”
13.9.4.checkbox“checkbox”HTML“input”User Preferences
publicclassPreferences{
privatebooleanreceiveNewsletter;
privateString[]interests;
privateStringfavouriteWord;
publicbooleanisReceiveNewsletter(){
returnreceiveNewsletter;
}
publicvoidsetReceiveNewsletter(booleanreceiveNewsletter){
this.receiveNewsletter=receiveNewsletter;
}
publicString[]getInterests(){
returninterests;
}
publicvoidsetInterests(String[]interests){
this.interests=interests;
}
publicStringgetFavouriteWord(){
returnfavouriteWord;
}
publicvoidsetFavouriteWord(StringfavouriteWord){
this.favouriteWord=favouriteWord;
}
}
form.jsp
<form:form>
<table>
<tr>
<td>Subscribetonewsletter?:</td>
<%--Approach1:Propertyisoftypejava.lang.Boolean
<td><form:checkboxpath="preferences.receiveNewsletter"/></td>
</tr>
<tr>
<td>Interests:</td>
<td>
<%--Approach2:Propertyisofanarrayoroftype
Quidditch:<form:checkboxpath="preferences.interests"value="Quidditch"/>
Herbology:<form:checkboxpath="preferences.interests"value="Herbology"/>
DefenceAgainsttheDarkArts:<form:checkboxpath="preferences.interests"
value="DefenceAgainsttheDarkArts"/>
</td>
</tr>
<tr>
<td>FavouriteWord:</td>
<td>
<%--Approach3:Propertyisoftypejava.lang.Object
Magic:<form:checkboxpath="preferences.favouriteWord"value="Magic"/>
</td>
</tr>
</table>
</form:form>
checkboxcheckbox
java.lang.Boolean true input(checkbox) value
setValue(Object)
arrayjava.util.Collection setValue(Object)Collection
input(checkbox)
setValue(Object) input(checkbox)
HTMLcheckboxHTML
<tr>
<td>Interests:</td>
<td>
Quidditch:<inputname="preferences.interests"type="checkbox"value="Quidditch"/>
<inputtype="hidden"value="1"name="_preferences.interests"/>
Herbology:<inputname="preferences.interests"type="checkbox"value="Herbology"/>
<inputtype="hidden"value="1"name="_preferences.interests"/>
DefenceAgainsttheDarkArts:<inputname="preferences.interests"type="checkbox"
value="DefenceAgainsttheDarkArts"/>
<inputtype="hidden"value="1"name="_preferences.interests"/>
</td>
</tr>
checkboxfield HTMLcheckboxcheckboxSpringcheckbox"_"checkbox ”
13.9.5.checkboxes“checkbox”HTML“input”checkbox JSP JSP
<form:form>
<table>
<tr>
<td>Interests:</td>
<td>
<%--Propertyisofanarrayoroftypejava.util.Collection
<form:checkboxespath="preferences.interests"items="${interestList}"/>
</td>
</tr>
</table>
</form:form>
“interestList” List Mapmapmap“itemLabel”
13.9.6.radiobutton“radio”HTML“input”
<tr>
<td>Sex:</td>
<td>Male:<form:radiobuttonpath="sex"value="M"/><br/>
Female:<form:radiobuttonpath="sex"value="F"/></td>
</tr>
13.9.7.radiobuttons“radio”HTML“input”checkboxes radiobuttons
map map“itemValue”“itemLabel”
<tr>
<td>Sex:</td>
<td><form:radiobuttonspath="sex"items="${sexOptions}"/></td>
</tr>
13.9.8.password“password”HTML“input”
<tr>
<td>Password:</td>
<td>
<form:passwordpath="password"/>
</td>
</tr>
“ showPassword”true
<tr>
<td>Password:</td>
<td>
<form:passwordpath="password"value="^76525bvHGq"showPassword="true"/>
</td>
</tr>
13.9.9.selectHTML“select” option
User
<tr>
<td>Skills:</td>
<td><form:selectpath="skills"items="${skills}"/></td>
</tr>
User“Skills”HTML
<tr>
<td>Skills:</td>
<td><selectname="skills"multiple="true">
<optionvalue="Potions">Potions</option>
<optionvalue="Herbology"selected="selected">Herbology</option>
<optionvalue="Quidditch">Quidditch</option></select>
</td>
</tr>
13.9.10.optionHTML“option”“selected”
<tr>
<td>House:</td>
<td>
<form:selectpath="house">
<form:optionvalue="Gryffindor"/>
<form:optionvalue="Hufflepuff"/>
<form:optionvalue="Ravenclaw"/>
<form:optionvalue="Slytherin"/>
</form:select>
</td>
</tr>
UserGryffindorGryffindor·Hogwarts—— “House”HTML
<tr>
<td>House:</td>
<td>
<selectname="house">
<optionvalue="Gryffindor"selected="selected">Gryffindor</option>
<optionvalue="Hufflepuff">Hufflepuff</option>
<optionvalue="Ravenclaw">Ravenclaw</option>
<optionvalue="Slytherin">Slytherin</option>
</select>
</td>
</tr>
13.9.11.optionsHTML“option”“selected”
<tr>
<td>Country:</td>
<td>
<form:selectpath="country">
<form:optionvalue="-"label="--PleaseSelect"/>
<form:optionsitems="${countryList}"itemValue="code"itemLabel="name"/>
</form:select>
</td>
</tr>
User“Country”HTML
<tr>
<td>Country:</td>
<td>
<selectname="country">
<optionvalue="-">--PleaseSelect</option>
<optionvalue="AT">Austria</option>
<optionvalue="UK"selected="selected">UnitedKingdom</option>
<optionvalue="US">UnitedStates</option>
</select>
</td>
</tr>
optionoptionsHTML JSP“--PleaseSelect”
13.9.12.textareaHTML“textarea”
<tr>
<td>Notes:</td>
<td><form:textareapath="notes"rows="3"cols="20"/></td>
<td><form:errorspath="notes"/></td>
</tr>
13.9.13.hidden“hidden”HTML“input” HTMLinputinput
<form:hiddenpath="house"/>
“house”HTML
<inputname="house"type="hidden"value="Gryffindor"/>
13.9.14.errorsHTML“span”firstNamelastName UserUserValidator
publicclassUserValidatorimplementsValidator{
publicbooleansupports(Classcandidate){
returnUser.class.isAssignableFrom(candidate);
}
publicvoidvalidate(Objectobj,Errorserrors){
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"firstName","required","Fieldisrequired.");
ValidationUtils.rejectIfEmptyOrWhitespace(errors,"lastName","required","Fieldisrequired.");
}
}
form.jsp
<form:form>
<table>
<tr>
<td>FirstName:</td>
<td><form:inputpath="firstName"/></td>
<%--ShowerrorsforfirstNamefield--%>
<td><form:errorspath="firstName"/></td>
</tr>
<tr>
<td>LastName:</td>
<td><form:inputpath="lastName"/></td>
<%--ShowerrorsforlastNamefield--%>
<td><form:errorspath="lastName"/></td>
</tr>
<tr>
<tdcolspan="3">
<inputtype="submit"value="SaveChanges"/>
</td>
</tr>
</table>
</form:form>
firstNamelastName HTML
<formmethod="POST">
<table>
<tr>
<td>FirstName:</td>
<td><inputname="firstName"type="text"value=""/></td>
<%--AssociatederrorstofirstNamefielddisplayed--%>
<td><spanname="firstName.errors">Fieldisrequired.</span></td>
</tr>
<tr>
<td>LastName:</td>
<td><inputname="lastName"type="text"value=""/></td>
<%--AssociatederrorstolastNamefielddisplayed--%>
<td><spanname="lastName.errors">Fieldisrequired.</span></td>
</tr>
<tr>
<tdcolspan="3">
<inputtype="submit"value="SaveChanges"/>
</td>
</tr>
</table>
</form>
errors
path="*"
path="lastName*"lastName
<form:form>
<form:errorspath="*"cssClass="errorBox"/>
<table>
<tr>
<td>FirstName:</td>
<td><form:inputpath="firstName"/></td>
<td><form:errorspath="firstName"/></td>
</tr>
<tr>
<td>LastName:</td>
<td><form:inputpath="lastName"/></td>
<td><form:errorspath="lastName"/></td>
</tr>
<tr>
<tdcolspan="3">
<inputtype="submit"value="SaveChanges"/>
</td>
</tr>
</table>
</form:form>
HTML
<formmethod="POST">
<spanname="*.errors"class="errorBox">Fieldisrequired.<br/>Fieldisrequired.</span>
<table>
<tr>
<td>FirstName:</td>
<td><inputname="firstName"type="text"value=""/></td>
<td><spanname="firstName.errors">Fieldisrequired.</span></td>
</tr>
<tr>
<td>LastName:</td>
<td><inputname="lastName"type="text"value=""/></td>
<td><spanname="lastName.errors">Fieldisrequired.</span></td>
</tr>
<tr>
<tdcolspan="3">
<inputtype="submit"value="SaveChanges"/>
</td>
</tr>
</form>
13.10. Spring HandlerExceptionResolvers
Web web.xmlexceptionmappings
HandlerExceptionResolver resolveExceptionExceptionHandler
ModelAndView SimpleMappingExceptionResolver
13.11.conventionoverconfiguration……SpringWebMVC
SpringWebMVC
13.11.1. ControllerClassNameHandlerMapping
ControllerClassNameHandlerMappingHandlerMapping URL
Controller
publicclassViewShoppingCartControllerimplementsController{
publicModelAndViewhandleRequest(HttpServletRequestrequest,HttpServletResponseresponse){
//theimplementationisnothugelyimportantforthisexample...
}
}
SpringWebMVC
<beanclass="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<beanid="viewShoppingCart"class="x.y.z.ViewShoppingCartController">
<!--injectdependenciesasrequired...-->
</bean>
ControllerClassNameHandlerMappinghandler ControllerbeanController
WelcomeController“ /welcome*”URL
HomeController“ /home*”URL
IndexController“ /index*”URL
RegisterController“ /register*”URL
DisplayShoppingCartController“ /displayshoppingcart*URL———— Controller
MultiActionControllerMultiActionController
AdminController“ /admin/*”URL
CatalogController“ /catalog/*”URLControllerxxxController ControllerClassNameHandlerMapping———— SimpleUrlHandlerMapping
ControllerClassNameHandlerMappingAbstractHandlerMappingHandlerMappingHandlerInterceptor
13.11.2. ModelMapModelAndView
ModelMapMap View
publicclassDisplayShoppingCartControllerimplementsController{
publicModelAndViewhandleRequest(HttpServletRequestrequest,HttpServletResponseresponse){
ListcartItems=//getaListofCartItemobjects
Useruser=//gettheUserdoingtheshopping
ModelAndViewmav=newModelAndView("displayShoppingCart");
mav.addObject(cartItems);<--lookma,noname,justtheobject
mav.addObject(user);<--andagainma!
returnmav;
}
}
ModelAndViewModelMapMap ModelMap
x.y.User“ user”
x.y.Registration“ registration”
SpringWebMVCListModelAndView“people”“ PrincipleofLeastSurprise ”
x.y.Foo“ foo”
java.util.HashMap“ hashMap”“ hashMap
nullIllegalArgumentException null
SetList
x.y.Userx.y.User[]“ userList”
x.y.Userx.y.Foo[]“ fooList”
x.y.Userjava.util.ArrayList
“ userList”
x.y.Foojava.util.HashSet
“ fooList”
java.util.ArrayList addObject(..)
13.11.3. RequestToViewNameTranslator
RequestToViewNameTranslatorDefaultRequestToViewNameTranslator
DefaultRequestToViewNameTranslatorURL
publicclassRegistrationControllerimplementsController{
publicModelAndViewhandleRequest(HttpServletRequestrequest,HttpServletResponseresponse){
//processtherequest...
ModelAndViewmav=newModelAndView();
//adddataasnecessarytothemodel...
returnmav;
//noticethatnoVieworlogicalviewnamehasbeenset
}
}
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!--thisbeanwiththewellknownnamegeneratesviewnamesforus-->
<beanid="viewNameTranslator"class="org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator"/>
<beanclass="x.y.RegistrationController">
<!--injectdependenciesasnecessary-->
</bean>
<!--mapsrequestURLstoControllernames-->
<beanclass="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<beanid="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<propertyname="prefix"value="/WEB-INF/jsp/"/>
<propertyname="suffix"value=".jsp"/>
</bean>
</beans>
handleRequest(..) ModelAndViewViewDefaultRequestToViewNameTranslator RegistrationController
ControllerClassNameHandlerMapping“ http://localhost/registration.html”URLDefaultRequestToViewNameTranslator“ registration”InternalResourceViewResolver bean“ /WEB-INF/jsp/registration.jsp”
DefaultRequestToViewNameTranslator beanDefaultRequestToViewNameTranslator SpringWebMVCDispatcherServlet
DefaultRequestToViewNameTranslatorbeanDefaultRequestToViewNameTranslatorJavadoc
13.12.XMLSpring2.5MVCSpring2.5MVC @RequestMapping@RequestParam@ModelAttributeServletMVCPortletMVCPortlet
SpringPetClinic WebPetClinicWebMVC imagedbmulti-action“ samples/imagedb” imagedb
13.12.1.dispatcherHandlerMapping/ HandlerAdapterdispatcher@RequestMapping DispatcherServletDispatcherPortlet
HandlerMappingsHandlerAdapters DefaultAnnotationHandlerMapping
AnnotationMethodHandlerAdapter——@RequestMapping
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanclass="org.springframework.web.servlet.mvc.DefaultAnnotationHandlerMapping"/>
<beanclass="org.springframework.web.servlet.mvc.AnnotationMethodHandlerAdapter"/>
...(controllerbeandefinitions)...
</beans>
DefaultAnnotationHandlerMapping/ AnnotationMethodHandlerAdapter
PathMatcherWebBindingInitializer
13.12.2. @Controller
@Controller ServletAPIServlet@Controller DispatcherbeandispatcherSpringbean XML
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd">
<context:component-scanbase-package="org.springframework.samples.petclinic.web"/>
...
</beans>
13.12.3. @RequestMapping
@RequestMapping“/editPet.do”URL“GET/POST”HTTP
@RequestMappingController@RequestMapping Controller SimpleFormController
PetClinic
@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
publicclassEditPetForm{
privatefinalClinicclinic;
@Autowired
publicEditPetForm(Clinicclinic){
this.clinic=clinic;
}
@ModelAttribute("types")
publicCollection<PetType>populatePetTypes(){
returnthis.clinic.getPetTypes();
}
@RequestMapping(method=RequestMethod.GET)
publicStringsetupForm(@RequestParam("petId")intpetId,ModelMapmodel){
Petpet=this.clinic.loadPet(petId);
model.addAttribute("pet",pet);
return"petForm";
}
@RequestMapping(method=RequestMethod.POST)
publicStringprocessSubmit(@ModelAttribute("pet")Petpet,BindingResultresult,
SessionStatusstatus){
newPetValidator().validate(pet,result);
if(result.hasErrors()){
return"petForm";
}
else{
this.clinic.storePet(pet);
status.setComplete();
return"redirect:owner.do?ownerId="+pet.getOwner().getId();
}
}
}
multi-actionURLURL
@Controller
publicclassClinicController{
privatefinalClinicclinic;
@Autowired
publicClinicController(Clinicclinic){
this.clinic=clinic;
}
/**
*Customhandlerforthewelcomeview.
*NotethatthishandlerreliesontheRequestToViewNameTranslatorto
*determinethelogicalviewnamebasedontherequestURL:"/welcome.do"
*->"welcome".
*/
@RequestMapping("/welcome.do")
publicvoidwelcomeHandler(){
}
/**
*Customhandlerfordisplayingvets.
*Notethatthishandlerreturnsaplain{@linkModelMap}objectinsteadof
*aModelAndView,thusleveragingconvention-basedmodelattributenames.
*ItreliesontheRequestToViewNameTranslatortodeterminethelogical
*viewnamebasedontherequestURL:"/vets.do"->"vets".
*
*@returnaModelMapwiththemodelattributesfortheview
*/
@RequestMapping("/vets.do")
publicModelMapvetsHandler(){
returnnewModelMap(this.clinic.getVets());
}
/**
*Customhandlerfordisplayinganowner.
*Notethatthishandlerreturnsaplain{@linkModelMap}objectinsteadof
*aModelAndView,thusleveragingconvention-basedmodelattributenames.
*ItreliesontheRequestToViewNameTranslatortodeterminethelogical
*viewnamebasedontherequestURL:"/owner.do"->"owner".
*
*@paramownerIdtheIDoftheownertodisplay
*@returnaModelMapwiththemodelattributesfortheview
*/
@RequestMapping("/owner.do")
publicModelMapownerHandler(@RequestParam("ownerId")intownerId){
returnnewModelMap(this.clinic.loadOwner(ownerId));
}
}
@RequestMapping
/ServletAPIPortletAPI /ServletRequest/HttpServletRequestPortletRequest/ActionRequest/RenderRequest Portletaction/renderactionrenderrequestsServletAPIPortletAPIHttpSessionPortletSessionServlet AnnotationMethodHandlerAdapter
“synchronizeOnSession”“true”org.springframework.web.context.request.WebRequest
org.springframework.web.context.request.NativeWebRequest/Servlet/PortletAPIjava.util.Localelocalejava.io.InputStream/java.io.Reader Servlet/PortletAPIInputStream/Readerjava.io.OutputStream/java.io.Writer Servlet/PortletAPIOutputStream/Writer@RequestParamServlet/Portlet
java.util.Map/org.springframework.ui.Model/org.springframework.ui.ModelMapWeb/bean @InitBinder/HandlerAdapter——AnnotationMethodHandlerAdapter“ webBindingInitializer”“mypackage.OrderAddress”“orderAddress”ModelAttribute
org.springframework.validation.Errors/org.springframework.validation.BindingResult/org.springframework.web.bind.support.SessionStatus
@SessionAttributes
13.12.4. @RequestParam
@RequestParam
PetClinic
@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
publicclassEditPetForm{
//...
@RequestMapping(method=RequestMethod.GET)
publicStringsetupForm(@RequestParam("petId")intpetId
Petpet=this.clinic.loadPet(petId);
model.addAttribute("pet",pet);
return"petForm";
}
//...
@RequestParamrequiredfalse @RequestParam(value="id",
required="false")
13.12.5. @ModelAttribute
@ModelAttribute @ModelAttribute
java.lang.Object
@ModelAttribute populatePetTypes()@ModelAttribute@RequestMapping
@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
publicclassEditPetForm{
//...
@ModelAttribute("types")
publicCollection<PetType>populatePetTypes(){
returnthis.clinic.getPetTypes();
}
@RequestMapping(method=RequestMethod.POST)
publicStringprocessSubmit(@ModelAttribute("pet")Petpet
SessionStatusstatus){
newPetValidator().validate(pet,result);
if(result.hasErrors()){
return"petForm";
}
else{
this.clinic.storePet(pet);
status.setComplete();
return"redirect:owner.do?ownerId="+pet.getOwner().getId();
}
}
}
13.12.6. @SessionAttributes
@SessionAttributes beans
@Controller
@RequestMapping("/editPet.do")
@SessionAttributes("pet")
publicclassEditPetForm{
//...
}
13.12.7. WebDataBinder
SpringWebDataBinderPropertyEditors @InitBinder——WebBindingInitializer
13.12.7.1. @InitBinder
@InitBinderWeb @InitBinderWebDataBinder
init-binder@RequestMapping/ Init-binderWebDataBinderWebRequestjava.util.Locale
@InitBinder java.util.DateCustomDateEditor
@Controller
publicclassMyFormController{
@InitBinder
publicvoidinitBinder(WebDataBinderbinder){
SimpleDateFormatdateFormat=newSimpleDateFormat("yyyy-MM-dd");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class,newCustomDateEditor(dateFormat,false));
}
//...
}
13.12.7.2. WebBindingInitializer
WebBindingInitializer AnnotationMethodHandlerAdapter
PetClinicWebBindingInitializer——org.springframework.samples.petclinic.web.ClinicBindingInitializer
PetClinicPropertyEditors
<beanclass="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<propertyname="cacheSeconds"value="0"/>
<propertyname="webBindingInitializer">
<beanclass="org.springframework.samples.petclinic.web.ClinicBindingInitializer"/>
</property>
</bean>
13.13.SpringWebMVC
SpringSpringWebMVCSpringWebMVCSpring“ docs”SpringFramework
SethLadd“ ExpertSpringWebMVCandWebFlow”ApressSpringWebMVC
14
14.1.14.2.JSPJSTL
14.2.1.14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTL14.2.3.
14.3.Tiles14.3.1.14.3.2.Tiles
14.4.VelocityFreeMarker14.4.1.14.4.2.Context14.4.3.14.4.4.14.4.5.
14.5.XSLT14.5.1.14.5.2.
14.6.PDF/Excel14.6.1.14.6.2.
14.7.JasperReports14.7.1.14.7.2.14.7.3. ModelAndView
14.7.4.14.7.5.Exporter
14.1.SpringviewMVC VelocityXSLTJSP“” “mvc-viewresolver”viewMVC
14.2.JSPJSTLSpringJSPJSTLviewJSPJSTLJSP SpringJSP
14.2.1.SpringJSPResourceBundleViewResolver
<!--the
ResourceBundleViewResolver
-->
<beanid="viewResolver"class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<propertyname="basename"value="views"/>
</bean>
#Andasamplepropertiesfileisuses
(views.propertiesinWEB-INF/classes):
welcome.class=org.springframework.web.servlet.view.JstlView
welcome.url=/WEB-INF/jsp/welcome.jsp
productList.class=org.springframework.web.servlet.view.JstlView
productList.url=/WEB-INF/jsp/productlist.jsp
ResourceBundleViewResolverview1)class2)URLResourceBundleViewResolver
<beanid="viewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<propertyname="viewClass"value="org.springframework.web.servlet.view.JstlView"/>
<propertyname="prefix"value="/WEB-INF/jsp/"/>
<propertyname="suffix"value=".jsp"/>
</bean>
JSP InternalResourceBundleViewResolver
14.2.2.'Plain-old'JSPsversusJSTL'Plain-old'JSPJSTLJSTLview JstlViewJSTLi18N
14.2.3.SpringJSPSpringspring.jar(TLD)tagtag
14.3.TilesSpringwebTilesweb
Spring org.springframework.web.servlet.view.tiles2Tiles2TilesJava5+ org.springframework.web.servlet.view.tiles
Tiles1.x“StrutsTiles”Struts1.1+Java1.4
14.3.1.Tiles
Tilesversion2.0.4
CommonsBeanUtils
CommonsDigester
CommonsLogging
Spring
14.3.2.TilesTilesTiles
<beanid="tilesConfigurer"class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<propertyname="definitions">
<list>
<value>/WEB-INF/defs/general.xml</value>
<value>/WEB-INF/defs/widgets.xml</value>
<value>/WEB-INF/defs/administrator.xml</value>
<value>/WEB-INF/defs/customer.xml</value>
<value>/WEB-INF/defs/templates.xml</value>
</list>
</property>
</bean>
'WEB-INF/defs' WebApplicationContext
tilesviewsSpringweb viewsUrlBasedViewResolverResourceBundleViewResolver
14.3.2.1.UrlBasedViewResolver
UrlBasedViewResolverview viewClass
<beanid="viewResolver"class="org.springframework.web.servlet.view.UrlBasedViewResolver">
<propertyname="viewClass"value="org.springframework.web.servlet.view.tiles2.TilesView"/>
</bean>
14.3.2.2.ResourceBundleViewResolverResourceBundleViewResolver
<beanid="viewResolver"class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<propertyname="basename"value="views"/>
</bean>
...
welcomeView.class=org.springframework.web.servlet.view.tiles2.TilesView
welcomeView.url=welcome
(thisisthenameofaTilesdefinition)
vetsView.class=org.springframework.web.servlet.view.tiles2.TilesView
vetsView.url=vetsView
(again,thisisthenameofaTilesdefinition)
findOwnersForm.class=org.springframework.web.servlet.view.JstlView
findOwnersForm.url=/WEB-INF/jsp/findOwners.jsp
...
ResourceBundleViewResolverviewTiles2 TilesViewJSTLJSPTiles1.x
14.3.2.3. SimpleSpringPreparerFactorySpringBeanPreparerFactory
SpringTiles2 PreparerFactoryTilespreparer SimpleSpringPreparerFactoryViewPreparerSpring
SpringBeanPostProcessorsSpring annotation-configViewPreparerTilespreparer
SpringBeanPreparerFactorypreparerDispatcherServletbeanSpringbean
<beanid="tilesConfigurer"class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
<propertyname="definitions">
<list>
<value>/WEB-INF/defs/general.xml</value>
<value>/WEB-INF/defs/widgets.xml</value>
<value>/WEB-INF/defs/administrator.xml</value>
<value>/WEB-INF/defs/customer.xml</value>
<value>/WEB-INF/defs/templates.xml</value>
</list>
</property>
<!--resolvingpreparernamesasSpringbean
definitionnames-->
<propertyname="preparerFactoryClass"
value="org.springframework.web.servlet.view.tiles2.SpringBeanPreparerFactory"/>
</bean>
14.4.VelocityFreeMarkerVelocityFreeMarkerviewSpringMVC
14.4.1.VelocityFreeMarker velocity-1.x.x.jarfreemarker-2.x.jarVelocitycommons-collections.jarjar WEB-INF/libJ2EEServerwebclasspath 'WEB-INF/lib' spring.jarSpringVelocityFreeMarkercommonscollections /lib/VelocitySpringdateToolAttributenumberToolAttribute velocity-tools-generic-1.x.jar
14.4.2.Context '*-servlet.xml'bean
<!--
beanVelocityVelocity
-->
<beanid="velocityConfig"class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<propertyname="resourceLoaderPath"value="/WEB-INF/velocity/"/>
</bean>
<!--
ResourceBundleXMLLocaleresourcebundle
-->
<beanid="viewResolver"class="org.springframework.web.servlet.view.velocity.VelocityViewResolver">
<propertyname="cache"value="true"/>
<propertyname="prefix"value=""/>
<propertyname="suffix"value=".vm"/>
</bean>
<!--freemarkerconfig-->
<beanid="freemarkerConfig"class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<propertyname="templateLoaderPath"value="/WEB-INF/freemarker/"/>
</bean>
<!--
ResourceBundleXMLLocaleresourcebundle
-->
<beanid="viewResolver"class="org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver">
<propertyname="cache"value="true"/>
<propertyname="prefix"value=""/>
<propertyname="suffix"value=".ftl"/>
</bean>
webapplicationcontext VelocityConfigurationFactoryBean
FreeMarkerConfigurationFactoryBean
14.4.3.*Configurerbean
ModelAndView“welcome”/WEB-INF/velocity/welcome.vm
14.4.4.Spring
14.4.4.1.velocity.propertiesVelocity
<beanid="velocityConfig"
class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<propertyname="configLocation
value="/WEB-INF/velocity.properties"/>
</bean>
Velocityconfigbeanvelocity“configLocation”
<beanid="velocityConfig"class="org.springframework.web.servlet.view.velocity.VelocityConfigurer">
<propertyname="velocityProperties">
<props>
<propkey="resource.loader">file</prop>
<propkey="file.resource.loader.class">
org.apache.velocity.runtime.resource.loader.FileResourceLoader
</prop>
<propkey="file.resource.loader.path">${webapp.root}/WEB-INF/velocity</prop>
<propkey="file.resource.loader.cache">false</prop>
</props>
</property>
</bean>
SpringVelocity API Velocity
14.4.4.2.FreeMarkerFreeMarker'Settings''SharedVariables' FreeMarkerConfigurer
FreeMarkerConfiguration freemarkerSettings java.util.Properties
freemarkerVariables java.util.Map
<beanid="freemarkerConfig"class="org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer">
<propertyname="templateLoaderPath"value="/WEB-INF/freemarker/"/>
<propertyname="freemarkerVariables">
<map>
<entrykey="xml_escape"value-ref="fmXmlEscape"/>
</map>
</property>
</bean>
<beanid="fmXmlEscape"class="freemarker.template.utility.XmlEscape"/>
settingsvariables ConfigurationFreeMarker
14.4.5.SpringJSP <spring:bind/>1.1SpringVelocityFreeMarker
14.4.5.1.spring.jar
Spring org.springframework.web.servlet.view.velocity spring.vmorg.springframework.web.servlet.view.freemarkerspring.ftl
14.4.5.2.Springhtmlvm/ftl JSP'commandName' personFormVpersonFormF
<!--velocity--><html>...
<formaction=""method="POST">Name:
#springBind("command.name")<inputtype="text"
name="${status.expression}"value="$!status.value"
/><br>#foreach($errorin
$status.errorMessages)<b>$error</b>
<br>#end<br>...<input
type="submit"value="submit"/></form>...
</html>
<!--FreeMarker'spring'
--><#import"spring.ftl"asspring/>
<html>...<formaction=""
method="POST">Name:<@spring.bind
"command.name"/><inputtype="text"
name="${spring.status.expression}"
value="${spring.status.value?default("")}"
/><br><#list
spring.status.errorMessagesaserror>
<b>${error}</b><br>
</#list><br>...<input
type="submit"value="submit"/></form>...
</html>
#springBind/<@spring.bind>'path''command'FormController “command.address.street”
web.xml defaultHtmlEscapeServletContext #springBindEscaped/<@spring.bindEscaped>HTML
14.4.5.3. HTMLspringVTLFTL
14.1.
macro VTLdefinition FTLdefinitionmessagecode
#springMessage($code) <@spring.messagecode/>
messageTextcodedefault
#springMessageText($code
$text)
<@spring.messageTextcode,
text/>
urlURLapplicationcontextroot
#springUrl($relativeUrl) <@spring.urlrelativeUrl/>
formInput #springFormInput($path
$attributes)
<@spring.formInputpath,
attributes,fieldType/>
formHiddenInput* #springFormHiddenInput($path
$attributes)
<@spring.formHiddenInput
path,attributes/>
formPasswordInput*
#springFormPasswordInput($path
$attributes)
<@spring.formPasswordInput
path,attributes/>
formTextarea #springFormTextarea($path
$attributes)
<@spring.formTextarea
path,attributes/>
formSingleSelect #springFormSingleSelect($path
$options$attributes)
<@spring.formSingleSelect
path,options,
attributes/>
formMultiSelect #springFormMultiSelect($path
$options$attributes)
<@spring.formMultiSelect
path,options,
attributes/>
formRadioButtons#springFormRadioButtons($path
$options$separator
$attributes)
<@spring.formRadioButtons
path,optionsseparator,
attributes/>
formCheckboxes#springFormCheckboxes($path
$options$separator
$attributes)
<@spring.formCheckboxes
path,options,separator,
attributes/>
showErrors #springShowErrors($separator
$classOrStyle)
<@spring.showErrors
separator,classOrStyle/>
*FTLFreeMarker formInput
'password'
path:command.name
MapmapkeysvaluesMapmapMapSortedMap TreeMapComparatorcommons-collectionsLinkedHashMapLinkedMap
radiobuttonscheckboxes"<br>"
HTMLtextarea'rows="5"'style="border:1pxsolidsilver"'classOrStyleshowErrorsCSSspan<b></b>
FTLVTL
14.4.5.3.1.
<!--NameVTL-->
...Name:#springFormInput("command.name"
"")<br>#springShowErrors("<br>"
"")<br>
formInputpathcommand.namepathshowErrorspath——fieldshowErrorsCSSFreeMarkerVelocityFTL
<@spring.formInput"command.name"/>
<@spring.showErrors"<br>"/>
nameSpringHTML
Name:<inputtype="text"name="name"value=""
><br><b>required</b>
<br><br>
textarea
14.4.5.3.2.
HTMLformSingleSelect
formMultiSelect
formRadioButtons
formCheckboxesMapFTLradioformbacking object'London''cityMap'
...Town:<@spring.formRadioButtons
"command.address.town",cityMap,""
/><br><br>
radio—— cityMap""cityMapkey-valueStringmapkeyvalueHTML
Town:<inputtype="radio"name="address.town"
value="London">London<inputtype="radio"
name="address.town"value="Paris"
checked="checked">Paris<input
type="radio"name="address.town"value="New
York">NewYork
map
protectedMapreferenceData(HttpServletRequest
request)throwsException{MapcityMap=new
LinkedHashMap();cityMap.put("LDN","London");
cityMap.put("PRS","Paris");cityMap.put("NYC",
"NewYork");
Mapm=newHashMap();m.put("cityMap",
cityMap);returnm;}
radio
Town:<inputtype="radio"name="address.town"
value="LDN">London<inputtype="radio"
name="address.town"value="PRS"
checked="checked">Paris<input
type="radio"name="address.town"value="NYC">
NewYork
14.4.5.4.HTMLXHTMLHTML 4.01Springweb.xmlHTMLXHTMLHTMLXHTMLmodel/contextxhtmlComplianttrue
##forVelocity..#set($springXhtmlCompliant=true)
<#--forFreeMarker--><#assign
xhtmlCompliant=trueinspring>
SpringXHTMLHTML
<#--HTML-->
<#assignhtmlEscape=trueinspring><#--
nextfieldwilluseHTMLescaping-->
<@spring.formInput"command.name"/>
<#assignhtmlEscape=falseinspring><#--
allfuturefieldswillbeboundwithHTMLescaping
off-->
14.5.XSLTXSLTXMLwebview XMLXMLXSLTXSLT
14.5.1.Spring ControllermodelmapXSLTMVCControllerXSLTXML
14.5.1.1.BeanSpringdispatcherservlet ViewResolver
<beanid="homeController"class="xslt.HomeController"/>
“”
14.5.1.2.MVCAbstractControllerhandler
protectedModelAndViewhandleRequestInternal(
HttpServletRequestrequest,
HttpServletResponseresponse)throwsException{
Mapmap=newHashMap();
ListwordList=newArrayList();
wordList.add("hello");
wordList.add("world");
map.put("wordList",wordList);
returnnewModelAndView("home",map);
}
XSLTSpring MVC XSLTXMLXML
14.5.1.3.XML
XML org.springframework.web.servlet.view.xslt.AbstractXsltView
createXsltSource(..)smodelMap
packagexslt;
//importsomittedforbrevity
publicclassHomePageextendsAbstractXsltView{
protectedSourcecreateXsltSource(Mapmodel,StringrootName,HttpServletRequest
request,HttpServletResponseresponse)throwsException{
Documentdocument=DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
Elementroot=document.createElement(rootName);
Listwords=(List)model.get("wordList");
for(Iteratorit=words.iterator();it.hasNext();){
StringnextWord=(String)it.next();
ElementwordNode=document.createElement("word");
TexttextNode=document.createTextNode(nextWord);
wordNode.appendChild(textNode);
root.appendChild(wordNode);
}
returnnewDOMSource(root);
}
}
name/valuepairsname="myParam">defaultValue</xsl:param>getParameters() MapSpring1.1JSTLVelocityXSLT Springorg.springframework.web.servlet.view.xslt.FormatHelperJavadoc
14.5.1.4.“”views.propertiesxmlXMLVelocity
home.class=xslt.HomePage
home.stylesheetLocation=/WEB-INF/xsl/home.xslt
home.root=words
'.class' HomePageXMLHTML '.root'XML createXsltSource(..)
14.5.1.5.XSLT 'views.properties'
<?xmlversion="1.0"encoding="utf-8"?>
<xsl:stylesheetversion="1.0"xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:outputmethod="html"omit-xml-declaration="yes"/>
<xsl:templatematch="/">
<html>
<head><title>Hello!</title></head>
<body>
<h1>MyFirstWords</h1>
<xsl:apply-templates/>
</body>
</html>
</xsl:template>
<xsl:templatematch="word">
<xsl:value-ofselect="."/><br/>
</xsl:template>
</xsl:stylesheet>
14.5.2.WARWAR
ProjectRoot|+-WebContent|+-WEB-INF|+-classes|
||+-xslt|||||+-HomePageController.class||+-
HomePage.class|||+-views.properties|+-lib|||
+-spring.jar|+-xsl|||+-home.xslt|+-
frontcontroller-servlet.xml
classpathXMLXSLTJDK1.4J2EE
14.6.PDF/Excel
14.6.1.HTML SpringPDFExcelExcel'poi'classpathPDFiText.jarSpring
14.6.2.XSLT XSLTcontrollerPDFExcelOpenOffice
14.6.2.1.view.propertiesxml
home.class=xslt.HomePage
home.stylesheetLocation=/WEB-INF/xsl/home.xslt
home.root=words
xl.class=excel.HomePage
pdf.class=pdf.HomePage
'url'
14.6.2.2.ControllercontrollerXSLT URLSpirng
14.6.2.3.ExcelXSLT Excelorg.springframework.web.servlet.view.document.AbstractExcelView
POIorg.springframework.web.servlet.view.document.AbstractJExcelView
JExcelApi buildExcelDocument
POIExcel
packageexcel;
//importsomittedforbrevity
publicclassHomePageextendsAbstractExcelView
{
protectedvoidbuildExcelDocument(Mapmodel,
HSSFWorkbookwb,HttpServletRequestreq,
HttpServletResponseresp)throwsException{
HSSFSheetsheet;HSSFRowsheetRow;HSSFCell
cell;
//Gotothefirstsheet//getSheetAt:onlyif
wbiscreatedfromanexistingdocument//sheet
=wb.getSheetAt(0);sheet=
wb.createSheet("Spring");
sheet.setDefaultColumnWidth((short)12);
//writeatextatA1cell=getCell(sheet,0,
0);setText(cell,"Spring-Exceltest");
Listwords=(List)model.get("wordList");for
(inti=0;i<words.size();i++){cell=
getCell(sheet,2+i,0);setText(cell,(String)
words.get(i));
}}}
JExcelApiExcel
packageexcel;
//importsomittedforbrevity
publicclassHomePageextendsAbstractExcelView
{
protectedvoidbuildExcelDocument(Mapmodel,
WritableWorkbookwb,HttpServletRequestrequest,
HttpServletResponseresponse)throwsException{
WritableSheetsheet=wb.createSheet("Spring");
sheet.addCell(newLabel(0,0,"Spring-Excel
test");
Listwords=(List)model.get("wordList");for
(inti=-;i<words.size();i++){
sheet.addCell(newLabel(2+i,0,
(String)words.get(i));}}}
APIJExcelApi JExcelApicontroller xl returnnewModelAndView("xl",map);
Excel
14.6.2.4.PDFPDForg.springframework.web.servlet.view.document.AbstractPdfView
buildPdfDocument()
packagepdf;
//importsomittedforbrevity
publicclassPDFPageextendsAbstractPdfView{
protectedvoidbuildPdfDocument(Mapmodel,
Documentdoc,PdfWriterwriter,
HttpServletRequestreq,HttpServletResponse
resp)throwsException{
Listwords=(List)model.get("wordList");
for(inti=0;i<words.size();i++)doc.add(
newParagraph((String)words.get(i)));
}}
controller pdf returnnewModelAndView("pdf",map);
14.7.JasperReportsJasperReports(http://jasperreports.sourceforge.net) XML4CSVExcelHTMLPDF
14.7.1.JasperReports0.6.1 JasperReports:
BeanShell
CommonsBeanUtils
CommonsCollections
CommonsDigester
CommonsLogging
iText
POIJasperReportsJAXP
14.7.2. ApplicationContextJasperReports ViewResolver
14.7.2.1. ViewResolver
ResourceBundleViewResolver
<beanid="viewResolver"class="org.springframework.web.servlet.view.ResourceBundleViewResolver">
<propertyname="basename"value="views"/>
</bean>
ResourceBundleViewResolverbasename
14.7.2.2. View
SpringJasperReportsJasperReports
14.2.JasperReportsViewClasses
JasperReportsCsvView CSV
JasperReportsHtmlView HTML
JasperReportsPdfView PDF
JasperReportsXlsView MicrosoftExcel
JasperReportsMultiFormatView 14.7.2.4“JasperReportsMultiFormatView”
simpleReport.class=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper
simpleReport JasperReportsPdfViewPDFurl
14.7.2.3.JasperReports .jrxml.jrxml .jasper SpringSpring
14.7.2.4. JasperReportsMultiFormatView
JasperReportsMultiFormatViewJasperReportsview-JasperReportsMultiFormatView
JasperReportsMultiFormatViewformatkeydiscriminatorkeyJasperReportsMultiFormatViewmappingkeyformatkeymappingkeymodelformatkeymappingkey
publicModelAndView
handleSimpleReportMulti(HttpServletRequestrequest,
HttpServletResponseresponse)throwsException{
Stringuri=request.getRequestURI();Stringformat
=uri.substring(uri.lastIndexOf(".")+1);
Mapmodel=getModel();model.put("format",format);
returnnewModelAndView("simpleReportMulti",model);
}
mappingkeyrequestURIformatkey format
key JasperReportsMultiFormatView formatKey
JasperReportsMultiFormatViewmappingkey
14.3.JasperReportsMultiFormatViewMappingKey
MappingKey ViewClasscsv JasperReportsCsvView
html JasperReportsHtmlView
pdf JasperReportsPdfView
xls JasperReportsXlsView
/foo/myReport.pdf JasperReportsPdfViewJasperReportsMultiFormatViewformatMappingsmappingkey
14.7.3. ModelAndView
Spring JasperReportsreportdatasourcereportparametersmodel Map
modelkey JRDataSourceCollectionmodel
privateMapgetModel(){Mapmodel=newHashMap();
CollectionbeanData=getBeanData();
model.put("myBeanData",beanData);returnmodel;}
JRDataSourceCollection reportDataKey
Collection JRBeanCollectionDataSource
privateMapgetModel(){Mapmodel=newHashMap();
CollectionbeanData=getBeanData();Collection
someData=getSomeData();model.put("myBeanData",
beanData);model.put("someData",someData);return
model;}
Collectionmodel
simpleReport.class=org.springframework.web.servlet.view.jasperreports.JasperReportsPdfView
simpleReport.url=/WEB-INF/reports/DataSourceReport.jasper
simpleReport.reportDataKey=myBeanData
Spring JRDataSourceCollectionmodel
14.7.4.JasperReports
14.7.4.1.Spring
<parametername="ProductsSubReport"
class="net.sf.jasperreports.engine.JasperReport"/>
<subreport><reportElement
isPrintRepeatedValues="false"x="5"y="25"
width="325"height="20"
isRemoveLineWhenBlank="true"
backcolor="#ffcc99"/><subreportParameter
name="City">
<subreportParameterExpression><![CDATA[$F{city}]]></subreportParameterExpression>
</subreportParameter>
<dataSourceExpression><![CDATA[$P{SubReportData}]]></dataSourceExpression>
<subreportExpression
class="net.sf.jasperreports.engine.JasperReport">
<![CDATA[$P{ProductsSubReport}]]></subreportExpression>
</subreport>
ProductsSubReport net.sf.jasperreports.engine.JasperReportsJaspersubReportUrlsSpringJasperReports
<propertyname="subReportUrls">
<map><entrykey="ProductsSubReport"
value="/WEB-INF/reports/subReportChild.jrxml"/>
</map></property>
MapkeyURL SpringkeyJasperReports
14.7.4.2.SpringModelAndView subReportDataKeys
<propertyname="subReportDataKeys"
value="SubReportData"/>
key ModelAndViewkey
14.7.5.ExporterexporterPDF Springexportervalue
<beanid="htmlReport"
class="org.springframework.web.servlet.view.jasperreports.JasperReportsHtmlView">
<propertyname="url"
value="/WEB-INF/reports/simpleReport.jrxml"/>
<propertyname="exporterParameters"><map>
<entry
key="net.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER">
<value>FooterbySpring!
</td><td
width="50%">&nbsp;
</td></tr>
</table></body></html>
</value></entry></map>
</property></bean>
JasperReportsHtmlView exporternet.sf.jasperreports.engine.export.JRHtmlExporterParameter.HTML_FOOTER
HTML
15Web
15.1.15.2.15.3.JavaServerFaces
15.3.1.DelegatingVariableResolver15.3.2.FacesContextUtils
15.4.Struts15.4.1.ContextLoaderPlugin15.4.2.ActionSupportClasses
15.5.Tapestry15.5.1.Springbeans
15.6.WebWork15.7.
SpringWebFlowSpringWebFlowSWFWeb
SWFservletportletSpringMVCStrutsJSF SWFSWFSWF SpringWebFlow
15.1.Spring StrutsJSFTapestry WebWorkSpring Spring WebSpringWebSpringMVC WebStrutsSpringSpringSpringWebJavaJavaWeb...JavaWeb SpringWebWebStruts WebStruts Web 15.7“”
15.2.Web WebSpringSpringWebSpringMVCSpring“” Web... “businnescontext”context Web“presentationcontext” Spring“businessbeans”...Web web.xml ContextLoaderListener
<context-param/> SpringXML<listener/>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
ListenersServletAPI2.3listenerServlet2.4 Servlet2.2 ContextLoaderServlet
<context-param/>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext*.xml</param-value>
</context-param>
contextConfigLocationcontext ContextLoaderListenerINF/applicationContext.xml contextSpringbeanWebApplicationContextWeb ServletContextJavaWebServletAPI ContextLoaderListener
ApplicationContext
WebApplicationContextctx=WebApplicationContextUtils.getWebApplicationContext(servletContext);
WebApplicationContextUtils ServletContextgetWebApplicationContext()
WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE NullPointerExceptions getRequiredWebApplicationContext()
ApplicationContext WebApplicationContext beanbeanbeanSpring
15.3.JavaServerFacesJavaServerFaces(JSF)WebDelegatingVariableResolver
15.3.1.DelegatingVariableResolverSpringJSFWeb DelegatingVariableResolver
Resolver faces-context.xml <faces-config/><application/> <variable-resolver/> SpringDelegatingVariableResolver
<faces-config>
<application>
<variable-resolver>org.springframework.web.jsf.DelegatingVariableResolver</variable-resolver>
<locale-config>
<default-locale>en</default-locale>
<supported-locale>en</supported-locale>
<supported-locale>es</supported-locale>
</locale-config>
<message-bundle>messages</message-bundle>
</application>
</faces-config>
DelegatingVariableResolverJSF Spring“businesscontext”WebApplicationContextJSFbeanJSFbean faces-config.xml #{userManager}
“businesscontext”bean
<managed-bean>
<managed-bean-name>userList</managed-bean-name>
<managed-bean-class>com.whatever.jsf.UserList</managed-bean-class>
<managed-bean-scope>request</managed-bean-scope>
<managed-property>
<property-name>userManager</property-name>
<value>#{userManager}</value>
</managed-property>
</managed-bean>
15.3.2.FacesContextUtils faces-config.xmlbean VariableResolver
FacesContextUtils WebApplicationContextUtils
ServletContext
ApplicationContextctx=FacesContextUtils.getWebApplicationContext(FacesContext.getCurrentInstance());
DelegatingVariableResolverJSFSpring
15.4.StrutsStruts JavaWeb20016 JSP/ServletStrutsSpring
SpringActionbean ContextLoaderPluginSpringcontextSpring ActionSupport getWebApplicationContext()Springbean
15.4.1.ContextLoaderPluginContextLoaderPlugin Struts1.1+Struts ActionServletSpring context context WebApplicationContextContextLoaderListener contextServlet ActionServletweb.xml <servlet-name>action</servlet-name>/WEB-INF/action-servlet.xmlXML struts-config.xmlplug-ins
<plug-inclassName="org.springframework.web.struts.ContextLoaderPlugIn"/>
context‘ contextConfigLocation’
<plug-inclassName="org.springframework.web.struts.ContextLoaderPlugIn">
<set-propertyproperty="contextConfigLocation"
value="/WEB-INF/action-servlet.xml,/WEB-INF/applicationContext.xml"/>
</plug-in>
StrutsTestCaseListener plug-in bug “” struts-config.xmlSping ActionSpring(1.1.3)
Spring DelegatingRequestProcessorStruts RequestProcessor
<action-mapping> type DelegatingActionProxy
action-servlet.xmlAction struts-config.xmlservlet.xmlAction action-mapping“path”bean“name”
struts-config.xml
<actionpath="/users".../>
action-servlet.xmlActionbean“/users”
<beanname="/users".../>
15.4.1.1.DelegatingRequestProcessor struts-config.xml DelegatingRequestProcessor<controller>“processorClass” <action-mapping>
<controller>
<set-propertyproperty="processorClass"
value="org.springframework.web.struts.DelegatingRequestProcessor"/>
</controller>
ActionSpingcontext
<actionpath="/user"type="com.whatever.struts.UserAction"/>
<actionpath="/user"/>
Struts modulesbeanmodule Action<actionpath="/user"/>module“admin” <bean
name="/admin/user"/>bean
Struts Tiles <controller>DelegatingTilesRequestProcessor
15.4.1.2.DelegatingActionProxy RequestProcessor DelegatingRequestProcessor
DelegatingTilesRequestProcessor DelegatingActionProxy action-mapping
<actionpath="/user"type="org.springframework.web.struts.DelegatingActionProxy"
name="userForm"scope="request"validate="false"parameter="method">
<forwardname="list"path="/userList.jsp"/>
<forwardname="edit"path="/userForm.jsp"/>
</action>
action-servlet.xmlbean RequestProcessor
DelegatingActionProxy
ActionSpringcontextSpringbean Actionbean scope="prototype"
<beanname="/user"scope="prototype"autowire="byName"
class="org.example.web.UserAction"/>
15.4.2.ActionSupportClasses WebApplicationContextUtils ServletContextWebApplicationContext Spring ActionStrutsSpring ActionSupportActionSupport getWebApplicationContext()Action
publicclassUserActionextendsDispatchActionSupport{
publicActionForwardexecute(ActionMappingmapping,
ActionFormform,
HttpServletRequestrequest,
HttpServletResponseresponse)throwsException{
if(log.isDebugEnabled()){
log.debug("entering'delete'method...");
}
WebApplicationContextctx=getWebApplicationContext();
UserManagermgr=(UserManager)ctx.getBean("userManager");
//talktomanagerforbusinesslogic
returnmapping.findForward("success");
}
}
SpringStrutsAction-Spring SupportActionSupport,
DispatchActionSupport,
LookupDispatchActionSupportand
MappingDispatchActionSupport.
15.5.Tapestry Tapestry...“TapestryWebJava TapestryJavaServletAPI Servlet ”Spring Web Tapestry WebSpringJ2EE
TapestrySpring J2EETapestry UISpringTapestry []
“TapestryListener ”...TapestrySpring-TapestryTapestry SpringbeanTapestryTapestry HowardM.LewisShip
15.5.1.SpringbeansSpringXML
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!--theDataSource-->
<beanid="dataSource"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="java:DefaultDS"/>
</bean>
<beanid="hibSessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<propertyname="dataSource"ref="dataSource"/>
</bean>
<beanid="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager"/>
<beanid="mapper"
class="com.whatever.dataaccess.mapper.hibernate.MapperImpl">
<propertyname="sessionFactory"ref="hibSessionFactory"/>
</bean>
<!--(transactional)AuthenticationService-->
<beanid="authenticationService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<propertyname="transactionManager"ref="transactionManager"/>
<propertyname="target">
<beanclass="com.whatever.services.service.user.AuthenticationServiceImpl">
<propertyname="mapper"ref="mapper"/>
</bean>
</property>
<propertyname="proxyInterfacesOnly"value="true"/>
<propertyname="transactionAttributes">
<value>
*=PROPAGATION_REQUIRED
</value>
</property>
</bean>
<!--(transactional)UserService-->
<beanid="userService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<propertyname="transactionManager"ref="transactionManager"/>
<propertyname="target">
<beanclass="com.whatever.services.service.user.UserServiceImpl">
<propertyname="mapper"ref="mapper"/>
</bean>
</property>
<propertyname="proxyInterfacesOnly"value="true"/>
<propertyname="transactionAttributes">
<value>
*=PROPAGATION_REQUIRED
</value>
</property>
</bean>
</beans>
Tapestrybean Spring TapestryauthenticationService userService bean
AuthenticationService UserServiceWeb SpringWebApplicationContextUtils.getApplicationContext(servletContext)applicationcontextservletContextJ2EEServlet UserService
WebApplicationContextappContext=WebApplicationContextUtils.getApplicationContext(
getRequestCycle().getRequestContext().getServlet().getServletContext());
UserServiceuserService=(UserService)appContext.getBean("userService");
...somecodewhichusesUserService
...Tapestry
Tapestry<4.0Tapestry4.0+BeansTapestry-Tapestry4.0+”
15.5.1.1.SpringBeansTapestryTapestry ServletContext ApplicationContextApplicationContext ServletContextWebApplicationContextUtils.getApplicationContext(servletContext)TapestryIEngine ApplicationContext
packagecom.whatever.web.xportal;
import...
publicclassMyEngineextendsorg.apache.tapestry.engine.BaseEngine{
publicstaticfinalStringAPPLICATION_CONTEXT_KEY="appContext";
/**
*@seeorg.apache.tapestry.engine.AbstractEngine#setupForRequest(org.apache.tapestry.request.RequestContext)
*/
protectedvoidsetupForRequest(RequestContextcontext){
super.setupForRequest(context);
//insertApplicationContextinglobal,ifnotthere
Mapglobal=(Map)getGlobal();
ApplicationContextac=(ApplicationContext)global.get(APPLICATION_CONTEXT_KEY);
if(ac==null){
ac=WebApplicationContextUtils.getWebApplicationContext(
context.getServlet().getServletContext()
);
global.put(APPLICATION_CONTEXT_KEY,ac);
}
}
}
Springapplicationcontext“appContext”TapestryTapestryIEngineTapestry
file:xportal.application:
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEapplicationPUBLIC
"-//ApacheSoftwareFoundation//TapestrySpecification3.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
<application
name="WhateverxPortal"
engine-class="com.whatever.web.xportal.MyEngine">
</application>
15.5.1.2.*.page*.jwcproperty-specificationbeanbean
<property-specificationname="userService"
type="com.whatever.services.service.user.UserService">
global.appContext.getBean("userService")
</property-specification>
<property-specificationname="authenticationService"
type="com.whatever.services.service.user.AuthenticationService">
global.appContext.getBean("authenticationService")
</property-specification>
property-specificationOGNLcontextbean
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEpage-specificationPUBLIC
"-//ApacheSoftwareFoundation//TapestrySpecification3.0//EN"
"http://jakarta.apache.org/tapestry/dtd/Tapestry_3_0.dtd">
<page-specificationclass="com.whatever.web.xportal.pages.Login">
<property-specificationname="username"type="java.lang.String"/>
<property-specificationname="password"type="java.lang.String"/>
<property-specificationname="error"type="java.lang.String"/>
<property-specificationname="callback"type="org.apache.tapestry.callback.ICallback"persistent="yes"/>
<property-specificationname="userService"
type="com.whatever.services.service.user.UserService">
global.appContext.getBean("userService")
</property-specification>
<property-specificationname="authenticationService"
type="com.whatever.services.service.user.AuthenticationService">
global.appContext.getBean("authenticationService")
</property-specification>
<beanname="delegate"class="com.whatever.web.xportal.PortalValidationDelegate"/>
<beanname="validator"class="org.apache.tapestry.valid.StringValidator"lifecycle="page">
<set-propertyname="required"expression="true"/>
<set-propertyname="clientScriptingEnabled"expression="true"/>
</bean>
<componentid="inputUsername"type="ValidField">
<static-bindingname="displayName"value="Username"/>
<bindingname="value"expression="username"/>
<bindingname="validator"expression="beans.validator"/>
</component>
<componentid="inputPassword"type="ValidField">
<bindingname="value"expression="password"/>
<bindingname="validator"expression="beans.validator"/>
<static-bindingname="displayName"value="Password"/>
<bindingname="hidden"expression="true"/>
</component>
</page-specification>
15.5.1.3.Javagetter
//ourUserServiceimplementation;willcomefrompagedefinition
publicabstractUserServicegetUserService();
//ourAuthenticationServiceimplementation;willcomefrompagedefinition
publicabstractAuthenticationServicegetAuthenticationService();
Java
packagecom.whatever.web.xportal.pages;
/**
*Allowstheusertologin,byprovidingusernameandpassword.
*Aftersuccessfullyloggingin,acookieisplacedontheclientbrowser
*thatprovidesthedefaultusernameforfuturelogins(thecookie
*persistsforaweek).
*/
publicabstractclassLoginextendsBasePageimplementsErrorProperty,PageRenderListener{
/**thekeyunderwhichtheauthenticateduserobjectisstoredinthevisitas*/
publicstaticfinalStringUSER_KEY="user";
/**Thenameofthecookiethatidentifiesauser**/
privatestaticfinalStringCOOKIE_NAME=Login.class.getName()+".username";
privatefinalstaticintONE_WEEK=7*24*60*60;
publicabstractStringgetUsername();
publicabstractvoidsetUsername(Stringusername);
publicabstractStringgetPassword();
publicabstractvoidsetPassword(Stringpassword);
publicabstractICallbackgetCallback();
publicabstractvoidsetCallback(ICallbackvalue);
publicabstractUserServicegetUserService();
publicabstractAuthenticationServicegetAuthenticationService();
protectedIValidationDelegategetValidationDelegate(){
return(IValidationDelegate)getBeans().getBean("delegate");
}
protectedvoidsetErrorField(StringcomponentId,Stringmessage){
IFormComponentfield=(IFormComponent)getComponent(componentId);
IValidationDelegatedelegate=getValidationDelegate();
delegate.setFormComponent(field);
delegate.record(newValidatorException(message));
}
/**
*Attemptstologin.
*<p>
*Iftheusernameisnotknown,orthepasswordisinvalid,thenanerror
*messageisdisplayed.
**/
publicvoidattemptLogin(IRequestCyclecycle){
Stringpassword=getPassword();
//Doalittleextraworktoclearoutthepassword.
setPassword(null);
IValidationDelegatedelegate=getValidationDelegate();
delegate.setFormComponent((IFormComponent)getComponent("inputPassword"));
delegate.recordFieldInputValue(null);
//Anerror,fromavalidationfield,mayalreadyhaveoccurred.
if(delegate.getHasErrors()){
return;
}
try{
Useruser=getAuthenticationService().login(getUsername(),getPassword());
loginUser(user,cycle);
}
catch(FailedLoginExceptionex){
this.setError("Loginfailed:"+ex.getMessage());
return;
}
}
/**
*Setsupthe{@linkUser}astheloggedinuser,creates
*acookiefortheirusername(forsubsequentlogins),
*andredirectstotheappropriatepage,or
*aspecifiedpage).
**/
publicvoidloginUser(Useruser,IRequestCyclecycle){
Stringusername=user.getUsername();
//Getthevisitobject;thiswilllikelyforcethe
//creationofthevisitobjectandanHttpSession
Mapvisit=(Map)getVisit();
visit.put(USER_KEY,user);
//Afterloggingin,gototheMyLibrarypage,unlessotherwisespecified
ICallbackcallback=getCallback();
if(callback==null){
cycle.activate("Home");
}
else{
callback.performCallback(cycle);
}
IEngineengine=getEngine();
Cookiecookie=newCookie(COOKIE_NAME,username);
cookie.setPath(engine.getServletPath());
cookie.setMaxAge(ONE_WEEK);
//Recordtheuser'susernameinacookie
cycle.getRequestContext().addCookie(cookie);
engine.forgetPage(getPageName());
}
publicvoidpageBeginRender(PageEventevent){
if(getUsername()==null){
setUsername(getRequestCycle().getRequestContext().getCookieValue(COOKIE_NAME));
}
}
}
15.5.1.4.SpringBeansTapestry-Tapestry4.0+Tapestry4.0+SpringbeansTapestry Web WEB-INF/lib Spring SpringbeansTapestryJava5annotationSpring userService authenticationService
Login
packagecom.whatever.web.xportal.pages;
publicabstractclassLoginextendsBasePageimplementsErrorProperty,PageRenderListener{
@InjectObject("spring:userService")
publicabstractUserServicegetUserService();
@InjectObject("spring:authenticationService")
publicabstractAuthenticationServicegetAuthenticationService();
}
...HiveMind ServletContext SpringHiveMind
<?xmlversion="1.0"?>
<moduleid="com.javaforge.tapestry.spring"version="0.1.1">
<service-pointid="SpringApplicationInitializer"
interface="org.apache.tapestry.services.ApplicationInitializer"
visibility="private">
<invoke-factory>
<constructclass="com.javaforge.tapestry.spring.SpringApplicationInitializer">
<set-objectproperty="beanFactoryHolder"
value="service:hivemind.lib.DefaultSpringBeanFactoryHolder"/>
</construct>
</invoke-factory>
</service-point>
<!--HooktheSpringsetupintotheoverallapplicationinitialization.-->
<contribution
configuration-id="tapestry.init.ApplicationInitializers">
<commandid="spring-context"
object="service:SpringApplicationInitializer"/>
</contribution>
</module>
Java5annotationJava5annotationTapestry XML.page .jwc
<injectproperty="userService"object="spring:userService"/>
<injectproperty="authenticationService"object="spring:authenticationService"/>
SpringbeanTapestryTapestryJ2EE
15.6.WebWork WebWork...“WebWorkJavaWebJavaBean ”WebWorkWebWebWork IoC WebWorkAction“wiring”WebWork2.2WebWorkIoC IoCSpringWebWork2.2IoC SpringSpringWebWorkDRY-Don'tRepeatYourselfSpring-WebWorkWebWork WebWorkwiki Spring-WebWork
Spring-WebWorkWebWorkSpringSpring-WebWork
15.7.Web
TheStrutshomepage
TheJSFhomepage
TheTapestryhomepage
TheWebWorkhomepageWeb
TheStrutsTIprojectwiki
16PortletMVC
16.1.16.1.1.-MVCC16.1.2.-MVCV16.1.3.WebBean
16.2.DispatcherPortlet16.3.ViewRendererServlet16.4.
16.4.1.AbstractController PortletContentGenerator
16.4.2.16.4.3.Command16.4.4.PortletWrappingController
16.5.16.5.1.PortletModeHandlerMapping16.5.2.ParameterHandlerMapping16.5.3.PortletModeParameterHandlerMapping16.5.4. HandlerInterceptors16.5.5.HandlerInterceptorAdapter16.5.6.ParameterMappingInterceptor
16.6.16.7.Multipart
16.7.1. PortletMultipartResolver
16.7.2.16.8.16.9.Portlet
JSR-168JavaPortletPortletSUNJSR-168
SpringWebFlowSpringWebFlowSWFWeb
SWFservletportletSpringMVCStrutsJSF SWFSWFSWF SpringWebFlow
16.1.SpringServletWebJSR-168Portlet PortletMVCWebMVC 13 WebMVCframeworkWeb14
SpringMVCSpringPorletMVCJSR-168PortletPorletServletPortlet “”JSR-168 PortletMVCServlet- PortletSpringPortletMVCServletMVC PortletMVC ServletAbstractControllerhandleRequestInternal(..)PortletAbstractController
handleActionRequestInternal(..)
handleRenderRequestInternal(..)
DispatcherPortlet WebDispatcherServletPortletMVC-portal/portlet SpringSpring(DispatcherPortlet DispatcherServlet
16.1.1.-MVCC Controller
voidhandleActionRequest(request,response)
ModelAndViewhandleRenderRequest(request,response)
AbstractControllerSimpleFormController
16.1.2.-MVCVServlet ViewRendererServletServletServletPortlet JSPVelocity
16.1.3.WebBean
SpringPortletMVCWebBeanBeanHTTP HTTPWebApplicationContext 3.4.4“” Bean
SpringSpringPortletMVCSpringPortletMVCsamples/petportal'petportal'
16.2.DispatcherPortletPortletMVCWebMVCPortlet PorltetSpringDispatcherPortletSpring ApplicationContextDispatcherPortletPortlet Web portlet.xml
<portlet>
<portlet-name>sample</portlet-name>
<portlet-class>org.springframework.web.portlet.DispatcherPortlet</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>view</portlet-mode>
</supports>
<portlet-info>
<title>SamplePortlet</title>
</portlet-info>
</portlet>
DispatcherPortlet
PortletMVC DispatcherPortlet WebApplicationContext
WebApplicationContextBean PortletBeanBeanPortlet DispatcherPortletWeb WEB-INF [portlet-name]-portlet.xml
BeanDispatcherPortlet PortletSpringDispatcherPortletBean SpringBeanBeanWebApplicationContext Bean
16.1.WebApplicationContextBean
(16.5“” ) Portlet
(16.4“” )MVC Bean
(16.6“” )
(multipart) (16.7“Multipart” ) HTML
(16.8“” )
DispatcherPortlet DispatcherPortlet
PortletRequest.getLocale() Locale
ActionRequest“Multipart”
()
WebApplicationContext
WebApplicationContextportlet.xmlContextPortlet Spring DispatcherPortlet
16.2.DispatcherPortlet
contextClassWebApplicationContextPortletcontextXmlPortletApplicationContext
contextConfigLocationcontext( contextClass) context()beancontext
namespaceWebApplicationContext [portlet-name]-
portlet
viewRendererUrlViewRendererServletURL DispatcherPortlet
( 16.3“ ViewRendererServlet”)
16.3.ViewRendererServletPortletMVCWebMVCSpringWebMVC PortletResponse HttpServletRequest/HttpServletResponse View
render DispatcherPortletservlet ViewRendererServlet
DispatcherPortlet web.xmlweb ViewRendererServlet
<servlet>
<servlet-name>ViewRendererServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.ViewRendererServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ViewRendererServlet</servlet-name>
<url-pattern>/WEB-INF/servlet/view</url-pattern>
</servlet-mapping>
DispatcherPortlet
WebApplicationContext DispatcherServlet
WEB_APPLICATION_CONTEXT_ATTRIBUTEkey
ModelView ViewRendererServlet
PortletRequestDispatcher ViewRendererServlet/WEB-
INF/servlet/viewURLincludeViewRendererServlet Viewrender
DispatcherPortletviewRendererUrl ViewRendererServletURL
16.4.PortletMVCWebMVCPortletMVC org.springframework.web.portlet.mvc.Controller
publicinterfaceController{
/**
*ProcesstherenderrequestandreturnaModelAndViewobjectwhichthe
*DispatcherPortletwillrender.
*/
ModelAndViewhandleRenderRequest(RenderRequestrequest,RenderResponseresponse)
throwsException;
/**
*Processtheactionrequest.Thereisnothingtoreturn.
*/
voidhandleActionRequest(ActionRequestrequest,ActionResponseresponse)
throwsException;
}
Portlet ControllerPortlet PortletMVC-SpringWebMVC
16.4.1. AbstractControllerPortletContentGenerator
ControllerSpringPortlet ControllerAbstractControllerSpringApplicationContext
16.3.AbstractController
requireSession Controllersession SessionRequiredException
synchronizeSessionsessionhandleActionRequestInternal(..) session
renderWhenMinimized portlet truefalseportlet
cacheSeconds portlet -1
requireSession cacheSeconds AbstractController
PortletContentGeneratorAbstractControllerhandleActionRequestInternal(ActionRequest, ActionResponse)
handleRenderRequestInternal(RenderRequest,RenderResponse)
ModelAndView handleRenderRequestInternal
handleActionRequestInternal(..) handleRenderRequestInternal(..)PortletExceptionJSR-168API GenericPortletwebcontext
packagesamples;
importjavax.portlet.RenderRequest;
importjavax.portlet.RenderResponse;
importorg.springframework.web.portlet.mvc.AbstractController;
importorg.springframework.web.portlet.ModelAndView;
publicclassSampleControllerextendsAbstractController{
publicModelAndViewhandleRenderRequestInternal(
RenderRequestrequest,
RenderResponseresponse)throwsException{
ModelAndViewmav=newModelAndView("foo");
mav.addObject("message","HelloWorld!");
returnmav;
}
}
<beanid="sampleController"class="samples.SampleController">
<propertyname="cacheSeconds"value="120"/>
</bean>
webcontext
16.4.2.AbstractControllerSpringPortletMVCMVCParameterizableViewController webcontextPortletModeNameViewController PortletPortletView
PortletMode.VIEW“View”
16.4.3.CommandSpringPortletMVCSpringWebMVC commandcontrollersPortletRequest Command
AbstractCommandController-Command
AbstractFormController-AbstractFormController (
SimpleFormController- AbstractFormControllercommandSimpleFormController command
AbstractWizardFormController– AbstractFormController
command javadoc
16.4.4.PortletWrappingControllerportlet DispatcherPortletController
<beanid="wrappingController"
class="org.springframework.web.portlet.mvc.PortletWrappingController">
<propertyname="portletClass"value="sample.MyPortlet"/>
<propertyname="portletName"value="my-portlet"/>
<propertyname="initParameters">
<value>
config=/WEB-INF/my-portlet-config.xml
</value>
</property>
</bean>
portlet JSR-168MyFacesOpenSessionInViewInterceptor
16.5.portlet“”“” DispatcherPortlet DispatcherPortletHandlerMapping HandlerExecutionChainHandlerExecutionChain DispatcherPortletchain( )SpringWebMVCURLPortletURL portletSpringPortletMVC AbstractHandlerMapping
interceptors: HandlerInterceptor 16.5.4 “
HandlerInterceptors”
defaultHandler:
order:Springorder ( org.springframework.core.Ordered)
lazyInitHandlers:Lazy (prototypelazy)false
16.5.1.PortletModeHandlerMappingportlet'view','edit','help'
<beanid="portletModeHandlerMapping"
class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
<propertyname="portletModeMap">
<map>
<entrykey="view"value-ref="viewHandler"/>
<entrykey="edit"value-ref="editHandler"/>
<entrykey="help"value-ref="helpHandler"/>
</map>
</property>
</bean>
16.5.2.ParameterHandlerMappingportlet keyParameterHandlerMapping 'action'
bean
<beanid="parameterHandlerMapping"
class="org.springframework.web.portlet.handler.ParameterHandlerMapping”>
<propertyname="parameterMap">
<map>
<entrykey="add"value-ref="addItemHandler"/>
<entrykey="edit"value-ref="editItemHandler"/>
<entrykey="delete"value-ref="deleteItemHandler"/>
</map>
</property>
</bean>
16.5.3.PortletModeParameterHandlerMapping PortletModeParameterHandlerMapping portlet“action” parameterNameportlet portletportletbean
<beanid="portletModeParameterHandlerMapping"
class="org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping">
<propertyname="portletModeParameterMap">
<map>
<entrykey="view"><!--'view'portletmode-->
<map>
<entrykey="add"value-ref="addItemHandler"/>
<entrykey="edit"value-ref="editItemHandler"/>
<entrykey="delete"value-ref="deleteItemHandler"/>
</map>
</entry>
<entrykey="edit"><!--'edit'portletmode-->
<map>
<entrykey="prefs"value-ref="prefsHandler"/>
<entrykey="resetPrefs"value-ref="resetPrefsHandler"/>
</map>
</entry>
</map>
</property>
</bean>
PortletModeHandlerMapping
16.5.4. HandlerInterceptorsSpring principalSpringorg.springframework.web.portlet HandlerInterceptor servlet(preHandle)( postHandle)( afterCompletion)preHandle true
postHandleRenderRequest ActionRequestRenderRequest preHandle
afterCompletion
16.5.5.HandlerInterceptorAdapterservletportlet HandlerInterceptor HandlerInterceptorAdapter
16.5.6.ParameterMappingInterceptorPortletParameterMappingInterceptor ParameterHandlerMapping
PortletModeParameterHandlerMappingRenderRequest ActionRequest preHandleActionResponsesetRenderParameter
16.6.SpringPortleMVCSprintWebMVCViewViewResolver
portletHTML JSP/JSTLVelocityFreeMakerXSLTportlet
portletHTTP(ActionResponsesendRedirect(..)portal)PortletMVCRedirectView'redirect:'
PortletMVC'forward:' portletURLURLURL
JSPSpringTaglibSpringtaglibServletportlet
16.7.MultipartSpringPortletMVCWebMVCmultipartportletPortletMultipartResolvermultipartorg.springframework.web.portlet.multipart SpringPortletMultipartResolver CommonsFileUploadSpringPortletmultipartmultipart webcontextmultipartDispatcherPortletmultipart multipartcontextPortletMultipartResolver multipart
PortletMultipartResolverbean id" PortletMultipartResolver" PortletMultipartResolver
DispatcherPortlet PortletMultipartResolvermultipart
16.7.1. PortletMultipartResolver
CommonsPortletMultipartResolver
<beanid="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver">
<!--byte-->
<propertyname="maxUploadSize"value="100000"/>
</bean>
multipartjar CommonsMultipartResolver
1.1 CommonsFileUploadJSR-168PortletMVCmultipart DispatcherPortlet
ActionRequest MultipartActionRequest MultipartActionRequest
multipartmultipartRenderRequestmultipart ActionRequest
16.7.2. PortletMultipartResolver SpringJSP/HTML
<h1>Pleaseuploadafile</h1>
<formmethod="post"action="<portlet:actionURL/>"enctype="multipart/form-data">
<inputtype="file"name="file"/>
<inputtype="submit"/>
</form>
bean“File” byte[](enctype="multipart/form-data"
() ByteArrayMultipartFileEditorbean
<beanid="portletMultipartResolver"
class="org.springframework.web.portlet.multipart.CommonsPortletMultipartResolver"/>
<beanid="portletModeHandlerMapping"
class="org.springframework.web.portlet.handler.PortletModeHandlerMapping">
<propertyname="portletModeMap">
<map>
<entrykey="view"value-ref="fileUploadController"/>
</map>
</property>
</bean>
<beanid="fileUploadController"class="examples.FileUploadController">
<propertyname="commandClass"value="examples.FileUploadBean"/>
<propertyname="formView"value="fileuploadform"/>
<propertyname="successView"value="confirmation"/>
</bean>
publicclassFileUploadControllerextendsSimpleFormController{
publicvoidonSubmitAction(
ActionRequestrequest,
ActionResponseresponse,
Objectcommand,
BindExceptionerrors)
throwsException{
//castthebean
FileUploadBeanbean=(FileUploadBean)command;
//let'sseeifthere'scontentthere
byte[]file=bean.getFile();
if(file==null){
//hmm,that'sstrange,theuserdidnotuploadanything
}
//dosomethingwiththefilehere
}
protectedvoidinitBinder(
PortletRequestrequest,PortletRequestDataBinderbinder)
throwsException{
//toactuallybeabletoconvertMultipartinstancetobyte[]
//wehavetoregisteracustomeditor
binder.registerCustomEditor(byte[].class,newByteArrayMultipartFileEditor());
//nowSpringknowshowtohandlemultipartobjectandconvert
}
}
publicclassFileUploadBean{
privatebyte[]file;
publicvoidsetFile(byte[]file){
this.file=file;
}
publicbyte[]getFile(){
returnfile;
}
}
FileUploadBean byte[]
publicclassFileUploadControllerextendsSimpleFormController{
publicvoidonSubmitAction(
ActionRequestrequest,
ActionResponseresponse,
Objectcommand,
BindExceptionerrors)throwsException{
//castthebean
FileUploadBeanbean=(FileUploadBean)command;
//let'sseeifthere'scontentthere
Stringfile=bean.getFile();
if(file==null){
//hmm,that'sstrange,theuserdidnotuploadanything
}
//dosomethingwiththefilehere
}
protectedvoidinitBinder(
PortletRequestrequest,PortletRequestDataBinderbinder)throwsException{
//toactuallybeabletoconvertMultipartinstancetoaString
//wehavetoregisteracustomeditor
binder.registerCustomEditor(String.class,
newStringMultipartFileEditor());
//nowSpringknowshowtohandlemultipartobjectsandconvert
}
}
publicclassFileUploadBean{
privateStringfile;
publicvoidsetFile(Stringfile){
this.file=file;
}
publicStringgetFile(){
returnfile;
}
}
MultipartFile
publicclassFileUploadControllerextendsSimpleFormController{
publicvoidonSubmitAction(
ActionRequestrequest,
ActionResponseresponse,
Objectcommand,
BindExceptionerrors)throwsException{
//castthebean
FileUploadBeanbean=(FileUploadBean)command;
//let'sseeifthere'scontentthere
MultipartFilefile=bean.getFile();
if(file==null){
//hmm,that'sstrange,theuserdidnotuploadanything
}
//dosomethingwiththefilehere
}
}
publicclassFileUploadBean{
privateMultipartFilefile;
publicvoidsetFile(MultipartFilefile){
this.file=file;
}
publicMultipartFilegetFile(){
returnfile;
}
}
16.8.WebMVCPortletMVC HandlerExceptionResolver PortletMVCSimpleMappingExceptionResolver
16.9.PortletSpringPortletMVCJSR-168Portletportal/portletservletWeb PortletservletWebPortletPortletServletContextServlet portlet.xml
JSR-168Portlet “”PortletPortletPortletPortlet web.xml PortletServletServletWebPortletServletPortletWebPortletPortletJSPTabportalPortlet ()portalPortlet web.xmlportal ViewRendererServletPortlet
IV.SpringFrameworkJ2EE
17 SpringWeb
18 EnterpriseJavaBeans(EJB)
19 JMS(JavaMessageService)
20 JMX
21 JCACCI
22 Spring
23 Spring(Scheduling)(ThreadPooling)
24
25
17.SpringWeb17.1.17.2.RMI
17.2.1.RmiServiceExporter17.2.2.
17.3.HessianBurlapHTTP17.3.1.Hessianco.DispatcherServlet17.3.2.HessianServiceExporterbean17.3.3.17.3.4.Burlap17.3.5.HessianBurlapHTTPBasic
17.4.HTTP17.4.1.Exposingtheserviceobject17.4.2.
17.5.WebServices17.5.1.JAX-RPCservletweb17.5.2.JAX-RPCweb17.5.3.JAX-RPCBean17.5.4.JAX-RPC17.5.5.JAX-WSservletweb17.5.6.JAX-WSweb17.5.7.SpringJAX-WSRI17.5.8.JAX-WSweb17.5.9.XFireWeb
17.6.JMS17.6.1.17.6.2.
17.7.17.8.
18.EnterpriseJavaBeans(EJB)18.1.18.2.EJB
18.2.1.18.2.2.SessionBean(SLSB)18.2.3.SLSB18.2.4.AccessingEJB2.xSLSBsversusEJB3SLSBs
18.3.SpringEJB18.3.1.EJB2.xbaseclasses18.3.2.EJB3
19.JMS(JavaMessageService)19.1.19.2.SpringJMS
19.2.1.JmsTemplate19.2.2.19.2.3.19.2.4.19.2.5.
19.3.19.3.1.19.3.2.SessionCallback ProducerCallback
19.4.19.4.1.19.4.2.-POJO19.4.3.SessionAwareMessageListener19.4.4.MessageListenerAdapter19.4.5.
19.5.JCA19.6.JMS
20.JMX20.1.20.2.BeanJMX
20.2.1.MBeanServer20.2.2.MBeanServer20.2.3.MBean20.2.4.MBean20.2.5.
20.3.Bean20.3.1.MBeanInfoAssembler20.3.2.20.3.3.JDK5.020.3.4.20.3.5.AutodetectCapableMBeanInfoAssembler20.3.6.Java20.3.7.MethodNameBasedMBeanInfoAssembler
20.4.BeanObjectName20.4.1. PropertiesProperties
20.4.2.MetadataNamingStrategy20.4.3.<context:mbean-export/>
20.5.JSR-16020.5.1.20.5.2.20.5.3.Burlap/Hessian/SOAPJMX
20.6.MBean20.7.
20.7.1.20.7.2.
20.8.
21.JCACCI21.1.21.2.CCI
21.2.1.21.2.2.SpringConnectionFactory21.2.3.CCI21.2.4.CCI
21.3.SpringCCI21.3.1.21.3.2.CciTemplate21.3.3.DAO21.3.4.21.3.5.21.3.6.CCIConnectionInteraction21.3.7.CciTemplate
21.4.CCI21.4.1.MappingRecordOperation21.4.2.MappingCommAreaOperation21.4.3.21.4.4.21.4.5.MappingRecordOperation21.4.6.MappingCommAreaOperation
21.5.
22.Spring22.1.22.2.Spring
22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator
22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.
23.Spring(Scheduling)(ThreadPooling)23.1.23.2.OpenSymphonyQuartz
23.2.1.JobDetailBean23.2.2. MethodInvokingJobDetailFactoryBean
23.2.3.triggersSchedulerFactoryBean23.3.JDKTimer
23.3.1.timers23.3.2. MethodInvokingTimerTaskFactoryBean
23.3.3. TimerFactoryBean
23.4.SpringTaskExecutor23.4.1.TaskExecutor23.4.2.TaskExecutor23.4.3.TaskExecutor
24.24.1.24.2.24.3.bean
24.3.1.24.3.2.JRubybeans24.3.3.Groovybeans24.3.4.BeanShellbeans
24.4.24.4.1.SpringMVC24.4.2.Validator
24.5.Bitsandbobs24.5.1.AOP-bean24.5.2.
24.6.
25.25.1.25.2.Spring25.3.
25.3.1.@Required
25.3.2.Spring@Annotations25.4.JakartaCommonsAttributes25.5.SpringAOP
25.5.1.25.5.2.
17SpringWeb
17.1.17.2.RMI
17.2.1.RmiServiceExporter17.2.2.
17.3.HessianBurlapHTTP17.3.1.Hessianco.DispatcherServlet17.3.2.HessianServiceExporterbean17.3.3.17.3.4.Burlap17.3.5.HessianBurlapHTTPBasic
17.4.HTTP17.4.1.Exposingtheserviceobject17.4.2.
17.5.WebServices17.5.1.JAX-RPCservletweb17.5.2.JAX-RPCweb17.5.3.JAX-RPCBean17.5.4.JAX-RPC17.5.5.JAX-WSservletweb17.5.6.JAX-WSweb17.5.7.SpringJAX-WSRI17.5.8.JAX-WSweb17.5.9.XFireWeb
17.6.JMS17.6.1.17.6.2.
17.7.17.8.
17.1.SpringSpringSpringPOJOSpring
RMI RmiProxyFactoryBean RmiServiceExporterSpringRMIjava.rmi.Remotejava.rmi.RemoteExceptionRMIJava
SpringHTTPSpringHTTPJavaJavaRMIHttpInvokerProxyFactoryBean HttpInvokerServiceExporter
Hessian HessianProxyFactoryBean HessianServiceExporter
CauchoHTTPBurlapBurlapCauchoXMLHessianSpringBurlapProxyFactoryBean BurlapServiceExporter
JAXRPCSpringJAX-RPCJ2EE1.4'swwebserviceAPIWebservicesJAX-WS.Spring(JavaEE5Java6JAX-RPC)WebServices
JMS.JmsInvokerServiceExporterJmsInvokerProxyFactoryBeanJMS.
Spring
publicclassAccountimplementsSerializable{
privateStringname;
publicStringgetName();
publicvoidsetName(Stringname){
this.name=name;
}
}
publicinterfaceAccountService{
publicvoidinsertAccount(Accountaccount);
publicListgetAccounts(Stringname);
}
publicinterfaceRemoteAccountServiceextendsRemote{
publicvoidinsertAccount(Accountaccount)throwsRemoteException;
publicListgetAccounts(Stringname)throwsRemoteException;
}
//
publicclassAccountServiceImplimplementsAccountService{
publicvoidinsertAccount(Accountacc){
//……
}
publicListgetAccounts(Stringname){
//……
}
}
RMIRMIHessian
17.2.RMISpringRMIRMISpringRMIEJBRMISpring
17.2.1. RmiServiceExporter
RmiServiceExporterAccountServiceRMI RmiProxyFactoryBeanRMIRMI RmiServiceExporterRMIRMISpring
<beanid="accountService"class="example.AccountServiceImpl">
<!--DAO-->
</bean>
RmiServiceExporter
<beanclass="org.springframework.remoting.rmi.RmiServiceExporter">
<!--bean-->
<propertyname="serviceName"value="AccountService"/>
<propertyname="service"ref="accountService"/>
<propertyname="serviceInterface"value="example.AccountService"/>
<!--1199-->
<propertyname="registryPort"value="1199"/>
</bean>
RMIRMI rmi://HOST:1199/AccountServiceURL
servicePort(0)..
17.2.2.AccountServiceaccount
publicclassSimpleObject{
privateAccountServiceaccountService;
publicvoidsetAccountService(AccountServiceaccountService){
this.accountService=accountService;
}
}
Spring
<beanclass="example.SimpleObject">
<propertyname="accountService"ref="accountService"/>
</bean>
<beanid="accountService"class="org.springframework.remoting.rmi.RmiProxyFactoryBean">
<propertyname="serviceUrl"value="rmi://HOST:1199/AccountService"/>
<propertyname="serviceInterface"value="example.AccountService"/>
</bean>
accountSpring RmiServiceExporteraccount RmiProxyFactoryBean
17.3.HessianBurlapHTTPHessianHTTPCaucho http://www.caucho.comHessian
17.3.1.Hessianco. DispatcherServlet
HessianServletHTTPSpringWebMVC DispatcherServletServletServlet web.xml
<servlet>
<servlet-name>remoting</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>remoting</servlet-name>
<url-pattern>/remoting/*</url-pattern>
</servlet-mapping>
SpringDispatcherServlet 'WEB-INF''remoting-servlet.xml'(servlet)SpringSpring HttpRequestHandlerServlet 'WEB-
INF/applicationContext.xml'exporterservletexporterbeanservletexporterbean
17.3.2. HessianServiceExporterbean remoting-servlet.xml HessianServiceExporter
<beanid="accountService"class="example.AccountServiceImpl">
<!--anyadditionalproperties,maybeaDAO?-->
</bean>
<beanname="/AccountService"class="org.springframework.remoting.caucho.HessianServiceExporter">
<propertyname="service"ref="accountService"/>
<propertyname="serviceInterface"value="example.AccountService"/>
</bean>
BeanNameUrlHandlerMappingURLbeanURL
http://HOST:8080/remoting/AccountService, HessianServiceExporter( 'WEB-INF/applicationContext.xml'):
<beanname="accountExporter"class="org.springframework.remoting.caucho.HessianServiceExporter">
<propertyname="service"ref="accountService"/>
<propertyname="serviceInterface"value="example.AccountService"/>
</bean>
, 'web.xml'exporterservletexporterrequest/remoting/AccountServiceservletexporterbean
<servlet>
<servlet-name>accountExporter</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>accountExporter</servlet-name>
<url-pattern>/remoting/AccountService</url-pattern>
</servlet-mapping>
17.3.3.HessianProxyFactoryBeanRMIbeanbean SimpleObject
AccountServiceaccounts
<beanclass="example.SimpleObject">
<propertyname="accountService"ref="accountService"/>
</bean>
<beanid="accountService"class="org.springframework.remoting.caucho.HessianProxyFactoryBean">
<propertyname="serviceUrl"value="http://remotehost:8080/remoting/AccountService"/>
<propertyname="serviceInterface"value="example.AccountService"/>
</bean>
17.3.4.BurlapBurlapXMLHessianHessian Hessian Burlap
17.3.5.HessianBurlapHTTPBasicHessianBurlapHTTPBasicHTTPHTTPServer web.xml
Hessian/BurlapProxyFactoryBeanJDBC
<beanclass="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping">
<propertyname="interceptors"ref="authorizationInterceptor"/>
</bean>
<beanid="authorizationInterceptor"
class="org.springframework.web.servlet.handler.UserRoleAuthorizationInterceptor">
<propertyname="authorizedRoles"value="administrator,operator"/>
</bean>
BeanNameUrlHandlerMappingbean
http://acegisecurity.sourceforge.netAcegiSecuritySystemforSpring
17.4.HTTPBurlapHessianSpringHTTPJavaHTTPHessianBurlapHTTP
SpringJ2SECommonsHttpClientHTTPjakarta.apache.org/commons/httpclient
17.4.1.Exposingtheserviceobject
17.4.1.ExposingtheserviceobjectHTTPHessianBurlapHessian HessianServiceExporterSpringHTTPorg.springframework.remoting.httpinvoker.HttpInvokerServiceExporter
SpringWebMVCDispatcherServletAccountService()dispatcher
<beanname="/AccountService"class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<propertyname="service"ref="accountService"/>
<propertyname="serviceInterface"value="example.AccountService"/>
</bean>
Hessianexporter DispatcherServlet
,( 'WEB-INF/applicationContext.xml')HttpInvokerServiceExporter:
<beanname="accountExporter"class="org.springframework.remoting.httpinvoker.HttpInvokerServiceExporter">
<propertyname="service"ref="accountService"/>
<propertyname="serviceInterface"value="example.AccountService"/>
</bean>
, 'web.xml'exporterservletexporterbean:
<servlet>
<servlet-name>accountExporter</servlet-name>
<servlet-class>org.springframework.web.context.support.HttpRequestHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>accountExporter</servlet-name>
<url-pattern>/remoting/AccountService</url-pattern>
</servlet-mapping>
17.4.2.HessianBurlapSpringHTTPPOSTURL
<beanid="httpInvokerProxy"class="org.springframework.remoting.httpinvoker.HttpInvokerProxyFactoryBean">
<propertyname="serviceUrl"value="http://remotehost:8080/remoting/AccountService"/>
<propertyname="serviceInterface"value="example.AccountService"/>
</bean>
HTTP HttpInvokerProxyJ2SEHTTPhttpInvokerRequestExecutorCommonsHttpClient
<propertyname="httpInvokerRequestExecutor">
<beanclass="org.springframework.remoting.httpinvoker.CommonsHttpInvokerRequestExecutor"/>
</property>
17.5.WebServicesSpringJavawebAPI:
JAX-RPCweb
JAX-RPCweb
JAX-WSweb
JAX-WSweb
2JavawebAPIs?JAX-RPC1.1J2EE1.4webAPIRPCJavaEE5JAX-WS2.0JAX-WS2.0annotationJAX-WS2.1Java6(SunJDK1.6.0_04SunJDK1.6.0JAX-WS2.0)JDKHTTPSpringJavawebAPIJDK1.4/J2EE1.4JAX-RPCJavaEE5/Java6JAX-WSJava5J2EE1.4JAX-WSproviderJ2EE
SpringCoreJAX-RPCandJAX-WSSpringportfolio SpringWebServicesweb-web XFireSpringSpringbeanweb
17.5.1.JAX-RPCservletwebSpringJAX-RPCservlet- ServletEndpointSupport. AccountService
Spring ServletEndpointSupport
/**
*JAX-RPCcompliantRemoteAccountServiceimplementationthatsimplydelegates
*totheAccountServiceimplementationintherootwebapplicationcontext.
*
*ThiswrapperclassisnecessarybecauseJAX-RPCrequiresworkingwithdedicated
*endpointclasses.Ifanexistingserviceneedstobeexported,awrapperthat
*extendsServletEndpointSupportforsimpleapplicationcontextaccessis
*thesimplestJAX-RPCcompliantway.
*
*Thisistheclassregisteredwiththeserver-sideJAX-RPCimplementation.
*InthecaseofAxis,thishappensin"server-config.wsdd"respectivelyvia
*deploymentcalls.Thewebserviceenginemanagesthelifecycleofinstances
*ofthisclass:ASpringapplicationcontextcanjustbeaccessedhere.
*/importorg.springframework.remoting.jaxrpc.ServletEndpointSupport;
publicclassAccountServiceEndpointextendsServletEndpointSupportimplementsRemoteAccountService{
privateAccountServicebiz;
protectedvoidonInit(){
this.biz=(AccountService)getWebApplicationContext().getBean("accountService");
}
publicvoidinsertAccount(Accountacc)throwsRemoteException{
biz.insertAccount(acc);
}
publicAccount[]getAccounts(Stringname)throwsRemoteException{
returnbiz.getAccounts(name);
}
}
AccountServletEndpointSpringwebSpringAxis AxisServlet
'web.xml' 'server-config.wsdd'JPetStore OrderServiceAxisWeb
17.5.2.JAX-RPCwebSpringbeanWeb LocalJaxRpcServiceFactoryBeanJaxRpcPortProxyFactoryBeanJAX-RPC AccountService
SpringWeb-Spring
<beanid="accountWebService"class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
<propertyname="serviceInterface"value="example.RemoteAccountService"/>
<propertyname="wsdlDocumentUrl"value="http://localhost:8080/account/services/accountService?WSDL"/>
<propertyname="namespaceUri"value="http://localhost:8080/account/services/accountService"/>
<propertyname="serviceName"value="AccountService"/>
<propertyname="portName"value="AccountPort"/>
</bean>
serviceInterface wsdlDocumentUrlWSDLURL.SpringJAX-RPCnamespaceUri.wsdltargetNamespace serviceName.wsdlportName.wsdl
web RemoteAccountServicebeanSpring
<beanid="client"class="example.AccountClientImpl">
...
<propertyname="service"ref="accountWebService"/>
</bean>
RemoteExceptionweb
publicclassAccountClientImpl{
privateRemoteAccountServiceservice;
publicvoidsetService(RemoteAccountServiceservice){
this.service=service;
}
publicvoidfoo(){
try{
service.insertAccount(...);
}
catch(RemoteExceptionex){
//ouch
}
}
}
RemoteExceptionSpringRemoteExceptionRMI
<beanid="accountWebService"class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean">
<propertyname="serviceInterface"value="example.AccountService"/>
<propertyname="portInterface"value="example.RemoteAccountService"/>
</bean>
serviceInterfaceRMIRMI portInterface java.rmi.RemoteException:
publicclassAccountClientImpl{
privateAccountServiceservice;
publicvoidsetService(AccountServiceservice){
this.service=service;
}
publicvoidfoo(){
service.insertAccount(...);
}
}
"portInterface""serviceInterface" JaxRpcPortProxyFactoryBeanJAX-RPC"",RMIJavaJavawebJaxRpcPortProxyFactoryBeanjavadoc
17.5.3.JAX-RPCBeanTAccountbean
'server-config.wsdd'AxisbeanAxisbeanbean:
publicclassAxisPortProxyFactoryBeanextendsJaxRpcPortProxyFactoryBean{
protectedvoidpostProcessJaxRpcService(Serviceservice){
TypeMappingRegistryregistry=service.getTypeMappingRegistry();
TypeMappingmapping=registry.createTypeMapping();
registerBeanMapping(mapping,Account.class,"Account");
registry.register("http://schemas.xmlsoap.org/soap/encoding/",mapping);
}
protectedvoidregisterBeanMapping(TypeMappingmapping,Classtype,Stringname){
QNameqName=newQName("http://localhost:8080/account/services/accountService",name);
mapping.register(type,qName,
newBeanSerializerFactory(type,qName),
newBeanDeserializerFactory(type,qName));
}
}
17.5.4.JAX-RPCjavax.rpc.xml.handler.Handler WebSOAP Handler
jaxrpc.jarjavax.rpc.xml.handler.GenericHandler
publicclassAccountHandlerextendsGenericHandler{
publicQName[]getHeaders(){
returnnull;
}
publicbooleanhandleRequest(MessageContextcontext){
SOAPMessageContextsmc=(SOAPMessageContext)context;
SOAPMessagemsg=smc.getMessage();
try{
SOAPEnvelopeenvelope=msg.getSOAPPart().getEnvelope();
SOAPHeaderheader=envelope.getHeader();
...
}
catch(SOAPExceptionex){
thrownewJAXRPCException(ex);
}
returntrue;
}
}
AccountHandlerJAX-RPC handleRequest(..)SpringSpring postProcessJaxRpcService(..)
publicclassAccountHandlerJaxRpcPortProxyFactoryBeanextendsJaxRpcPortProxyFactoryBean{
protectedvoidpostProcessJaxRpcService(Serviceservice){
QNameport=newQName(this.getNamespaceUri(),this.getPortName());
Listlist=service.getHandlerRegistry().getHandlerChain(port);
list.add(newHandlerInfo(AccountHandler.class,null,null));
logger.info("RegisteredJAX-RPCAccountHandleronport"+port);
}
}
Springbean:
<beanid="accountWebService"class="example.AccountHandlerJaxRpcPortProxyFactoryBean">
...
</bean>
17.5.5.JAX-WSservletwebSpringJAX-WS servlet - SpringBeanAutowiringSupportAccountService
Spring SpringBeanAutowiringSupportSpring2.5 @Autowired
Springbean
/**
*JAX-WScompliantAccountServiceimplementationthatsimplydelegates
*totheAccountServiceimplementationintherootwebapplicationcontext.
*
*ThiswrapperclassisnecessarybecauseJAX-WSrequiresworkingwithdedicated
*endpointclasses.Ifanexistingserviceneedstobeexported,awrapperthat
*extendsSpringBeanAutowiringSupportforsimpleSpringbeanautowiring(through
*the@Autowiredannotation)isthesimplestJAX-WScompliantway.
*
*Thisistheclassregisteredwiththeserver-sideJAX-WSimplementation.
*InthecaseofaJavaEE5server,thiswouldsimplybedefinedasaservlet
*inweb.xml,withtheserverdetectingthatthisisaJAX-WSendpointandreacting
*accordingly.TheservletnameusuallyneedstomatchthespecifiedWSservicename.
*
*Thewebserviceenginemanagesthelifecycleofinstancesofthisclass.
*Springbeanreferenceswilljustbewiredinhere.
*/importorg.springframework.web.context.support.SpringBeanAutowiringSupport;
@WebService(serviceName="AccountService")
publicclassAccountServiceEndpointextendsSpringBeanAutowiringSupport{
@Autowired
privateAccountServicebiz;
@WebMethod
publicvoidinsertAccount(Accountacc){
biz.insertAccount(acc);
}
@WebMethod
publicAccount[]getAccounts(Stringname){
returnbiz.getAccounts(name);
}
}
SpringSpring AccountServletEndpointwebJavaEE5JAX-WSservletJavaEE5web
17.5.6.JAX-WSwebSun JDK 1.6JAX-WS provider HTTPwebSpringSimpleJaxWsServiceExporterSpringl@WebServicebeanJAX-WSJDK1.6HTTPSpringbeanJAX-WSSpringSpring @Autowired
<beanclass="org.springframework.remoting.jaxws.SimpleJaxWsServiceExporter">
<propertyname="baseAddress"value="http://localhost:9999/"/>
</bean>
<beanid="accountServiceEndpoint"class="example.AccountServiceEndpoint">
...
</bean>
...
AccountServiceEndpointSpring SpringBeanAutowiringSupport
Springbean-Spring
@WebService(serviceName="AccountService")
publicclassAccountServiceEndpoint{
@Autowired
privateAccountServicebiz;
@WebMethod
publicvoidinsertAccount(Accountacc){
biz.insertAccount(acc);
}
@WebMethod
publicAccount[]getAccounts(Stringname){
returnbiz.getAccounts(name);
}
}
17.5.7.SpringJAX-WSRISunJAX-WSRIGlassFish,SpringJAX-WSCommonsJAX-WSSpringbean-Servlet JavaEE5EEwebTomcatJAX-WSRIservletSpring web.xmlJAX-WSservletJavaEE5()servletSpringbean( @Autowired)https://jax-ws-commons.dev.java.net/spring/
17.5.8.JAX-WSwebJAX-RPCSpring2beanJAX-WS web LocalJaxWsServiceFactoryBean
JaxWsPortProxyFactoryBeanJAX-WS AccountService
<beanid="accountWebService"class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
<propertyname="serviceInterface"value="example.AccountService"/>
<propertyname="wsdlDocumentUrl"value="http://localhost:8080/account/services/accountService?WSDL"/>
<propertyname="namespaceUri"value="http://localhost:8080/account/services/accountService"/>
<propertyname="serviceName"value="AccountService"/>
<propertyname="portName"value="AccountPort"/>
</bean>
serviceInterface wsdlDocumentUrlWSDLURL.SpringJAX-RPCnamespaceUri.wsdltargetNamespace serviceName.wsdlportName.wsdlweb AccountServicebeanSpring
<beanid="client"class="example.AccountClientImpl">
...
<propertyname="service"ref="accountWebService"/>
</bean>
web
publicclassAccountClientImpl{
privateAccountServiceservice;
publicvoidsetService(AccountServiceservice){
this.service=service;
}
publicvoidfoo(){
service.insertAccount(...);
}
}
: JAX-WS @WebService,@SOAPBindingJavaJAX-WSJAX-WS
17.5.9.XFireWebXFireCodehausSOAPXFireXFirecontextcontextRemoteExporterbean WebApplicationContext DispatcherServlet
WebApplicationContext
<servlet>
<servlet-name>xfire</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
XFirecontext ContextLoaderListener ContextLoaderServlet
contextConfigLocations
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>classpath:org/codehaus/xfire/spring/xfire.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
Servlet /*XFireServletbeanXFire 'xfire-servlet.xml'
<beans>
<beanname="/Echo"class="org.codehaus.xfire.spring.remoting.XFireExporter">
<propertyname="serviceInterface"value="org.codehaus.xfire.spring.Echo"/>
<propertyname="serviceBean">
<beanclass="org.codehaus.xfire.spring.EchoImpl"/>
</property>
<!--theXFirebeanisdefinedinthexfire.xmlfile-->
<propertyname="xfire"ref="xfire"/>
</bean>
</beans>
XFireWSDLXFireXFireSpring docs.codehaus.org/display/XFIRE/Spring
17.6.JMSJMSSpringJMS- SessionThefollowinginterfaceisusedonboththeserverandtheclientside.
packagecom.foo;
publicinterfaceCheckingAccountService{
publicvoidcancelAccount(LongaccountId);
}
packagecom.foo;
publicclassSimpleCheckingAccountServiceimplementsCheckingAccountService{
publicvoidcancelAccount(LongaccountId){
System.out.println("Cancellingaccount["+accountId+"]");
}
}
JMSbean
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanid="connectionFactory"class="org.apache.activemq.ActiveMQConnectionFactory">
<propertyname="brokerURL"value="tcp://ep-t43:61616"/>
</bean>
<beanid="queue"class="org.apache.activemq.command.ActiveMQQueue">
<constructor-argvalue="mmm"/>
</bean>
</beans>
17.6.1.JmsInvokerServiceExporter
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanid="checkingAccountService"
class="org.springframework.jms.remoting.JmsInvokerServiceExporter">
<propertyname="serviceInterface"value="com.foo.CheckingAccountService"/>
<propertyname="service">
<beanclass="com.foo.SimpleCheckingAccountService"/>
</property>
</bean>
<beanclass="org.springframework.jms.listener.SimpleMessageListenerContainer">
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="destination"ref="queue"/>
<propertyname="concurrentConsumers"value="3"/>
<propertyname="messageListener"ref="checkingAccountService"/>
</bean>
</beans>
packagecom.foo;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
publicclassServer{
publicstaticvoidmain(String[]args)throwsException{
newClassPathXmlApplicationContext(newString[]{"com/foo/server.xml","com/foo/jms.xml"});
}
}
17.6.2.(CheckingAccountService)beanJMS
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanid="checkingAccountService"
class="org.springframework.jms.remoting.JmsInvokerProxyFactoryBean">
<propertyname="serviceInterface"value="com.foo.CheckingAccountService"/>
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="queue"ref="queue"/>
</bean>
</beans>
packagecom.foo;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
publicclassClient{
publicstaticvoidmain(String[]args)throwsException{
ApplicationContextctx=newClassPathXmlApplicationContext(
newString[]{"com/foo/client.xml","com/foo/jms.xml"});
CheckingAccountServiceservice=(CheckingAccountService)ctx.getBean("checkingAccountService");
service.cancelAccount(newLong(10));
}
}
Lingo()“ ...POJOSpringJMS ”
17.7.InitializingBeanDisposableBean
17.8.
RMIHTTPHTTPRMIRMIRMI-JRMPJavaJava-to-JavaHTTPJavaSpringHTTPRMIHTTPHTTPJava-to-JavaSpringSpringRMIRMISpringJMSJMSbroker-JMSJMSJavaJMSXStreamRMIEJBRMIHTTPSpringSpring
18EnterpriseJavaBeans(EJB)
18.1.18.2.EJB
18.2.1.18.2.2.SessionBean(SLSB)18.2.3.SLSB18.2.4.AccessingEJB2.xSLSBsversusEJB3SLSBs
18.3.SpringEJB18.3.1.EJB2.xbaseclasses18.3.2.EJB3
18.1.SpringEJBSpringORMJDBCEJBEJBSpringEJBSpringEJBSpringEJBEJBEJBPOJO(Java)SpringEJBSpringSessionBean(SLSBs)
18.2.EJB
18.2.1.sessionbeanJNDI()EJBHome"create"()EJBEJBEJB(ServiceLocator)(BussinessDelegate)JNDI
EJB
EJBHomecreateEJBAPIEJB
EJBSpringSpringJNDI
18.2.2.SessionBean(SLSB)webEJBEJB(BusinessMethodsInterface)EJBEJBMyComponent
publicinterfaceMyComponent{
...
}
beanPOJO(Java)HomeBean SessionBean
MyComponentWebEJBJava MyComponentsetter
privateMyComponentmyComponent;
publicvoidsetMyComponent(MyComponentmyComponent){
this.myComponent=myComponent;
}
Spring() LocalStatelessSessionProxyFactoryBeanEJBmyComponent
<beanid="myComponent"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<propertyname="jndiName"value="myJndiComponent"/>
<propertyname="businessInterface"value="com.mycom.MyComponent"/>
</bean>
<beanid="myController"class="com.mycom.myController">
<propertyname="myComponent"ref="myComponent"/>
</bean>
SpringAOPAOPBean myComponentEJBEJBHomeJNDIEJBEJB classnameEJBThe myController bean definition sets the myComponent property of thecontrollerclasstotheEJBproxy.BeanmyController myComponentEJBSpring"jee" local-slsb
<jee:local-slsbid="myComponent"jndi-name="myJndiComponent"
business-interface="com.mycom.MyComponent"/>
<beanid="myController"class="com.mycom.myController">
<propertyname="myComponent"ref="myComponent"/>
</bean>
EJBWeb(EJB)EJBEJBPOJOBean myComponentJavaJNDIEJBEJBEJBEJBJNDIBean()Bean(XML ApplicationContext)EJBEJBJNDIinitEJBXMLSpringEJBAOP LocalSlsbInvokerInterceptor
18.2.3.SLSBEJBEJB SimpleRemoteStatelessSessionProxyFactoryBeanjee:remote-
slsbSpringSpringEJBSpringEJBEJBEJB RemoteExceptionEJBEJBSpringEJBEJB RemoteException
uncheckedexceptionRemoteAccessException RuntimeExceptionEJBEJB(POJO)
18.2.4.AccessingEJB2.xSLSBsversusEJB3SLSBs
SpringEJB2.XEJB3SessionbeanSpringEJBjee:remote-slsb EJB2.xhomeEJB3home:EJB3sessionbean JndiObjectFactoryBean/jee:jndi-lookupjee:local-slsb/jee:remote-slsbEJB
18.3.SpringEJB
18.3.1.EJB2.xbaseclassesSpringEJBEJBPOJOEJBSession BeanBeanAbstractStatelessSessionBeanAbstractStatefulSessionBean
AbstractMessageDrivenBean/AbstractJmsMessageDrivenBeanSessionbeanSessionBeanJava
publicinterfaceMyComponent{
publicvoidmyMethod(...);
...
}
Java
publicclassMyComponentImplimplementsMyComponent{
publicStringmyMethod(...){
...
}
...
}
SessionBean
publicclassMyFacadeEJBextendsAbstractStatelessSessionBean
implementsMyFacadeLocal{
privateMyComponentmyComp;
/**
*ObtainourPOJOserviceobjectfromtheBeanFactory/ApplicationContext
*@seeorg.springframework.ejb.support.AbstractStatelessSessionBean#onEjbCreate()
*/
protectedvoidonEjbCreate()throwsCreateException{
myComp=(MyComponent)getBeanFactory().getBean(
ServicesConstants.CONTEXT_MYCOMP_ID);
}
//forbusinessmethod,delegatetoPOJOserviceimpl.
publicStringmyFacadeMethod(...){
returnmyComp.myMethod(...);
}
...
}
SpringEJBSpringIoCEJB(POJO) BeanFactoryLocatorBeanFactoryLocatorContextJndiBeanFactoryLocatorJNDI
ApplicationContext(EJB java:comp/env/ejb/BeanFactoryPath
BeanFactoryApplicationContext setSessionContext()EJBsetBeanFactoryLocator()BeanFactoryLocatorJavaDocJavaDocSession Bean()EJB ejbPassivateejbActivate
unloadBeanFactory()loadBeanFactoryApplicationContextEJB ContextJndiBeanFactoryLocatorApplicationContextbeanbean(Hibernate SessionFactory)EJB ContextJndiBeanFactoryLocatorContextSingletonBeanFactoryLocatorEJBEJB
/**
*OverridedefaultBeanFactoryLocatorimplementation
*@seejavax.ejb.SessionBean#setSessionContext(javax.ejb.SessionContext)
*/
publicvoidsetSessionContext(SessionContextsessionContext){
super.setSessionContext(sessionContext);
setBeanFactoryLocator(ContextSingletonBeanFactoryLocator.getInstance());
setBeanFactoryLocatorKey(ServicesConstants.PRIMARY_CONTEXT_ID);
}
beanRefContext.xmlbeanEJBbean()bean(businessApplicationContext.xmlPOJObean)
<beans>
<beanid="businessBeanFactory"class="org.springframework.context.support.ClassPathXmlApplicationContext">
<constructor-argvalue="businessApplicationContext.xml"/>
</bean>
</beans>
ServicesConstants.PRIMARY_CONTEXT_ID
publicstaticfinalStringServicesConstants.PRIMARY_CONTEXT_ID="businessBeanFactory";
BeanFactoryLocatorContextSingletonBeanFactoryLocatorJavadoc
18.3.2.EJB3EJB3 Session beanMessage-Driven Bean, SpringEJBorg.springframework.ejb.interceptor.SpringBeanAutowiringInterceptor
Spring2.5 @AutowiredEJB @Interceptors
binding
@Stateless
@Interceptors(SpringBeanAutowiringInterceptor.class)
publicclassMyFacadeEJBimplementsMyFacadeLocal{
//automaticallyinjectedwithamatchingSpringbean
@Autowired
privateMyComponentmyComp;
//forbusinessmethod,delegatetoPOJOserviceimpl.
publicStringmyFacadeMethod(...){
returnmyComp.myMethod(...);
}
...
}
SpringBeanAutowiringInterceptorContextSingletonBeanFactoryLocatorbean beanRefContext.xml
beanRefContext.xml SpringBeanAutowiringInterceptor
getBeanFactoryLocatorKey
SpringBeanAutowiringInterceptor getBeanFactoryApplicationContext
19JMS(JavaMessageService)
19.1.19.2.SpringJMS
19.2.1.JmsTemplate19.2.2.19.2.3.19.2.4.19.2.5.
19.3.19.3.1.19.3.2.SessionCallback ProducerCallback
19.4.19.4.1.19.4.2.-POJO19.4.3.SessionAwareMessageListener19.4.4.MessageListenerAdapter19.4.5.
19.5.JCA19.6.JMS
JMS1.0.21.1JMS1.0.2/JMS1.0.2APIJMSAPIJMS1.1APIJMS1.1Session
JMS1.120024200311J2EE1.4J2EE1.3BEAWebLogic8.1IBMWebSphere5.1)JMS1.0.2
19.1.SpringJMSAPIJMSAPI1.0.21.1JMS JmsTemplateJavaEEBeanSpringPOJOMDPorg.springframework.jms.coreJMSJDBC JdbcTemplateJMSJMSSpringJMSJMSsessionorg.springframework.jms.supportJMSExceptionJMSExceptionjavax.jms.JMSExceptionUncategorizedJmsException
org.springframework.jms.support.converter MessageConverterJavaJMSorg.springframework.jms.support.destinationJMSJNDI
org.springframework.jms.connectionConnectionFactoryJMSSpring PlatformTransactionManager JmsTransactionManager
JMSSpring
19.2.SpringJMS
19.2.1.JmsTemplateJmsTemplate JmsTemplate JMS 1.1API JmsTemplate102 JMS1.0.2API JmsTemplate MessageCreatorJmsTemplateSessionJMSAPI SessionCallbackJMSsession ProducerCallbackSessionMessageProducerJMSAPIQOSQOS JmsTemplateQOSbean setReceiveTimeoutJMSConnectionFactoryQOS MessageProducer send(Destination
destination,Messagemessage)QOSJMSQOSJmsTemplate isExplicitQosEnabledtrueQOS
JmsTemplate JmsTemplateJmsTemplate ConnectionFactory
19.2.2.JmsTemplate ConnectionFactory ConnectionFactoryJMSJMSJMSSSLEJBJMSJMSrefEJB JmsTemplateConnectionFactorySpring ConnectionFactory SingleConnectionFactory
createConnection Connection close JmsTemplateSingleConnectionFactoryJNDI ConnectionFactory
19.2.3.JNDIJMSSpringJNDI JndiObjectFactoryBeanJMSJMS
JndiDestinationResolver JmsTemplateJndiDestinationResolverJNDI DynamicDestinationResolverJMSJMSJNDIAPI-JMS
TopicSession createTopic(StringtopicName) QueueSession
createQueue(StringqueueName) DynamicDestinationResolver
pubSubDomain JmsTemplateJMSfalse1.0.2JmsTemplate Queue Topic1.1JMS DestinationResolver
defaultDestination JmsTemplate
19.2.4.EJBJMSBeanMDBSpringPOJOMDPEJBSpringMDP 19.4.2“-POJO” JMSMDPMDPMDPJMSSpring AbstractMessageListenerContainer
19.2.4.1.SimpleMessageListenerContainerJMSsessionJMSJMSAPI
19.2.4.2.DefaultMessageListenerContainer SimpleMessageListenerContainerXAJtaTransactionManagerXAJMS
19.2.4.3.ServerSessionMessageListenerContainerJMSServerSessionPoolSPIJMSSession JMSServerSessionPoolSPI DefaultMessageListenerContainerSimpleMessageListenerContainer
19.2.5.Spring JmsTransactionManager JMS ConnectionFactory JMS 9
Spring JmsTransactionManager ConnectionFactoryConnection/Session JmsTemplateJavaEE SingleConnectionFactoryConnectionSessionSpringSingleConnectionFactoryJMSConnection Session,ActiveMQPooledConnectionFactoryJmsTemplate JtaTransactionManagerXAJMSConnectionFactory
JTAXAConnectionFactoryJ2EE/JMSJMSAPI Connection SessionJMSAPI SessionJMS JmsTemplate SessionTransacted
SessionAcknowledgeMode JmsTemplatePlatformTransactionManagerJMS Session
19.3.JmsTemplate javax.jms.DestinationJNDI1.0.2JMS
importjavax.jms.ConnectionFactory;
importjavax.jms.JMSException;
importjavax.jms.Message;
importjavax.jms.Queue;
importjavax.jms.Session;
importorg.springframework.jms.core.MessageCreator;
importorg.springframework.jms.core.JmsTemplate;
importorg.springframework.jms.core.JmsTemplate102;
publicclassJmsQueueSender{
privateJmsTemplatejmsTemplate;
privateQueuequeue;
publicvoidsetConnectionFactory(ConnectionFactorycf){
this.jmsTemplate=newJmsTemplate102(cf,false);
}
publicvoidsetQueue(Queuequeue){
this.queue=queue;
}
publicvoidsimpleSend(){
this.jmsTemplate.send(this.queue,newMessageCreator(){
publicMessagecreateMessage(Sessionsession)throwsJMSException{
returnsession.createTextMessage("helloqueueworld");
}
});
}
}
MessageCreator Session ConnectionFactory JmsTemplate
connectionFactory/queueBeanBeanFactoryJavaSpring JmsGatewaySupportJMSBeanJMS1.0.2 pubSubDomain
send(StringdestinationName,MessageCreatorcreator)JNDI destinationResolver JndiDestinationResolver JmsTemplate send(MessageCreatorc)
19.3.1.JmsTemplate Java JmsTemplate convertAndSend
receiveAndConvert MessageConverterJavaJMSSimpleMessageConverter String TextMessagebyte[] BytesMesssage
java.util.Map MapMessageJMSJMS MapMessageConverterJavaBean MapMessageXMLJAXBCastorXMLBeansXStream TextMessage
MessagePostProcessor java.util.Map
publicvoidsendWithConversion(){
Mapmap=newHashMap();
map.put("Name","Mark");
map.put("Age",newInteger(47));
jmsTemplate.convertAndSend("testQueue",map,newMessagePostProcessor(){
publicMessagepostProcessMessage(Messagemessage)throwsJMSException{
message.setIntProperty("AccountID",1234);
message.setJMSCorrelationID("123-00001");
returnmessage;
}
});
}
:
MapMessage={
Header={
...standardheaders...
CorrelationID={123-00001}
}
Properties={
AccountID={Integer:1234}
}
Fields={
Name={String:Mark}
Age={Integer:47}
}
}
19.3.2.SessionCallback ProducerCallback
sendJMS Session MessageProducer SessionCallbackProducerCallback JMS Session Session / MessageProducer
JmsTemplate execute()
19.4.
19.4.1.JMS receive(..) receiveTimeout
19.4.2.-POJOEJBBeanMDBPOJOMDPJMSMDPjavax.jms.MessageListener javax.jms.MessageListenerPOJO-MDP:
importjavax.jms.JMSException;
importjavax.jms.Message;
importjavax.jms.MessageListener;
importjavax.jms.TextMessage;
publicclassExampleListenerimplementsMessageListener{
publicvoidonMessage(Messagemessage){
if(messageinstanceofTextMessage){
try{
System.out.println(((TextMessage)message).getText());
}
catch(JMSExceptionex){
thrownewRuntimeException(ex);
}
}
else{
thrownewIllegalArgumentException("MessagemustbeoftypeTextMessage");
}
}
}
MessageListenerSping DefaultMessageListenerContainer
<!--thisistheMessageDrivenPOJO(MDP)-->
<beanid="messageListener"class="jmsexample.ExampleListener"/>
<!--andthisisthemessagelistenercontainer-->
<beanid="jmsContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="destination"ref="destination"/>
<propertyname="messageListener"ref="messageListener"/>
</bean>
SpringJavadoc
19.4.3.SessionAwareMessageListenerSessionAwareMessageListenerSpringJMSMessageListenerMessageJMSSession
packageorg.springframework.jms.listener;
publicinterfaceSessionAwareMessageListener{
voidonMessage(Messagemessage,Sessionsession)throwsJMSException
}
MDP onMessage(Message,Session) SessionMDPJMSMessageListener )SpringMDP MessageListenerSessionAwareMessageListener SessionAwareMessageListenerSpring SessionAwareMessageListener 'onMessage(..)' JMSException
JMS MessageListener SessionAwareMessageListener
19.4.4.MessageListenerAdapterMessageListenerAdapterSpringfinalclass MDP
JMS 1.0.2 API MessageListenerAdapterMessageListenerAdapter102
MessageListener SessionAwareMessageListenerMessageListenerAdapterMDP
publicinterfaceMessageDelegate{
voidhandleMessage(Stringmessage);
voidhandleMessage(Mapmessage);
voidhandleMessage(byte[]message);
voidhandleMessage(Serializablemessage);
}
publicclassDefaultMessageDelegateimplementsMessageDelegate{
//implementationelidedforclarity...
}
MessageDelegate DefaultMessageDelegate JMSPOJOMDP
<!--thisistheMessageDrivenPOJO(MDP)-->
<beanid="messageListener"class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<beanclass="jmsexample.DefaultMessageDelegate"/>
</constructor-arg>
</bean>
<!--andthisisthemessagelistenercontainer...-->
<beanid="jmsContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="destination"ref="destination"/>
<propertyname="messageListener"ref="messageListener"/>
</bean>
JMSTextMessageMDP 'receive' MessageListenerAdapter'handleMessage' 'receive(..)'JMSTextMessage
publicinterfaceTextMessageDelegate{
voidreceive(TextMessagemessage);
}
publicclassDefaultTextMessageDelegateimplementsTextMessageDelegate{
//implementationelidedforclarity...
}
MessageListenerAdapter
<beanid="messageListener"class="org.springframework.jms.listener.adapter.MessageListenerAdapter">
<constructor-arg>
<beanclass="jmsexample.DefaultTextMessageDelegate"/>
</constructor-arg>
<propertyname="defaultListenerMethod"value="receive"/>
<!--wedon'twantautomaticmessagecontextextraction-->
<propertyname="messageConverter">
<null/>
</property>
</bean>
'messageListener' TextMessage JMS Message
IllegalStateExceptionMessageListenerAdapter
publicinterfaceResponsiveTextMessageDelegate{
//noticethereturntype...
Stringreceive(TextMessagemessage);
}
publicclassDefaultResponsiveTextMessageDelegateimplementsResponsiveTextMessageDelegate{
//implementationelidedforclarity...
}
DefaultResponsiveTextMessageDelegate MessageListenerAdapter 'receive(..)' TextMessage TextMessage Message
JMSReply-To MessageListenerAdapter InvalidDestinationException
19.4.5.
sessionTransactedJMSSessionAwareMessageListener
<beanid="jmsContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="destination"ref="destination"/>
<propertyname="messageListener"ref="messageListener"/>
<propertyname="sessionTransacted"value="true"/>
</bean>
DefaultMessageListenerContainerXA JtaTransactionManagerJ2EEJMSConnectionFactoryXAJTAJ2EEJNDIXA
<beanid="transactionManager"class="org.springframework.transaction.jta.JtaTransactionManager"/>
<beanid="jmsContainer"class="org.springframework.jms.listener.DefaultMessageListenerContainer">
<propertyname="connectionFactory"ref="connectionFactory"/>
<propertyname="destination"ref="destination"/>
<propertyname="messageListener"ref="messageListener"/>
<propertyname="transactionManager"ref="transactionManager"/>
</bean>
19.5.JCASpring2.5SpringJCA MessageListenerJmsMessageEndpointManager ResourceAdapter ActivationSpecSpring JmsActivationSpecConfig
<beanclass="org.springframework.jms.listener.endpoint.JmsMessageEndpointManager">
<propertyname="resourceAdapter"ref="resourceAdapter"/>
<propertyname="jmsActivationSpecConfig">
<beanclass="org.springframework.jms.listener.endpoint.JmsActivationSpecConfig">
<propertyname="destinationName"value="myQueue"/>
</bean>
</property>
<propertyname="messageListener"ref="myMessageListener"/>
</bean>
Spring ResourceAdapterFactoryBean ResourceAdapterWebLogicJNDI
<beanid="resourceAdapter"class="org.springframework.jca.support.ResourceAdapterFactoryBean">
<propertyname="resourceAdapter">
<beanclass="org.apache.activemq.ra.ActiveMQResourceAdapter">
<propertyname="serverUrl"value="tcp://localhost:61616"/>
</bean>
</property>
<propertyname="workManager">
<beanclass="org.springframework.jca.work.SimpleTaskWorkManager"/>
</property>
</bean>
JmsMessageEndpointManagerJmsActivationSpecConfigResourceAdapterFactoryBeanJavaDocSpringJMSJCAorg.springframework.jca.endpoint.GenericMessageEndpointManagerCCIMessageListenerActivationSpecJCAGenericMessageEndpointManagerJavaDocSpring
JCAEJB2.1Message-DrivenBeansEJB2.1MDB
JCASpringContextSpringJMS“”JMSJCAAPI
19.6.JMSSpring2.5XMLJMSJMSJMSSchema
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jmshttp://www.springframework.org/schema/jms/spring-jms-2.5.xsd"
<!--<bean/>definitionshere-->
</beans>
<listener-container/> <jca-listener-container/> <listener/>
<jms:listener-container>
<jms:listenerdestination="queue.orders"ref="orderService"method="placeOrder"/>
<jms:listenerdestination="queue.confirmations"ref="confirmationLogger"method="log"/>
</jms:listener-container>
19.4.4“ MessageListenerAdapter” MessageListenerAdapterlistener
19.1.JMSlistener
id BeanBean
destination DestinationResolver
ref Bean
method ref MessageListenerSpring SessionAwareMessageListener
response-destination "JMSReplyTo""destination-type"
subscription
selector
<listener-container/> JMSdestinationResolver
<jms:listener-containerconnection-factory="myConnectionFactory"
task-executor="myTaskExecutor"
destination-resolver="myDestinationResolver"
transaction-manager="myTransactionManager"
concurrency="10">
<jms:listenerdestination="queue.orders"ref="orderService"method="placeOrder"/>
<jms:listenerdestination="queue.confirmations"ref="confirmationLogger"method="log"/>
</jms:listener-container>
AbstractMessageListenerContainerJavadocJavadoc
19.2.JMS<listener-container/>
container-type defaultsimpledefault102 simple102 'default'
connection-factory JMSConnectionFactoryBeanBean 'connectionFactory'
task-executor JMSSpringTaskExecutor
destination-resolver DestinationResolverJMS Destinations
message-converter MessageConverterJMSMessages SimpleMessageConverter
destination-type JMS queuetopic durableTopic 'queue'
client-id JMSid
acknowledge JMS autoclientdups-ok transacted 'auto' 'transacted'
Session transaction-manager
transaction-manager SpringPlatformTransactionManager
concurrency Session
prefetch Session
“jms”SchemaJCA
<jms:jca-listener-containerresource-adapter="myResourceAdapter"
destination-resolver="myDestinationResolver"
transaction-manager="myTransactionManager"
concurrency="10">
<jms:listenerdestination="queue.orders"ref="myMessageListener"/>
</jms:jca-listener-container>
JCA
19.3.JMS<jca-listener-container/>
resource-adapter JCAResourceAdapterBeanBean 'resourceAdapter'
activation-spec-factory
JmsActivationSpecFactory JMS ActivationSpecDefaultJmsActivationSpecFactory
destination-resolver DestinationResolverJMS Destinations
message-converter MessageConverterJMSMessages SimpleMessageConverter
destination-type JMS queuetopic durableTopic 'queue'
client-id JMSid
acknowledge JMS autoclientdups-ok transacted 'auto' 'transacted'
Session transaction-manager
transaction-manager
SpringJtaTransactionManager javax.transaction.TransactionManagerXA “acknowledge”
concurrency Session
prefetch Session
20JMX
20.1.20.2.BeanJMX
20.2.1.MBeanServer20.2.2.MBeanServer20.2.3.MBean20.2.4.MBean20.2.5.
20.3.Bean20.3.1.MBeanInfoAssembler20.3.2.20.3.3.JDK5.020.3.4.20.3.5.AutodetectCapableMBeanInfoAssembler20.3.6.Java20.3.7.MethodNameBasedMBeanInfoAssembler
20.4.BeanObjectName20.4.1. PropertiesProperties
20.4.2.MetadataNamingStrategy20.4.3.<context:mbean-export/>
20.5.JSR-16020.5.1.20.5.2.20.5.3.Burlap/Hessian/SOAPJMX
20.6.MBean20.7.
20.7.1.20.7.2.
20.8.
JMXJMXJMXJMXJMX 20.8“”
20.1.SpringJMXSpringJMXSpringJMX
SpringBeanJMXMBean
Bean
JSR-160MBean
MBeanSpringJMX SpringJMXSpringJMX
20.2.BeanJMXSpringJMX MBeanExporterSpringBean JMX
packageorg.springframework.jmx;
publicclassJmxTestBeanimplementsIJmxTestBean{
privateStringname;
privateintage;
privatebooleanisSuperman;
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
publicvoidsetName(Stringname){
this.name=name;
}
publicStringgetName(){
returnname;
}
publicintadd(intx,inty){
returnx+y;
}
publicvoiddontExposeMe(){
thrownewRuntimeException();
}
}
BeanJMXMBean MBeanExporterBean
<beans>
<!--Bean -->
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter"
lazy-init="false">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean1"value-ref="testBean"/>
</map>
</property>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
exporterBean beans MBeanExporterBeanJMX MBeanServer beans MapkeyBean ObjectName 20.4“Bean ObjectName
testBean bean:name=testBean1 ObjectNameMBean public public Object
20.2.1. MBeanServer
MBeanServerMBeanServerTomcatIBMWebSphere MBeanServer org.springframework.jmx.support.MBeanServerFactoryBeanMBeanExporter server MBeanExporterMBeanServerFactoryBean MBeanServer
<beans>
<beanid="mbeanServer"class="org.springframework.jmx.support.MBeanServerFactoryBean"/>
<!--
Bean
-->
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean1"value-ref="testBean"/>
</map>
</property>
<propertyname="server"ref="mbeanServer"/>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
MBeanServerFactoryBean MBeanServerserver MBeanExporter
MBeanServer MBeanExporter MBeanServerJMX
20.2.2. MBeanServer
MBeanExporter MBeanServer MBeanServerMBeanExporter MBeanServer agentId
<beans>
<beanid="mbeanServer"class="org.springframework.jmx.support.MBeanServerFactoryBean">
<!---->
<propertyname="locateExistingServerIfPossible"value="true"/>
<!--agentId MBeanServer-->
<propertyname="agentId"value="<MBeanServerinstanceagentId>
</bean>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="server"ref="mbeanServer"/>
...
</bean>
</beans>
MBeanServerlookup agentId factory-method
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="server">
<!-- MBeanServerLocator-->
<beanclass="platform.package.MBeanServerLocator"factory-method="locateMBeanServer"/>
</property>
<!--Bean-->
</bean>
</beans>
20.2.3.MBean MBeanExporterBean MBeanExporter MBeanExporterBean MBeanServerBean
20.2.4.MBean MBeanExporterBeanMBean MBeanServerSpringautodetecttrue MBeanExporterMBean
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="autodetect"value="true"/>
</bean>
<beanname="spring:mbean=true"class="org.springframework.jmx.export.TestDynamicMBean"/>
spring:mbean=trueBeanJMXMBeanSpringObjectNameBean 20.4“Bean ObjectName”overridden
20.2.5.Spring MBeanExporter ObjectName'bean:name=testBean1'MBeanServerMBean ObjectName MBeanInstanceAlreadyExistsException
MBean SpringJMX
20.1.
REGISTRATION_FAIL_ON_EXISTING MBean ObjectNameSpring MBeanInstanceAlreadyExistsException MBean
REGISTRATION_IGNORE_EXISTING MBean ObjectName MBean MBean
REGISTRATION_REPLACE_EXISTING MBean ObjectName MBean MBeanObjectName MBean
MBeanRegistrationSupport MBeanExporter MBeanExporter registrationBehaviorName REGISTRATION_REPLACE_EXISTING
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean1"value-ref="testBean"/>
</map>
</property>
<propertyname="registrationBehaviorName"value="REGISTRATION_REPLACE_EXISTING"/>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
20.3.BeanBeanBean publicJMXBeanJMXSpringJMXbean
20.3.1.MBeanInfoAssemblerMBeanExporter beanorg.springframework.jmx.export.assembler.MBeanInfoAssemblerBean
org.springframework.jmx.export.assembler.SimpleReflectiveMBeanInfoAssembler
publicpublic Spring
20.3.2. MetadataMBeanInfoAssemblerBeanorg.springframework.jmx.export.metadata.JmxAttributeSourceSprinJMXCommons Attributesorg.springframework.jmx.export.metadata.AttributesJmxAttributeSource
JDK 5.0org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource
MetadataMBeanInfoAssembler CommonsAttributesBeanJMX ManagedResourceBean CommonsAttributesorg.springframework.jmx.metadata gettersetterCommonsAttributes JmxTestBean
packageorg.springframework.jmx;
/**
*@@org.springframework.jmx.export.metadata.ManagedResource
*(description="MyManagedBean",objectName="spring:bean=test",
*log=true,logFile="jmx.log",currencyTimeLimit=15,persistPolicy="OnUpdate",
*persistPeriod=200,persistLocation="foo",persistName="bar")
*/
publicclassJmxTestBeanimplementsIJmxTestBean{
privateStringname;
privateintage;
/**
*@@org.springframework.jmx.export.metadata.ManagedAttribute
*(description="TheAgeAttribute",currencyTimeLimit=15)
*/
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
/**
*@@org.springframework.jmx.export.metadata.ManagedAttribute
*(description="TheNameAttribute",currencyTimeLimit=20,
*defaultValue="bar",persistPolicy="OnUpdate")
*/
publicvoidsetName(Stringname){
this.name=name;
}
/**
*@@org.springframework.jmx.export.metadata.ManagedAttribute
*(defaultValue="foo",persistPeriod=300)
*/
publicStringgetName(){
returnname;
}
/**
*@@org.springframework.jmx.export.metadata.ManagedOperation
*(description="AddTwoNumbersTogether")
*/
publicintadd(intx,inty){
returnx+y;
}
publicvoiddontExposeMe(){
thrownewRuntimeException();
}
}
JmxTestBean ManagedResource ManagedResourceMBeanExporterMBean 20.3.4“” age name ManagedAttribute agegetter
add(int,int) ManagedOperation dontExposeMe()MetadataMBeanInfoAssembler add(int,int) MetadataMBeanInfoAssembler MBeanExporter
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean1"value-ref="testBean"/>
</map>
</property>
<propertyname="assembler"ref="assembler"/>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
<beanid="attributeSource"
class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource">
<propertyname="attributes">
<beanclass="org.springframework.metadata.commons.CommonsAttributes"/>
</property>
</bean>
<beanid="assembler"class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<propertyname="attributeSource"ref="attributeSource"/>
</bean>
</beans>
MetadataMBeanInfoAssemblerBean AttributesJmxAttributeSource
assembler MBeanExporterSpringMBean
20.3.3.JDK5.0JDK5.0SpringCommonsAttributeAnnotationsJmxAttributeSource MBeanInfoAssemblerJDK5.0Bean
packageorg.springframework.jmx;
importorg.springframework.jmx.export.annotation.ManagedResource;
importorg.springframework.jmx.export.annotation.ManagedOperation;
importorg.springframework.jmx.export.annotation.ManagedAttribute;
@ManagedResource(objectName="bean:name=testBean4",description="MyManagedBean",log=true,
logFile="jmx.log",currencyTimeLimit=15,persistPolicy="OnUpdate",persistPeriod=200,
persistLocation="foo",persistName="bar")
publicclassAnnotationTestBeanimplementsIJmxTestBean{
privateStringname;
privateintage;
@ManagedAttribute(description="TheAgeAttribute",currencyTimeLimit=15)
publicintgetAge(){
returnage;
}
publicvoidsetAge(intage){
this.age=age;
}
@ManagedAttribute(description="TheNameAttribute",
currencyTimeLimit=20,
defaultValue="bar",
persistPolicy="OnUpdate")
publicvoidsetName(Stringname){
this.name=name;
}
@ManagedAttribute(defaultValue="foo",persistPeriod=300)
publicStringgetName(){
returnname;
}
@ManagedOperation(description="Addtwonumbers")
@ManagedOperationParameters({
@ManagedOperationParameter(name="x",description="Thefirstnumber"),
@ManagedOperationParameter(name="y",description="Thesecondnumber")})
publicintadd(intx,inty){
returnx+y;
}
publicvoiddontExposeMe(){
thrownewRuntimeException();
}
}
JDK5.0CommonsAttributes
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="assembler"ref="assembler"/>
<propertyname="namingStrategy"ref="namingStrategy"/>
<propertyname="autodetect"value="true"/>
</bean>
<beanid="jmxAttributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
<!---->
<beanid="assembler"
class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<propertyname="attributeSource"ref="jmxAttributeSource"/>
</bean>
<!-- ObjectName-->
<beanid="namingStrategy"
class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<propertyname="attributeSource"ref="jmxAttributeSource"/>
</bean>
<beanid="testBean"class="org.springframework.jmx.AnnotationTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
20.3.4.SpringJMX
20.2.
CommonsAttributes JDK5.0 /JMX ManagedResource @ManagedResource Class
JMX ManagedOperation @ManagedOperation Method
gettersetterJMX
ManagedAttribute @ManagedAttribute
Method(onlygettersandsetters)
getterssetters
ManagedOperationParameter
@ManagedOperationParameter
@ManagedOperationParameters
Method
20.3.
ObjectNameMetadataNamingStrategy
ObjectNameManagedResource
ManagedResource
ManagedAttribute
ManagedOperation
ManagedOperationParameter
currencyTimeLimit
currencyTimeLimit currencyTimeLimit ManagedResourceManagedAttribute
defaultValue defaultValue ManagedAttribute
log log ManagedResource
logFile logFile ManagedResource
persistPolicy persistPolicy ManagedResource
persistPeriod persistPeriod ManagedResource
persistLocation persistLocation ManagedResource
persistName persistName ManagedResource
name ManagedOperationParameter
index ManagedOperationParameter
20.3.5.AutodetectCapableMBeanInfoAssemblerSpring AutodetectCapableMBeanInfoAssemblerMBeanInfoAssembler MBeanAutodetectCapableMBeanInfoAssembler MBeanExporterJMXBeanAutodetectCapableMBeanInfo MetadataMBeanInfoAssembler“”ManagedResourceBean bean ObjectName
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<!-- 'beans'-->
<propertyname="autodetect"value="true"/>
<propertyname="assembler"ref="assembler"/>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
<!--CommonsAttributes-basedmetadata-->
<beanid="attributeSource"
class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource">
<propertyname="attributes">
<beanclass="org.springframework.metadata.commons.CommonsAttributes"/>
</property>
</bean>
<!--JDK5+-->
<!--
<beanid="attributeSource"
class="org.springframework.jmx.export.annotation.AnnotationJmxAttributeSource"/>
-->
<beanid="assembler"class="org.springframework.jmx.export.assembler.MetadataMBeanInfoAssembler">
<propertyname="attributeSource"ref="attributeSource"/>
</bean>
</beans>
MBeanExporterBean JmxTestBean ManagedResource
MetadataMBeanInfoAssembler Bean ObjectName” ObjectName
20.3.6.Java MetadataMBeanInfoAssemblerSpringInterfaceBasedMBeanInfoAssembler
MBean InterfaceBasedMBeanInfoAssembler
JmxTestBean
publicinterfaceIJmxTestBean{
publicintadd(intx,inty);
publiclongmyOperation();
publicintgetAge();
publicvoidsetAge(intage);
publicvoidsetName(Stringname);
publicStringgetName();
}
JMXMBeanSpringJMX
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean5"value-ref="testBean"/>
</map>
</property>
<propertyname="assembler">
<beanclass="org.springframework.jmx.export.assembler.InterfaceBasedMBeanInfoAssembler">
<propertyname="managedInterfaces">
<value>org.springframework.jmx.IJmxTestBean</value>
</property>
</bean>
</property>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
Bean InterfaceBasedMBeanInfoAssembler IJmxTestBean
InterfaceBasedMBeanInfoAssemblerbeanJMXIJmxTestBeanbean Bean
InterfaceBasedMBeanInfoAssembler interfaceMappings Properties
Bean(;)Bean managedInterfaces interfaceMappings
InterfaceBasedMBeanInfoAssemblerBean
20.3.7. MethodNameBasedMBeanInfoAssembler
MethodNameBasedMBeanInfoAssemblerJMX
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean5"value-ref="testBean"/>
</map>
</property>
<propertyname="assembler">
<beanclass="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
<propertyname="managedMethods">
<value>add,myOperation,getName,setName,getAge</value>
</property>
</bean>
</property>
</bean>
add myOperationJMX getName()setName(String) getAge()JMXJMXBean BeanmethodMappingsBean
20.4.Bean ObjectName
Bean MBeanExporter ObjectNamingStrategy ObjectNameKeyNamingStrategy beans Map ObjectName KeyNamingStrategy Properties ObjectName KeyNamingStrategySpringObjectNamingStrategy beanJVM ObjectNameIdentityNamingStrategy ObjectName MetadataNamingStrategy
20.4.1. PropertiesProperties
KeyNamingStrategy Properties ObjectNameBeanKeyNamingStrategybean Properties Bean ObjectName
KeyNamingStrategy
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="testBean"value-ref="testBean"/>
</map>
</property>
<propertyname="namingStrategy"ref="namingStrategy"/>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
<beanid="namingStrategy"class="org.springframework.jmx.export.naming.KeyNamingStrategy">
<propertyname="mappings">
<props>
<propkey="testBean">bean:name=testBean1</prop>
</props>
</property>
<propertyname="mappingLocations">
<value>names1.properties,names2.properties</value>
</property>
</bean
</beans>
KeyNamingStrategy Properties PropertiesmappingmappingLocations Properties testBean ObjectName bean:name=testBean1
PropertiesBean ObjectName
20.4.2. MetadataNamingStrategy
MetadataNamingStrategy Bean ManagedResource objectNameobjectName MetadataNamingStrategy
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="testBean"value-ref="testBean"/>
</map>
</property>
<propertyname="namingStrategy"ref="namingStrategy"/>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
<beanid="namingStrategy"class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
<propertyname="attributeSource"ref="attributeSource"/>
</bean>
<beanid="attributeSource"
class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource"/>
</beans>
objectName ManagedResource ObjectName [fully-qualified-package-name]:type=[short-classname],name=[bean-name]Bean
ObjectName com.foo:type=MyClass,name=myBean
<beanid="myBean"class="com.foo.MyClass"/>
20.4.3.<context:mbean-export/>Java5 MBeanExporter AnnotationMBeanExporter
namingStrategy attributeSource
<context:mbean-export/>
MBean defaultDomain AnnotationMBeanExporter
ObjectNames MetadataNamingStrategy
<context:mbean-exportserver="myMBeanServer"default-domain="myDomain"/>
.
20.5.JSR-160SpringJMX org.springframework.jmx.support FactoryBean
20.5.1.SpringJMXJSR-160 JMXConnectorServer
<beanid="serverConnector"class="org.springframework.jmx.support.ConnectorServerFactoryBean"/>
ConnectorServerFactoryBean JMXConnectorServer"service:jmx:jmxmp://localhost:9875" serverConnectorBean9875JMXMP MBeanServer JSR160JMXMPJMXMX4JJ2SE5.0JMXMPURL MBeanServer JMXConnectorServer serviceUrl
<beanid="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean">
<propertyname="objectName"value="connector:name=rmi"/>
<propertyname="serviceUrl"
value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector"/>
</bean>
ObjectNameSpring ObjectName MBeanServer JMXConnectorServerFactoryBean
<beanid="serverConnector"
class="org.springframework.jmx.support.ConnectorServerFactoryBean">
<propertyname="objectName"value="connector:name=iiop"/>
<propertyname="serviceUrl"
value="service:jmx:iiop://localhost/jndi/iiop://localhost:900/myconnector"/>
<propertyname="threaded"value="true"/>
<propertyname="daemon"value="true"/>
<propertyname="environment">
<map>
<entrykey="someKey"value="someValue"/>
</map>
</property>
</bean>
RMItnameservrmiregistrySpring
<beanid="registry"class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
<propertyname="port"value="1099"/>
</bean>
20.5.2. MBeanServerConnection JSR-160 MBeanServerMBeanServerConnectionFactoryBean
<beanid="clientConnector"class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
<propertyname="serviceUrl"value="service:jmx:rmi://localhost:9875"/>
</bean>
20.5.3.Burlap/Hessian/SOAPJMXJSR-160RMIJSR-160IIOPJRMPJMXMPMX4J SOAPHessianHTTPSSLBurlap
<beanid="serverConnector"class="org.springframework.jmx.support.ConnectorServerFactoryBean">
<propertyname="objectName"value="connector:name=burlap"/>
<propertyname="serviceUrl"value="service:jmx:burlap://localhost:9874"/>
</bean>
MX4J3.0.0MX4J
20.6.MBeanSpringJMX MBeanServerMBeanMBeanServerMBean
<beanid="proxy"class="org.springframework.jmx.access.MBeanProxyFactoryBean">
<propertyname="objectName"value="bean:name=testBean"/>
<propertyname="proxyInterface"value="org.springframework.jmx.IJmxTestBean"/>
</bean>
ObjectName:bean:name=testBeanMBean MBean InterfaceBasedMBeanInfoAssembler
MBeanProxyFactoryBeanMBean MBeanServerConnectionMBeanServerMBean MBeanServer MBeanServerConnection
<beanid="clientConnector"
class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
<propertyname="serviceUrl"value="service:jmx:rmi://remotehost:9875"/>
</bean>
<beanid="proxy"class="org.springframework.jmx.access.MBeanProxyFactoryBean">
<propertyname="objectName"value="bean:name=testBean"/>
<propertyname="proxyInterface"value="org.springframework.jmx.IJmxTestBean"/>
<propertyname="server"ref="clientConnector"/>
</bean>
MBeanServerConnectionFactoryBean MBeanServerConnection
MBeanServerConnection server MBeanProxyFactoryBeanMBeanServerConnection MBeanServer
20.7.SpringJMXJMX
20.7.1.SpringJMXMBean NotificationListenersSpringMBean MBean
packagecom.example;
importjavax.management.AttributeChangeNotification;
importjavax.management.Notification;
importjavax.management.NotificationFilter;
importjavax.management.NotificationListener;
publicclassConsoleLoggingNotificationListener
implementsNotificationListener,NotificationFilter{
publicvoidhandleNotification(Notificationnotification,Objecthandback){
System.out.println(notification);
System.out.println(handback);
}
publicbooleanisNotificationEnabled(Notificationnotification){
returnAttributeChangeNotification.class.isAssignableFrom(notification.getClass());
}
}
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean1"value-ref="testBean"/>
</map>
</property>
<propertyname="notificationListenerMappings">
<map>
<entrykey="bean:name=testBean1">
<beanclass="com.example.ConsoleLoggingNotificationListener"/>
</entry>
</map>
</property>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
MBean bean:name=testBean1JMXNotificationnotificationListenerMappings ConsoleLoggingNotificationListener
ConsoleLoggingNotificationListener Notification
BeanBean
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean1"value-ref="testBean"/>
</map>
</property>
<propertyname="notificationListenerMappings">
<map>
<entrykey="testBean">
<beanclass="com.example.ConsoleLoggingNotificationListener"/>
</entry>
</map>
</property>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
MBeanExporterBean NotificationListener'*'notificationListenerMappings
<propertyname="notificationListenerMappings">
<map>
<entrykey="*">
<beanclass="com.example.ConsoleLoggingNotificationListener"/>
</entry>
</map>
</property>
MBean notificationListeners
notificationListenerMappings NotificationListenerBean
…… NotificationListenerBean NotificationListenerMBeanServer ObjectName NotificationFilterJMX NotificationListenerBean
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean1"value-ref="testBean"/>
</map>
</property>
<propertyname="notificationListeners">
<list>
<beanclass="org.springframework.jmx.export.NotificationListenerBean">
<constructor-arg>
<beanclass="com.example.ConsoleLoggingNotificationListener"/>
</constructor-arg>
<propertyname="mappedObjectNames">
<list>
<value>bean:name=testBean1</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
<beanid="testBean"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
</beans>
Notification NotificationFilter JMX1.2 'The JMX Notification Model'
<beans>
<beanid="exporter"class="org.springframework.jmx.export.MBeanExporter">
<propertyname="beans">
<map>
<entrykey="bean:name=testBean1"value-ref="testBean1"/>
<entrykey="bean:name=testBean2"value-ref="testBean2"/>
</map>
</property>
<propertyname="notificationListeners">
<list>
<beanclass="org.springframework.jmx.export.NotificationListenerBean">
<constructor-argref="customerNotificationListener"/>
<propertyname="mappedObjectNames">
<list>
<!--handlesnotificationsfromtwodistinctMBeans-->
<value>bean:name=testBean1</value>
<value>bean:name=testBean2</value>
</list>
</property>
<propertyname="handback">
<beanclass="java.lang.String">
<constructor-argvalue="Thiscouldbeanything..."/>
</bean>
</property>
<propertyname="notificationFilter"ref="customerNotificationListener"/>
</bean>
</list>
</property>
</bean>
<!-- NotificationListener NotificationFilter-->
<beanid="customerNotificationListener"class="com.example.ConsoleLoggingNotificationListener"/>
<beanid="testBean1"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="TEST"/>
<propertyname="age"value="100"/>
</bean>
<beanid="testBean2"class="org.springframework.jmx.JmxTestBean">
<propertyname="name"value="ANOTHERTEST"/>
<propertyname="age"value="200"/>
</bean>
</beans>
20.7.2.Spring
MBeanExporterSpringBean
SpringJMX NotificationPublisher
org.springframework.jmx.export.notification MBeanExporter
MBeanBean NotificationPublisherAware NotificationPublisher
NotificationPublisherAwaresetterBeanBean Notification NotificationPublisherJavadoc NotificationPublisherBean SpringJMXJMXNotificationPublisher Bean MBeanServer
NotificationPublisher NotificationPublisher Notification Notification NotificationNotificationPublisher
sendNotification(Notification)
JmxTestBean add(int,int) NotificationEvent
packageorg.springframework.jmx;
importorg.springframework.jmx.export.notification.NotificationPublisherAware;
importorg.springframework.jmx.export.notification.NotificationPublisher;
importjavax.management.Notification;
publicclassJmxTestBeanimplementsIJmxTestBean,NotificationPublisherAware{
privateStringname;
privateintage;
privatebooleanisSuperman;
privateNotificationPublisherpublisher;
//gettersetter
publicintadd(intx,inty){
intanswer=x+y;
this.publisher.sendNotification(newNotification("add",this,0));
returnanswer;
}
publicvoiddontExposeMe(){
thrownewRuntimeException();
}
publicvoidsetNotificationPublisher(NotificationPublishernotificationPublisher){
this.publisher=notificationPublisher;
}
}
NotificationPublisherSpringJMX SpringJMX……NotificationPublisherSpringJMX
20.8.JMX
Sun JMX
JMXJSR-000003
JMXJSR-000160
MX4JJMX
GettingStartedwithJMX-Sun.
21JCACCI
21.1.21.2.CCI
21.2.1.21.2.2.SpringConnectionFactory21.2.3.CCI21.2.4.CCI
21.3.SpringCCI21.3.1.21.3.2.CciTemplate21.3.3.DAO21.3.4.21.3.5.21.3.6.CCIConnectionInteraction21.3.7.CciTemplate
21.4.CCI21.4.1.MappingRecordOperation21.4.2.MappingCommAreaOperation21.4.3.21.4.4.21.4.5.MappingRecordOperation21.4.6.MappingCommAreaOperation
21.5.
21.1.J2EEJCAJavaConnectorArchitectureEISEnterpriseInformationSystem
SPIServiceproviderinterfacesconnectorproviderresourceadapter connectionpoolingmanagedmode connectornon-managedmodeCCICommonClientInterfaceEISAPI
SpringCCISpringCCISpring
CCIAPIJCAresourceadaptercontractsconnectionpoolingglobaltransactionssecurity Springconnector-specificAPI
21.2.CCI
21.2.1.JCACCI ConnectionFactoryJNDI ConnectionFactory
ra.xml SpringSpringnon-managedmodeFactoryBeanLocalConnectionFactoryBean)bean classpathRAR ra.xml RAR ConnectionFactory CCIAPISpringCCI
CciTemplate
non-managedmode J2EE
21.2.2.Spring ConnectionFactory
EISmanagedmodemodeSpringmanagedmodeJNDI ConnectionFactory
<beanid="eciConnectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="eis/cicseci"/>
</bean>
non-managedmodeSpring ConnectionFactory
LocalConnectionFactoryBean ManagedConnectionFactoryConnectionFactory
<beanid="eciManagedConnectionFactory"class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
<propertyname="serverName"value="TXSERIES"/>
<propertyname="connectionURL"value="tcp://localhost/"/>
<propertyname="portNumber"value="2006"/>
</bean>
<beanid="eciConnectionFactory"class="org.springframework.jca.support.LocalConnectionFactoryBean">
<propertyname="managedConnectionFactory"ref="eciManagedConnectionFactory"/>
</bean>
ConnectionFactory JCASPI
21.2.3.CCIJCACCI ConnectionSpecEISConnectionSpecConnectionFactoryAdapter connectionSpecbeanCCI ConnectionFactoryCCI ConnectionSpec
mode ManagedConnectionFactory
publicinterfaceConnectionFactoryimplementsSerializable,Referenceable{
...
ConnectiongetConnection()throwsResourceException;
ConnectiongetConnection(ConnectionSpecconnectionSpec)throwsResourceException;
...
}
Spring ConnectionSpecConnectionFactoryAdapter ConnectionSpec, connectionSpec
ConnectionSpec
<beanid="managedConnectionFactory"
class="com.sun.connector.cciblackbox.CciLocalTxManagedConnectionFactory">
<propertyname="connectionURL"value="jdbc:hsqldb:hsql://localhost:9001"/>
<propertyname="driverName"value="org.hsqldb.jdbcDriver"/>
</bean>
<beanid="targetConnectionFactory"
class="org.springframework.jca.support.LocalConnectionFactoryBean">
<propertyname="managedConnectionFactory"ref="managedConnectionFactory"/>
</bean>
<beanid="connectionFactory"
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">
<propertyname="targetConnectionFactory"ref="targetConnectionFactory"/>
<propertyname="connectionSpec">
<beanclass="com.sun.connector.cciblackbox.CciConnectionSpec">
<propertyname="user"value="sa"/>
<propertyname="password"value=""/>
</bean>
</property>
</bean>
21.2.4.CCICCISpring ConnectionFactorybean Connection
<beanid="eciManagedConnectionFactory"
class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
<propertyname="serverName"value="TEST"/>
<propertyname="connectionURL"value="tcp://localhost/"/>
<propertyname="portNumber"value="2006"/>
</bean>
<beanid="targetEciConnectionFactory"
class="org.springframework.jca.support.LocalConnectionFactoryBean">
<propertyname="managedConnectionFactory"ref="eciManagedConnectionFactory"/>
</bean>
<beanid="eciConnectionFactory"
class="org.springframework.jca.cci.connection.SingleConnectionFactory">
<propertyname="targetConnectionFactory"ref="targetEciConnectionFactory"/>
</bean>
ConnectionFactory ConnectionSpec ConnectionSpec SingleConnectionFactoryConnectionSpecConnectionFactoryAdapter
21.3.SpringCCI
21.3.1.JCACCICCI Spring Record RecordCreator
publicinterfaceRecordCreator{
RecordcreateRecord(RecordFactoryrecordFactory)throwsResourceException,DataAccessException;
}
createRecord(..) RecordFactory RecordFactory IndexedRecord MappedRecordRecordFactoryindexed/mapped
publicclassMyRecordCreatorimplementsRecordCreator{
publicRecordcreateRecord(RecordFactoryrecordFactory)throwsResourceException{
IndexedRecordinput=recordFactory.createIndexedRecord("input");
input.add(newInteger(id));
returninput;
}
}
RecordEIS RecordExtractorSpring CciTemplate
Record
publicinterfaceRecordExtractor{
ObjectextractData(Recordrecord)throwsResourceException,SQLException,DataAccessException;
}
RecordExtractor
publicclassMyRecordExtractorimplementsRecordExtractor{
publicObjectextractData(Recordrecord)throwsResourceException{
CommAreaRecordcommAreaRecord=(CommAreaRecord)record;
Stringstr=newString(commAreaRecord.toByteArray());
Stringfield1=string.substring(0,6);
Stringfield2=string.substring(6,1);
returnnewOutputObject(Long.parseLong(field1),field2);
}
}
21.3.2.CciTemplateCciTemplateCCI org.springframework.jca.cci.core CCIJCACCIEISCCI Interaction execute
publicinterfacejavax.resource.cci.Interaction{
...
booleanexecute(InteractionSpecspec,Recordinput,Recordoutput)throwsResourceException;
Recordexecute(InteractionSpecspec,Recordinput)throwsResourceException;
...
}
CciTemplateinteraction execute
CciTemplate.execute(..)
RecordCCI CCI
RecordCreator RecordExtractor
Interaction
publicclassCciTemplateimplementsCciOperations{
publicRecordexecute(InteractionSpecspec,RecordinputRecord)
throwsDataAccessException{...}
publicvoidexecute(InteractionSpecspec,RecordinputRecord,RecordoutputRecord)
throwsDataAccessException{...}
}
publicclassCciTemplateimplementsCciOperations{
publicRecordexecute(InteractionSpecspec,RecordCreatorinputCreator)
throwsDataAccessException{...}
publicObjectexecute(InteractionSpecspec,RecordinputRecord,RecordExtractoroutputExtractor)
throwsDataAccessException{...}
publicObjectexecute(InteractionSpecspec,RecordCreatorcreator,RecordExtractorextractor)
throwsDataAccessException{...}
}
outputRecordCreator CCI Record execute Record createIndexRecord(..) createMappedRecord(..) CciTemplateRecordCreator IndexRecord MappedRecordDAOCciTemplate.execute(..)
publicclassCciTemplateimplementsCciOperations{
publicIndexedRecordcreateIndexedRecord(Stringname)throwsDataAccessException{...}
publicMappedRecordcreateMappedRecord(Stringname)throwsDataAccessException{...}
}
21.3.3.DAOSpringCCIDAO ConnectionFactory CciTemplate
CciDaoSupport setConnectionFactory setCciTemplateConnectionFactory CciTemplate
publicabstractclassCciDaoSupport{
publicvoidsetConnectionFactory(ConnectionFactoryconnectionFactory){...}
publicConnectionFactorygetConnectionFactory(){...}
publicvoidsetCciTemplate(CciTemplatecciTemplate){...}
publicCciTemplategetCciTemplate(){...}
}
21.3.4. Interaction.execute(..) outputRecordCreator JCAJCAconnector RecordCreator RecordCreator 21.3.1“”
outputRecordCreator CciTemplate
cciTemplate.setOutputRecordCreator(newEciOutputRecordCreator());
CciTemplatebeanoutputRecordCreatorSpring
<beanid="eciOutputRecordCreator"class="eci.EciOutputRecordCreator"/>
<beanid="cciTemplate"class="org.springframework.jca.cci.core.CciTemplate">
<propertyname="connectionFactory"ref="eciConnectionFactory"/>
<propertyname="outputRecordCreator"ref="eciOutputRecordCreator"/>
</bean>
CciTemplate
21.3.5. CciTemplateCCI Interaction
21.1.UsageofInteractionexecutemethods
CciTemplatemethodsignature
CciTemplateoutputRecordCreator
property
executemethodcalledontheCCI
InteractionRecord
execute(InteractionSpec, notsetRecord
execute(InteractionSpec,
Record) Record)
Recordexecute(InteractionSpec,
Record)set
booleanexecute(InteractionSpec,
Record,Record)
voidexecute(InteractionSpec,Record,Record) notset voidexecute(InteractionSpec,
Record,Record)
voidexecute(InteractionSpec,Record,Record) set voidexecute(InteractionSpec,
Record,Record)
Recordexecute(InteractionSpec,
RecordCreator)notset
Recordexecute(InteractionSpec,
Record)
Recordexecute(InteractionSpec,
RecordCreator)set voidexecute(InteractionSpec,
Record,Record)
Recordexecute(InteractionSpec,Record,RecordExtractor)
notsetRecord
execute(InteractionSpec,Record)
Recordexecute(InteractionSpec,Record,RecordExtractor)
set voidexecute(InteractionSpec,Record,Record)
Recordexecute(InteractionSpec,
RecordCreator,RecordExtractor)
notsetRecord
execute(InteractionSpec,Record)
Recordexecute(InteractionSpec,
RecordCreator,RecordExtractor)
set voidexecute(InteractionSpec,Record,Record)
21.3.6.CCI ConnectionInteraction
JdbcTemplate JmsTemplate CciTemplateCCIConnectionCallbackCCIConnection ConnectionFactory RecordFactoryindexed/mappedrecords
publicinterfaceConnectionCallback{
ObjectdoInConnection(Connectionconnection,ConnectionFactoryconnectionFactory)
throwsResourceException,SQLException,DataAccessException;
}
InteractionCallbackCCI Interaction CCI
ConnectionFactory
publicinterfaceInteractionCallback{
ObjectdoInInteraction(Interactioninteraction,ConnectionFactoryconnectionFactory)
throwsResourceException,SQLException,DataAccessException;
}
InteractionSpectemplate
21.3.7.CciTemplate CciTemplateIBMCICSECIECICICS.CCI InteractionSpecCICS
ECIInteractionSpecinteractionSpec=newECIInteractionSpec();
interactionSpec.setFunctionName("MYPROG");
interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);
SpringCCICCI Records
publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{
publicOutputObjectgetData(InputObjectinput){
ECIInteractionSpecinteractionSpec=...;
OutputObjectoutput=(ObjectOutput)getCciTemplate().execute(interactionSpec,
newRecordCreator(){
publicRecordcreateRecord(RecordFactoryrecordFactory)throwsResourceException{
returnnewCommAreaRecord(input.toString().getBytes());
}
},
newRecordExtractor(){
publicObjectextractData(Recordrecord)throwsResourceException{
CommAreaRecordcommAreaRecord=(CommAreaRecord)record;
Stringstr=newString(commAreaRecord.toByteArray());
Stringfield1=string.substring(0,6);
Stringfield2=string.substring(6,1);
returnnewOutputObject(Long.parseLong(field1),field2);
}
});
returnoutput;
}
}
callbacksCCI
publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{
publicOutputObjectgetData(InputObjectinput){
ObjectOutputoutput=(ObjectOutput)getCciTemplate().execute(
newConnectionCallback(){
publicObjectdoInConnection(Connectionconnection,ConnectionFactoryfactory)
throwsResourceException{
//dosomething...
}
});
}
returnoutput;
}
}
getCciTemplate().execute ConnectionCallback Connection CciTemplate callback
callback InteractionCallback Interaction
publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{
publicStringgetData(Stringinput){
ECIInteractionSpecinteractionSpec=...;
Stringoutput=(String)getCciTemplate().execute(interactionSpec,
newInteractionCallback(){
publicObjectdoInInteraction(Interactioninteraction,ConnectionFactoryfactory)
throwsResourceException{
Recordinput=newCommAreaRecord(inputString.getBytes());
Recordoutput=newCommAreaRecord();
interaction.execute(holder.getInteractionSpec(),input,output);
returnnewString(output.toByteArray());
}
});
returnoutput;
}
}
non-managedspringbeans
<beanid="managedConnectionFactory"class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
<propertyname="serverName"value="TXSERIES"/>
<propertyname="connectionURL"value="local:"/>
<propertyname="userName"value="CICSUSER"/>
<propertyname="password"value="CICS"/>
</bean>
<beanid="connectionFactory"class="org.springframework.jca.support.LocalConnectionFactoryBean">
<propertyname="managedConnectionFactory"ref="managedConnectionFactory"/>
</bean>
<beanid="component"class="mypackage.MyDaoImpl">
<propertyname="connectionFactory"ref="connectionFactory"/>
</bean>
managedmodeJ2EE
<beanid="connectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="eis/cicseci"/>
</bean>
<beanid="component"class="MyDaoImpl">
<propertyname="connectionFactory"ref="connectionFactory"/>
</bean>
21.4.CCIorg.springframework.jca.cci.objectEIS CCIAPI recordrecord: CciTemplate RecordCreator/RecordExtractorSpringCCI
21.4.1.MappingRecordOperationMappingRecordOperation CciTemplate pre-configured
createInputRecord(..)Record
extractOutputData(..) Record
publicabstractclassMappingRecordOperationextendsEisOperation{
...
protectedabstractRecordcreateInputRecord(RecordFactoryrecordFactory,ObjectinputObject)
throwsResourceException,DataAccessException{...}
protectedabstractObjectextractOutputData(RecordoutputRecord)
throwsResourceException,SQLException,DataAccessException{...}
...
}
EISexecuteapplication-level
publicabstractclassMappingRecordOperationextendsEisOperation{
...
publicObjectexecute(ObjectinputObject)throwsDataAccessException{
...
}
CciTemplate execute InteractionSpec InteractionSpec InteractionSpec
InteractionSpecspec=...;
MyMappingRecordOperationeisOperation=newMyMappingRecordOperation(getConnectionFactory(),spec);
...
21.4.2.MappingCommAreaOperationCOMMAREAEISMappingCommAreaOperation MappingRecordOperationCOMMAREA CommAreaRecordrecord COMMAREACOMMAREA
publicabstractclassMappingCommAreaOperationextendsMappingRecordOperation{
...
protectedabstractbyte[]objectToBytes(ObjectinObject)
throwsIOException,DataAccessException;
protectedabstractObjectbytesToObject(byte[]bytes)
throwsIOException,DataAccessException;
...
}
21.4.3. MappingRecordOperation CciTemplate CciTemplaterecord setOutputRecordCreator(..)
21.4.4. CciTemplate
21.2.UsageofInteractionexecutemethods
MappingRecordOperation
methodsignatureMappingRecordOperation
outputRecordCreator
property
executemethodcalledontheCCI
Interaction
Objectexecute(Object) notsetRecord
execute(InteractionSpec,Record)
Objectexecute(Object) setboolean
execute(InteractionSpec,Record,Record)
21.4.5.MappingRecordOperation
BlackboxCCI MappingRecordOperation
SUNJ2EESDK1.3CCI InteractionSpecSQL CCIrecordCCI
publicclassPersonMappingOperationextendsMappingRecordOperation{
publicPersonMappingOperation(ConnectionFactoryconnectionFactory){
setConnectionFactory(connectionFactory);
CciInteractionSpecinteractionSpec=newCciConnectionSpec();
interactionSpec.setSql("select*frompersonwhereperson_id=?");
setInteractionSpec(interactionSpec);
}
protectedRecordcreateInputRecord(RecordFactoryrecordFactory,ObjectinputObject)
throwsResourceException{
Integerid=(Integer)inputObject;
IndexedRecordinput=recordFactory.createIndexedRecord("input");
input.add(newInteger(id));
returninput;
}
protectedObjectextractOutputData(RecordoutputRecord)
throwsResourceException,SQLException{
ResultSetrs=(ResultSet)outputRecord;
Personperson=null;
if(rs.next()){
Personperson=newPerson();
person.setId(rs.getInt("person_id"));
person.setLastName(rs.getString("person_last_name"));
person.setFirstName(rs.getString("person_first_name"));
}
returnperson;
}
}
person
publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{
publicPersongetPerson(intid){
PersonMappingOperationquery=newPersonMappingOperation(getConnectionFactory());
Personperson=(Person)query.execute(newInteger(id));
returnperson;
}
}
Springbeansnon-managedmode
<beanid="managedConnectionFactory"
class="com.sun.connector.cciblackbox.CciLocalTxManagedConnectionFactory">
<propertyname="connectionURL"value="jdbc:hsqldb:hsql://localhost:9001"/>
<propertyname="driverName"value="org.hsqldb.jdbcDriver"/>
</bean>
<beanid="targetConnectionFactory"
class="org.springframework.jca.support.LocalConnectionFactoryBean">
<propertyname="managedConnectionFactory"ref="managedConnectionFactory"/>
</bean>
<beanid="connectionFactory"
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">
<propertyname="targetConnectionFactory"ref="targetConnectionFactory"/>
<propertyname="connectionSpec">
<beanclass="com.sun.connector.cciblackbox.CciConnectionSpec">
<propertyname="user"value="sa"/>
<propertyname="password"value=""/>
</bean>
</property>
</bean>
<beanid="component"class="MyDaoImpl">
<propertyname="connectionFactory"ref="connectionFactory"/>
</bean>
managedmodeJ2EE)
<beanid="targetConnectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="eis/blackbox"/>
</bean>
<beanid="connectionFactory"
class="org.springframework.jca.cci.connection.ConnectionSpecConnectionFactoryAdapter">
<propertyname="targetConnectionFactory"ref="targetConnectionFactory"/>
<propertyname="connectionSpec">
<beanclass="com.sun.connector.cciblackbox.CciConnectionSpec">
<propertyname="user"value="sa"/>
<propertyname="password"value=""/>
</bean>
</property>
</bean>
<beanid="component"class="MyDaoImpl">
<propertyname="connectionFactory"ref="connectionFactory"/>
</bean>
21.4.6.MappingCommAreaOperation MappingCommAreaOperationIBMECIECICICSCCI InteractionSpecCICS
publicabstractclassEciMappingOperationextendsMappingCommAreaOperation{
publicEciMappingOperation(ConnectionFactoryconnectionFactory,StringprogramName){
setConnectionFactory(connectionFactory);
ECIInteractionSpecinteractionSpec=newECIInteractionSpec(),
interactionSpec.setFunctionName(programName);
interactionSpec.setInteractionVerb(ECIInteractionSpec.SYNC_SEND_RECEIVE);
interactionSpec.setCommareaLength(30);
setInteractionSpec(interactionSpec);
setOutputRecordCreator(newEciOutputRecordCreator());
}
privatestaticclassEciOutputRecordCreatorimplementsRecordCreator{
publicRecordcreateRecord(RecordFactoryrecordFactory)throwsResourceException{
returnnewCommAreaRecord();
}
}
}
The abstract EciMappingOperation class can then be subclassed tospecifymappingsbetweencustomobjectsandRecords.
EciMappingOperation Records
publicclassMyDaoImplextendsCciDaoSupportimplementsMyDao{
publicOutputObjectgetData(Integerid){
EciMappingOperationquery=newEciMappingOperation(getConnectionFactory(),"MYPROG"){
protectedabstractbyte[]objectToBytes(ObjectinObject)throwsIOException{
Integerid=(Integer)inObject;
returnString.valueOf(id);
}
protectedabstractObjectbytesToObject(byte[]bytes)throwsIOException;
Stringstr=newString(bytes);
Stringfield1=str.substring(0,6);
Stringfield2=str.substring(6,1);
Stringfield3=str.substring(7,1);
returnnewOutputObject(field1,field2,field3);
}
});
return(OutputObject)query.execute(newInteger(id));
}
}
Springbeansnon-managedmode
<beanid="managedConnectionFactory"class="com.ibm.connector2.cics.ECIManagedConnectionFactory">
<propertyname="serverName"value="TXSERIES"/>
<propertyname="connectionURL"value="local:"/>
<propertyname="userName"value="CICSUSER"/>
<propertyname="password"value="CICS"/>
</bean>
<beanid="connectionFactory"class="org.springframework.jca.support.LocalConnectionFactoryBean">
<propertyname="managedConnectionFactory"ref="managedConnectionFactory"/>
</bean>
<beanid="component"class="MyDaoImpl">
<propertyname="connectionFactory"ref="connectionFactory"/>
</bean>
managedmodeJ2EE
<beanid="connectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="eis/cicseci"/>
</bean>
<beanid="component"class="MyDaoImpl">
<propertyname="connectionFactory"ref="connectionFactory"/>
</bean>
21.5.JCAresourceadapters ra.xmlCICSECIIMS
<connector>
<resourceadapter>
<!--<transaction-support>NoTransaction</transaction-support>-->
<!--<transaction-support>LocalTransaction</transaction-support>-->
<transaction-support>XATransaction</transaction-support>
<resourceadapter>
<connector>
Spring JtaTransactionManager
CCIConnectionFactory SpringCCI JDBCDataSourceTransactionManagerCCIAPICciLocalTransactionManager CCI SpringPlatformTransactionManager
<beanid="eciConnectionFactory"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="eis/cicseci"/>
</bean>
<beanid="eciTransactionManager"
class="org.springframework.jca.cci.connection.CciLocalTransactionManager">
<propertyname="connectionFactory"ref="eciConnectionFactory"/>
</bean>
Spring Spring PlatformTransactionManager
JtaTransactionManager CciLocalTransactionManagerSpring 9
22Spring
22.1.22.2.Spring
22.2.1.MailSender SimpleMailMessage22.2.2. JavaMailSender MimeMessagePreparator
22.3.MimeMessageHelper22.3.1.(inlineresources)22.3.2.
jarclasspathSpringFramework
JavaMailmail.jar
JAFactivation.jar
SpringFrameworkSpring-with-dependenciesrelease()
22.1.SpringSpringorg.springframework.mailMailSenderSimpleMailMessagefrom, to,cc,subject,text MailExceptioncheckedExceptionJavadocsJavaMail,MIME,Spring MailSender
,
org.springframework.mail.javamail.JavaMailSenderSpringorg.springframework.mail.javamail.MimeMessagePreparator,JavaMailMIME
22.2.SpringOrderManager:
publicinterfaceOrderManager{
voidplaceOrder(Orderorder);
}
email,
22.2.1.MailSender SimpleMailMessage
importorg.springframework.mail.MailException;
importorg.springframework.mail.MailSender;
importorg.springframework.mail.SimpleMailMessage;
publicclassSimpleOrderManagerimplementsOrderManager{
privateMailSendermailSender;
privateSimpleMailMessagetemplateMessage;
publicvoidsetMailSender(MailSendermailSender){
this.mailSender=mailSender;
}
publicvoidsetTemplateMessage(SimpleMailMessagetemplateMessage){
this.templateMessage=templateMessage;
}
publicvoidplaceOrder(Orderorder){
//Dothebusinesscalculations...
//Callthecollaboratorstopersisttheorder...
//Createathreadsafe"copy"ofthetemplatemessageandcustomizeit
SimpleMailMessagemsg=newSimpleMailMessage(this.templateMessage);
msg.setTo(order.getCustomer().getEmailAddress());
msg.setText(
"Dear"+order.getCustomer().getFirstName()
+order.getCustomer().getLastName()
+",thankyouforplacingorder.Yourordernumberis"
+order.getOrderNumber());
try{
this.mailSender.send(msg);
}
catch(MailExceptionex){
//simplylogitandgoon...
System.err.println(ex.getMessage());
}
}
}
bean:
<beanid="mailSender"class="org.springframework.mail.javamail.JavaMailSenderImpl">
<propertyname="host"value="mail.mycompany.com"/>
</bean>
<!--thisisatemplatemessagethatwecanpre-loadwithdefaultstate-->
<beanid="templateMessage"class="org.springframework.mail.SimpleMailMessage">
<propertyname="from"value="customerservice@mycompany.com"/>
<propertyname="subject"value="Yourorder"/>
</bean>
<beanid="orderManager"class="com.mycompany.businessapp.support.SimpleOrderManager">
<propertyname="mailSender"ref="mailSender"/>
<propertyname="templateMessage"ref="templateMessage"/>
</bean>
22.2.2. JavaMailSender MimeMessagePreparator
OrderManager, MimeMessagePreparator mailSender
JavaMailSenderJavaMail MimeMessage
importjavax.mail.Message;
importjavax.mail.MessagingException;
importjavax.mail.internet.InternetAddress;
importjavax.mail.internet.MimeMessage;
importjavax.mail.internet.MimeMessage;
importorg.springframework.mail.MailException;
importorg.springframework.mail.javamail.JavaMailSender;
importorg.springframework.mail.javamail.MimeMessagePreparator;
publicclassSimpleOrderManagerimplementsOrderManager{
privateJavaMailSendermailSender;
publicvoidsetMailSender(JavaMailSendermailSender){
this.mailSender=mailSender;
}
publicvoidplaceOrder(finalOrderorder){
//Dothebusinesscalculations...
//Callthecollaboratorstopersisttheorder...
MimeMessagePreparatorpreparator=newMimeMessagePreparator(){
publicvoidprepare(MimeMessagemimeMessage)throwsException{
mimeMessage.setRecipient(Message.RecipientType.TO,
newInternetAddress(order.getCustomer().getEmailAddress()));
mimeMessage.setFrom(newInternetAddress("mail@mycompany.com"));
mimeMessage.setText(
"Dear"+order.getCustomer().getFirstName()+""
+order.getCustomer().getLastName()
+",thankyouforplacingorder.Yourordernumberis"
+order.getOrderNumber());
}
};
try{
this.mailSender.send(preparator);
}
catch(MailExceptionex){
//simplylogitandgoon...
System.err.println(ex.getMessage());
}
}
}
SpringAOP OrderManagerjoinpointSpring FrameworkMailSenderJavaMailJason Hunter MailMessage
com.oreilly.servletJavadocs
22.3. MimeMessageHelper
org.springframework.mail.javamail.MimeMessageHelperJavaMailJavaMailAPI MimeMessageHelperMimeMessage
//ofcourseyouwoulduseDIinanyreal-worldcases
JavaMailSenderImplsender=newJavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessagemessage=sender.createMimeMessage();
MimeMessageHelperhelper=newMimeMessageHelper(message);
helper.setTo("test@host.com");
helper.setText("Thankyouforordering!");
sender.send(message);
22.3.1.(inlineresources)Multipartemail(inlineresources)
22.3.1.1.MimeMessageHelperemailJPEG
JavaMailSenderImplsender=newJavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessagemessage=sender.createMimeMessage();
//usethetrueflagtoindicateyouneedamultipartmessage
MimeMessageHelperhelper=newMimeMessageHelper(message,true);
helper.setTo("test@host.com");
helper.setText("Checkoutthisimage!");
//let'sattachtheinfamouswindowsSamplefile(thistimecopiedtoc:/)
FileSystemResourcefile=newFileSystemResource(newFile("c:/Sample.jpg"));
helper.addAttachment("CoolImage.jpg",file);
sender.send(message);
22.3.1.2.MimeMessageHelperemail
JavaMailSenderImplsender=newJavaMailSenderImpl();
sender.setHost("mail.host.com");
MimeMessagemessage=sender.createMimeMessage();
//usethetrueflagtoindicateyouneedamultipartmessage
MimeMessageHelperhelper=newMimeMessageHelper(message,true);
helper.setTo("test@host.com");
//usethetrueflagtoindicatethetextincludedisHTML
helper.setText("<html><body><imgsrc='cid:identifier1234'></body></html>",true);
//let'sincludetheinfamouswindowsSamplefile(thistimecopiedtoc:/)
FileSystemResourceres=newFileSystemResource(newFile("c:/Sample.jpg"));
helper.addInline("identifier1234",res);
sender.send(message);
Content-ID( identifier1234)mime
22.3.2.message.setText(..) API
,JavaHTML
Java……FreeMarkerVelocityVelocity
22.3.2.1.VelocityVelocityVelocityclasspath VelocityVelocityHTML
#inthecom/foo/package
<html>
<body>
<h3>Hi${user.userName},welcometotheChippingSodburyOn-the-Hillmessageboards!</h3>
<div>
Youremailaddressis<ahref="mailto:${user.emailAddress}">${user.emailAddress}</a>.
</div>
</body>
</html>
SpringXMLVelocity
packagecom.foo;
importorg.apache.velocity.app.VelocityEngine;
importorg.springframework.mail.javamail.JavaMailSender;
importorg.springframework.mail.javamail.MimeMessageHelper;
importorg.springframework.mail.javamail.MimeMessagePreparator;
importorg.springframework.ui.velocity.VelocityEngineUtils;
importjavax.mail.internet.MimeMessage;
importjava.util.HashMap;
importjava.util.Map;
publicclassSimpleRegistrationServiceimplementsRegistrationService{
privateJavaMailSendermailSender;
privateVelocityEnginevelocityEngine;
publicvoidsetMailSender(JavaMailSendermailSender){
this.mailSender=mailSender;
}
publicvoidsetVelocityEngine(VelocityEnginevelocityEngine){
this.velocityEngine=velocityEngine;
}
publicvoidregister(Useruser){
//Dotheregistrationlogic...
sendConfirmationEmail(user);
}
privatevoidsendConfirmationEmail(finalUseruser){
MimeMessagePreparatorpreparator=newMimeMessagePreparator(){
publicvoidprepare(MimeMessagemimeMessage)throwsException{
MimeMessageHelpermessage=newMimeMessageHelper(mimeMessage);
message.setTo(user.getEmailAddress());
message.setFrom("webmaster@csonth.gov.uk");//couldbeparameterized...
Mapmodel=newHashMap();
model.put("user",user);
Stringtext=VelocityEngineUtils.mergeTemplateIntoString(
velocityEngine,"com/dns/registration-confirmation.vm",model);
message.setText(text,true);
}
};
this.mailSender.send(preparator);
}
}
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanid="mailSender"class="org.springframework.mail.javamail.JavaMailSenderImpl">
<propertyname="host"value="mail.csonth.gov.uk"/>
</bean>
<beanid="registrationService"class="com.foo.SimpleRegistrationService">
<propertyname="mailSender"ref="mailSender"/>
<propertyname="velocityEngine"ref="velocityEngine"/>
</bean>
<beanid="velocityEngine"class="org.springframework.ui.velocity.VelocityEngineFactoryBean">
<propertyname="velocityProperties">
<value>
resource.loader=class
class.resource.loader.class=org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader
</value>
</property>
</bean>
</beans>
23Spring(Scheduling)(ThreadPooling)
23.1.23.2.OpenSymphonyQuartz
23.2.1.JobDetailBean23.2.2. MethodInvokingJobDetailFactoryBean
23.2.3.triggersSchedulerFactoryBean23.3.JDKTimer
23.3.1.timers23.3.2. MethodInvokingTimerTaskFactoryBean
23.3.3. TimerFactoryBean
23.4.SpringTaskExecutor23.4.1.TaskExecutor23.4.2.TaskExecutor23.4.3.TaskExecutor
23.1.SpringSpringJDK1.3 TimerQuartzScheduler(http://www.opensymphony.com/quartz/) FactoryBeanTimerTrigger
QuartzScheduler Timer MethodInvokingFactoryBeanSpringJava1.3,1.4,5JEE
23.2.OpenSymphonyQuartzQuartz Trigger,JobJobDetailQuartz http://www.opensymphony.com/quartz
SpringSpringuartz
23.2.1.JobDetailBeanJobDetailSpring JobDetailBeanJobDetail
<beanname="exampleJob"class="org.springframework.scheduling.quartz.JobDetailBean">
<propertyname="jobClass"value="example.ExampleJob"/>
<propertyname="jobDataAsMap">
<map>
<entrykey="timeout"value="5"/>
</map>
</property>
</bean>
Jobdetailbeanjob( ExampleJob) jobdatamaptimeoutJobdatamapJobExecutionContext) JobDetailBeanjobdatamapjobExampleJob timeout JobDetailBean
packageexample;
publicclassExampleJobextendsQuartzJobBean{
privateinttimeout;
/**
*SettercalledaftertheExampleJobisinstantiated
*withthevaluefromtheJobDetailBean(5)
*/
publicvoidsetTimeout(inttimeout){
this.timeout=timeout;
}
protectedvoidexecuteInternal(JobExecutionContextctx)throwsJobExecutionException{
//dotheactualwork
}
}
Jobdetailbeannamegroup,jobjobjobdetailbean exampleJob
23.2.2. MethodInvokingJobDetailFactoryBean
, MethodInvokingJobDetailFactoryBean
<beanid="jobDetail"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<propertyname="targetObject"ref="exampleBusinessObject"/>
<propertyname="targetMethod"value="doIt"/>
</bean>
exampleBusinessObjectdoIt
publicclassExampleBusinessObject{
//propertiesandcollaborators
publicvoiddoIt(){
//dotheactualwork
}
}
<beanid="exampleBusinessObject"class="examples.ExampleBusinessObject"/>
MethodInvokingJobDetailFactoryBeanjob,QuartzJobsjobs JobDetail
Stateful jobjobjobs,concurrentfalse
<beanid="jobDetail"class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
<propertyname="targetObject"ref="exampleBusinessObject"/>
<propertyname="targetMethod"value="doIt"/>
<propertyname="concurrent"value="false"/>
</bean>
jobs
23.2.3.triggers SchedulerFactoryBean
jobdetails,jobsbeantriggersSpringtriggers CronTriggerBeanSimpleTriggerBean
TriggersSpring SchedulerFactoryBeantriggers SchedulerFactoryBean
triggers
<beanid="simpleTrigger"class="org.springframework.scheduling.quartz.SimpleTriggerBean">
<!--seetheexampleofmethodinvokingjobabove-->
<propertyname="jobDetail"ref="jobDetail"/>
<!--10seconds-->
<propertyname="startDelay"value="10000"/>
<!--repeatevery50seconds-->
<propertyname="repeatInterval"value="50000"/>
</bean>
<beanid="cronTrigger"class="org.springframework.scheduling.quartz.CronTriggerBean">
<propertyname="jobDetail"ref="exampleJob"/>
<!--runeverymorningat6AM-->
<propertyname="cronExpression"value="006**?"/>
</bean>
triggers10506
<beanclass="org.springframework.scheduling.quartz.SchedulerFactoryBean">
<propertyname="triggers">
<list>
<refbean="cronTrigger"/>
<refbean="simpleTrigger"/>
</list>
</property>
</bean>
SchedulerFactoryBeanjobdetailsCalendars,QuartzJavaDOC(http://static.springframework.org/spring/docs/2.5.x/api/org/springframework/scheduling/quartz/SchedulerFactoryBean.html
23.3.JDKTimerJDKTimertimertimertimers
23.3.1.timersTimerTasktimertasksQuartzjobs:
publicclassCheckEmailAddressesextendsTimerTask{
privateListemailAddresses;
publicvoidsetEmailAddresses(ListemailAddresses){
this.emailAddresses=emailAddresses;
}
publicvoidrun(){
//iterateoverallemailaddressesandarchivethem
}
}
:
<beanid="checkEmail"class="examples.CheckEmailAddress">
<propertyname="emailAddresses">
<list>
<value>test@springframework.org</value>
<value>foo@bar.com</value>
<value>john@doe.net</value>
</list>
</property>
</bean>
<beanid="scheduledTask"class="org.springframework.scheduling.timer.ScheduledTimerTask">
<!--wait10secondsbeforestartingrepeatedexecution-->
<propertyname="delay"value="10000"/>
<!--runevery50seconds-->
<propertyname="period"value="50000"/>
<propertyname="timerTask"ref="checkEmail"/>
</bean>
period0
23.3.2. MethodInvokingTimerTaskFactoryBean
Quartz Timer:
<beanid="doIt"class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
<propertyname="targetObject"ref="exampleBusinessObject"/>
<propertyname="targetMethod"value="doIt"/>
</bean>
exampleBusinessObjectdoIt():
publicclassBusinessObject{
//propertiesandcollaborators
publicvoiddoIt(){
//dotheactualwork
}
}
ScheduledTimerTasktimerTaskdoItbeandoIt
23.3.3. TimerFactoryBean
TimerFactoryBeanQuartzSchedulerFactoryBean TimerFactoryBean
Timer
<beanid="timerFactory"class="org.springframework.scheduling.timer.TimerFactoryBean">
<propertyname="scheduledTimerTasks">
<list>
<!--seetheexampleabove-->
<refbean="scheduledTask"/>
</list>
</property>
</bean>
java.util.concurrent
DougLeaDawidKurzyniecjava.util.concurrent
23.4.SpringTaskExecutorSpring2.0(Executor)ExecutorJava5 SpringJava1.31.41.3,1.4,5,JavaEE
23.4.1.TaskExecutorSpring TaskExecutorjava.util.concurrent.Executor Java5execute(Runnabletask)
TaskExecutorSpring ApplicationEventMulticaster
AbstractMessageListenerContainerQuartzTaskExecutor bean
23.4.2.TaskExecutorSpring TaskExecutor
SimpleAsyncTaskExecutor
SyncTaskExecutortestcaseConcurrentTaskExecutorJava5 java.util.concurrent.Executor, ThreadPoolTaskExecutor
Executorbean ConcurrentTaskExecutor,ThreadPoolTaskExecutor ConcurrentTaskExecutor
SimpleThreadPoolTaskExecutorQuartz SimpleThreadPoolSpringQuartzQuartz
ThreadPoolTaskExecutorJava5beanproperties
java.util.concurrent.ThreadPoolExecutorTaskExecutor
ScheduledThreadPoolExecutor,ConcurrentTaskExecutor
CommonJBEAIBMJavaEEBEAIBM
TimerTaskExecutor
TimerTask SyncTaskExecutor
WorkManagerTaskExecutor
CommonJWorkManagerSpringcontextCommonJWorkManagerSimpleThreadPoolTaskExecutor
WorkManagerWorkManager
23.4.3. TaskExecutor
Spring TaskExecutorJavaBeansbean, ThreadPoolTaskExecutor
importorg.springframework.core.task.TaskExecutor;
publicclassTaskExecutorExample{
privateclassMessagePrinterTaskimplementsRunnable{
privateStringmessage;
publicMessagePrinterTask(Stringmessage){
this.message=message;
}
publicvoidrun(){
System.out.println(message);
}
}
privateTaskExecutortaskExecutor;
publicTaskExecutorExample(TaskExecutortaskExecutor){
this.taskExecutor=taskExecutor;
}
publicvoidprintMessages(){
for(inti=0;i<25;i++){
taskExecutor.execute(newMessagePrinterTask("Message"+i));
}
}
}
Runnable TaskExecutor
TaskExecutorbeanproperties
<beanid="taskExecutor"class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<propertyname="corePoolSize"value="5"/>
<propertyname="maxPoolSize"value="10"/>
<propertyname="queueCapacity"value="25"/>
</bean>
<beanid="taskExecutorExample"class="TaskExecutorExample">
<constructor-argref="taskExecutor"/>
</bean>
24
24.1.24.2.24.3.bean
24.3.1.24.3.2.JRubybeans24.3.3.Groovybeans24.3.4.BeanShellbeans
24.4.24.4.1.SpringMVC24.4.2.Validator
24.5.Bitsandbobs24.5.1.AOP-bean24.5.2.
24.6.
aJava cSpringSpring
24.1.Spring2.0SpringJRubySpringSpring
JRuby
Groovy
BeanShell24.4“” Spring
Spring2.0Spring 1.2.x
24.2.SpringbeanbeanGroovySpringGroovybean MessengerJava MessengerGroovy
packageorg.springframework.scripting;
publicinterfaceMessenger{
StringgetMessage();
}
Messenger
packageorg.springframework.scripting;
publicclassDefaultBookingServiceimplementsBookingService{
privateMessengermessenger;
publicvoidsetMessenger(Messengermessenger){
this.messenger=messenger;
}
publicvoidprocessBooking(){
//usetheinjectedMessengerobject...
}
}
GroovyMessenger
//fromthefile'Messenger.groovy'
packageorg.springframework.scripting.groovy;
//importtheMessengerinterface(writteninJava)thatistobeimplemented
importorg.springframework.scripting.Messenger
//definetheimplementationinGroovy
classGroovyMessengerimplementsMessenger{
Stringmessage
}
beanGroovy MessengerDefaultBookingService
dynamic-language-backedbeanSpringXMLXMLSchemaSpring ApplicationContextIoCSpring BeanFactory
dynamic-language-backedbeanSpringXMLSchema A,XMLSchema-basedconfiguration
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
<!--thisisthebeandefinitionfortheGroovy-backedMessenger
<lang:groovyid="messenger"script-source="classpath:Messenger.groovy">
<lang:propertyname="message"value="ICanDoTheFrug"/>
</lang:groovy>
<!--anotherwisenormalbeanthatwillbeinjectedbytheGroovy-backed
<beanid="bookingService"class="x.y.DefaultBookingService">
<propertyname="messenger"ref="messenger"/>
</bean>
</beans>
bookingServicebean DefaultBookingService messenger
MessengerJavaGroovyXML
XMLSchemaSpring2.0XMLSchemaSpringXMLDTDXMLSchema <lang:language/>
SpringXMLSchemaSpring
24.3.beanSpringSpringbeanGroovyGroovy
24.3.1.dynamic-language-backedbean
:)
XML <lang:language/>dynamic-language-backedbeanSpringAPI---beanbean
Spring
24.3.1.1.<lang:language/>dynamic-language-backedbeanbeanJavabeanJavabeandynamic language-backed bean<lang:language/>
<lang:language/>
<lang:jruby/>JRuby
<lang:groovy/>Groovy
<lang:bsh/>BeanShellbean
24.3.1.2.RefreshablebeanSpring 'refreshablebean'refreshablebeandynamic-language-backedbeandynamic-language-backedbeanSpringbeanbeanwebdynamic-language-backedbean
offrefreshablebeanrefreshablebeanbean SpringXMLrefreshablebean
<beans>
<!--thisbeanisnow'refreshable'duetothepresenceofthe'refresh-check-delay'attribute-->
<lang:groovyid="messenger"
refresh-check-delay="5000"<!--switchesrefreshingonwith5secondsbetweenchecks-->
script-source="classpath:Messenger.groovy">
<lang:propertyname="message"value="ICanDoTheFrug"/>
</lang:groovy>
<beanid="bookingService"class="x.y.DefaultBookingService">
<propertyname="messenger"ref="messenger"/>
</bean>
</beans>
'messenger'bean'refresh-check-delay'beanbean
refreshable 'jumping-through-hoops-to-pause-the-execution'System.in.read()dynamic-language-backedbean
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
importorg.springframework.scripting.Messenger;
publicfinalclassBoot{
publicstaticvoidmain(finalString[]args)throwsException{
ApplicationContextctx=newClassPathXmlApplicationContext("beans.xml");
Messengermessenger=(Messenger)ctx.getBean("messenger");
System.out.println(messenger.getMessage());
//pauseexecutionwhileIgooffandmakechangestothesourcefile...
System.in.read();
System.out.println(messenger.getMessage());
}
}
MessengergetMessage()message Messenger.groovy
packageorg.springframework.scripting
classGroovyMessengerimplementsMessenger{
privateStringmessage="Bingo"
publicStringgetMessage(){
//changetheimplementationtosurroundthemessageinquotes
return"'"+this.message+"'"
}
publicvoidsetMessage(Stringmessage){
this.message=message
}
}
ICanDoTheFrugdynamic-language-backedgetMessage()'ICanDoTheFrug'
'refresh-check-delay'beanbeanrefreshablebean <lang:inline-script/> 24.3.1.3“”
24.3.1.3.Springbean <lang:inline-script/>
<lang:groovyid="messenger">
<lang:inline-script>
packageorg.springframework.scripting.groovy;
importorg.springframework.scripting.Messenger
classGroovyMessengerimplementsMessenger{
Stringmessage
}
</lang:inline-script>
<lang:propertyname="message"value="ICanDoTheFrug"/>
</lang:groovy>
Spring <lang:inline-script/>
Validator 24.4.2“Validator”
JRubybeanSpringXML
<lang:jrubyid="messenger"script-interfaces="org.springframework.scripting.Messenger">
<lang:inline-script>
require'java'
include_class'org.springframework.scripting.Messenger'
classRubyMessenger<Messenger
defsetMessage(message)
@@message=message
end
defgetMessage
@@message
end
end
</lang:inline-script>
<lang:propertyname="message"value="HelloWorld!"/>
</lang:jruby>
24.3.1.4.dynamic-language-backedbeanSpringdynamic-language-backedbeandynamic-language-backedbean 100
//fromthefile'Messenger.groovy'
packageorg.springframework.scripting.groovy;
importorg.springframework.scripting.Messenger
classGroovyMessengerimplementsMessenger{
GroovyMessenger(){}
JRubySpringJRubyclasspathSpringJRuby
jruby.jar
cglib-nodep-2.1_3.jar
//thisconstructorisnotavailableforConstructorInjection
GroovyMessenger(Stringmessage){
this.message=message;
}
Stringmessage
StringanotherMessage
}
<lang:groovyid="badMessenger"
script-source="classpath:Messenger.groovy">
<!--thisnextconstructorargumentwill*not*beinjectedintothe
<!--infact,thisisn'tevenallowedaccordingtotheschema-->
<constructor-argvalue="Thiswill*not*work"/>
<!--onlypropertyvaluesareinjectedintothedynamic-language-backedobject-->
<lang:propertyname="anotherMessage"value="Passedstraightthroughtothedynamic-language-backedobject"/>
</lang>
setter
24.3.2.JRubybeansJRuby...“JRubyRubyJava ”SpringSpringJRubybeanJRubyRubySpringJRuby <lang:ruby>'script-
interfaces'SpringJDKJRubybean,JRubybeanJRuby Messenger
packageorg.springframework.scripting;
publicinterfaceMessenger{
StringgetMessage();
}
require'java'
classRubyMessenger
includeorg.springframework.scripting.Messenger
defsetMessage(message)
@@message=message
end
defgetMessage
@@message
end
end
#thislastlineisnotessential(butseebelow)
RubyMessenger.new
SpringXML RubyMessenger(JRubybean)
<lang:jrubyid="messageService"
script-interfaces="org.springframework.scripting.Messenger"
script-source="classpath:RubyMessenger.rb">
<lang:propertyname="message"value="HelloWorld!"/>
</lang:jruby>
JRuby 'RubyMessenger.new'SpringJRubyJRubyJRubydynamic-language-backedbeanJRuby
require'java'
include_class'org.springframework.scripting.Messenger'
#classdefinitionsameasabove...
#instantiateandreturnanewinstanceoftheRubyMessengerclass
RubyMessenger.new
GroovySpringGroovyclasspathjar
groovy-1.0.jar
asm-2.2.2.jar
antlr-2.7.6.jar
SpringJRubyJRubySpringJRubyJRuby ScriptCompilationExceptionSpringdynamic-language-backedbean,:org.springframework.scripting.ScriptCompilationException:
CompilationofJRubyscriptreturned''
JRuby-dynamic-language-backedbean()JRuby(Spring)24.4“” JRubybean.
24.3.3.GroovybeansGroovy...“GroovyJava2PythonRubySmalltalkJavaJavaGroovy-dynamic-language-backedbean (Spring)
Groovy1.4JDK
packageorg.springframework.scripting;
publicinterfaceCalculator{
intadd(intx,inty);
}
Groovy Calculator
//fromthefile'calculator.groovy'
packageorg.springframework.scripting.groovy
classGroovyCalculatorimplementsCalculator{
intadd(intx,inty){
x+y
}
}
<--fromthefile'beans.xml'-->
<beans>
<lang:groovyid="calculator"script-source="classpath:calculator.groovy"/>
</beans>
packageorg.springframework.scripting;
importorg.springframework.context.ApplicationContext;
importorg.springframework.context.support.ClassPathXmlApplicationContext;
publicclassMain{
publicstaticvoidMain(String[]args){
ApplicationContextctx=newClassPathXmlApplicationContext("beans.xml");
Calculatorcalc=(Calculator)ctx.getBean("calculator");
System.out.println(calc.add(2,8));
}
}
10 24.4“”
, GroovyclassGroovyJava(public)
24.3.3.1.GroovyGroovyObjectCustomizer Groovybean
publicinterfaceGroovyObjectCustomizer{
voidcustomize(GroovyObjectgoo);
}
SpringGroovybean GroovyObjectGroovyObject MetaClass
publicfinalclassSimpleMethodTracingCustomizerimplementsGroovyObjectCustomizer{
publicvoidcustomize(GroovyObjectgoo){
DelegatingMetaClassmetaClass=newDelegatingMetaClass(goo.getMetaClass()){
BeanShellSpringBeanShellclasspath
bsh-2.0b4.jar
cglib-nodep-2.1_3.jar
Spring-with-dependecies
publicObjectinvokeMethod(Objectobject,StringmethodName,Object[]arguments){
System.out.println("Invoking'"+methodName+"'.");
returnsuper.invokeMethod(object,methodName,arguments);
}
};
metaClass.initialize();
goo.setMetaClass(metaClass);
}
}
GroovyGroovy
<!--definetheGroovyObjectCustomizerjustlikeanyotherbean-->
<beanid="tracingCustomizer"class="example.SimpleMethodTracingCustomizer"/>
<!--...andplugitintothedesiredGroovybeanviathe'
<lang:groovyid="calculator"
script-source="classpath:org/springframework/scripting/groovy/Calculator.groovy"
customizer-ref="tracingCustomizer"/>
Spring2.0 GroovyObjectCustomizer
<beanid="calculator"class="org.springframework.scripting.groovy.GroovyScriptFactory">
<constructor-argvalue="classpath:org/springframework/scripting/groovy/Calculator.groovy"/>
<!--definetheGroovyObjectCustomizer(asaninnerbean)-->
<constructor-arg>
<beanid="tracingCustomizer"class="example.SimpleMethodTracingCustomizer"/>
</constructor-arg>
</bean>
<beanclass="org.springframework.scripting.support.ScriptFactoryPostProcessor"/>
24.3.4.BeanShellbeansBeanShell...“BeanShellJavaJavaBeanShellJavaPerlJavaScript
”GroovyBeanShellbeanSpring
BeanShell <lang:bsh>'script-
interfaces'SpringJDKBeanShellbean BeanShell-backedJDK
BeanShellbean Messenger
packageorg.springframework.scripting;
publicinterfaceMessenger{
StringgetMessage();
}
HereistheBeanShell'implementation'(thetermisusedlooselyhere)oftheMessengerinterface.BeanShellMessenger
Stringmessage;
StringgetMessage(){
returnmessage;
}
voidsetMessage(StringaMessage){
message=aMessage;
}
SpringXML“”“”
<lang:bshid="messageService"script-source="classpath:BshMessenger.bsh"
script-interfaces="org.springframework.scripting.Messenger">
<lang:propertyname="message"value="HelloWorld!"/>
</lang:bsh>
24.4“” BeanShellbean
24.4.SpringbeanSpring(Spring)
24.4.1.SpringMVCdynamic-language-backedbeanSpringMVCSpringMVCwebSpringMVCwebSpring SpringMVCdynamic-language-backedbean()bean()
“”dynamic-language-backedbean'refreshablebeans' 24.3.1.2“Refreshablebean”
Groovy org.springframework.web.servlet.mvc.Controller
Spring 'samples/showcases/dynamvc/'
//fromthefile'/WEB-INF/groovy/FortuneController.groovy'
packageorg.springframework.showcase.fortune.web
importorg.springframework.showcase.fortune.service.FortuneService
importorg.springframework.showcase.fortune.domain.Fortune
importorg.springframework.web.servlet.ModelAndView
importorg.springframework.web.servlet.mvc.Controller
importjavax.servlet.http.HttpServletRequest
importjavax.servlet.http.HttpServletResponse
classFortuneControllerimplementsController{
@PropertyFortuneServicefortuneService
ModelAndViewhandleRequest(
HttpServletRequestrequest,HttpServletResponsehttpServletResponse){
returnnewModelAndView("tell","fortune",this.fortuneService.tellFortune())
}
}
<lang:groovyid="fortune"
refresh-check-delay="3000"
script-source="/WEB-INF/groovy/FortuneController.groovy">
<lang:propertyname="fortuneService"ref="fortuneService"/>
</lang:groovy>
24.4.2.ValidatorSpringdynamic-language-backedbeandynamic-language-backedbean
“”dynamic-language-backedbean'refreshablebeans' 24.3.1.2“Refreshablebean”
Groovy org.springframework.validation.Validator
Spring Validator”
importorg.springframework.validation.Validator
importorg.springframework.validation.Errors
importorg.springframework.beans.TestBean
classTestBeanValidatorimplementsValidator{
booleansupports(Classclazz){
returnTestBean.class.isAssignableFrom(clazz)
}
voidvalidate(Objectbean,Errorserrors){
if(bean.name?.trim()?.size()>0){
return
}
errors.reject("whitespace","Cannotbecomposedwhollyofwhitespace.")
}
}
24.5.Bitsandbobs
24.5.Bitsandbobs
24.5.1.AOP-beanSpringAOPbeanSpringAOPbean Springbean
24.5.2.beanbean <lang:language/>
singletonbeanscopeGroovybeanprototype
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd">
<lang:groovyid="messenger"script-source="classpath:Messenger.groovy"
<lang:propertyname="message"value="ICanDoTheRoboCop"/>
</lang:groovy>
<beanid="bookingService"class="x.y.DefaultBookingService">
<propertyname="messenger"ref="messenger"/>
</bean>
</beans>
3 IoC() 3.4“Bean” Spring
24.6.
JRuby
Groovy
BeanShellSpringSpring
25
25.1.25.2.Spring25.3.
25.3.1.@Required
25.3.2.Spring@Annotations25.4.JakartaCommonsAttributes25.5.SpringAOP
25.5.1.25.5.2.
25.1.
/**
*Normalcommentshere
*@@org.springframework.transaction.interceptor.DefaultTransactionAttribute()
*/
publicclassPetStoreImplimplementsPetStoreFacade,OrderService{
/**
*Normalcommentshere
*@@org.springframework.transaction.interceptor.RuleBasedTransactionAttribute()
*@@org.springframework.transaction.interceptor.RollbackRuleAttribute(Exception.class)
*@@org.springframework.transaction.interceptor.NoRollbackRuleAttribute("ServletException")
*/
publicvoidechoException(Exceptionex)throwsException{
....
}
JakartaCommonsAttributesXDoclet(Java)Microsoft.NET (pooling)J2EEEJBXML
JavaJava(JSR-175Java5) SpringJMX(AspectJ)Java5 SpringJava1.4JVMSpringXDocletJava1.4CommonsAttributes
25.2.SpringSpringSpring(facade)
Java5
Java5
Java5JavaAPISpring
1.31.4Spring
APICommonsAttributes(Spring1.0-1.2)SpringSpringAttributes
publicinterfaceAttributes{
CollectiongetAttributes(ClasstargetClass);
CollectiongetAttributes(ClasstargetClass,Classfilter);
CollectiongetAttributes(MethodtargetMethod);
CollectiongetAttributes(MethodtargetMethod,Classfilter);
CollectiongetAttributes(FieldtargetField);
CollectiongetAttributes(FieldtargetField,Classfilter);
}
JSR-175.NET Object String NanningAspects ObjectJavaBeanCommonsAttributesSpringAPI Attributes
25.3.SpringJava5+
25.3.1.@Required
org.springframework.beans.factory.annotation@ Required(setter)) Exception
publicclassSimpleMovieLister{
//theSimpleMovieListerhasadependencyontheMovieFinder
privateMovieFindermovieFinder;
//asettermethodsothattheSpringcontainercan'inject'a
@Required
publicvoidsetMovieFinder(MovieFindermovieFinder){
this.movieFinder=movieFinder;
}
//businesslogicthatactually'uses'theinjectedMovieFinder
}
SimpleMovieListerBeanDefinitionsXML
<beanid="movieLister"class="x.y.SimpleMovieLister">
<!--whoops,noMovieFinderisset(andthispropertyis@
</bean>
Spring()
Exceptioninthread"main"java.lang.IllegalArgumentException:
Property'movieFinder'isrequiredforbean'movieLister'.
()Spring '' 'setter' @RequiredAnnotationBeanPostProcessor BeanPostProcessor
@Required'' beanSpringXML
<beanclass="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor"/>
RequiredAnnotationBeanPostProcessor Annotation @RequiredAnnotationBeanPostProcessor
(/)@ Mandatory RequiredAnnotationBeanPostProcessor
@Mandatory
<beanclass="org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor">
<propertyname="requiredAnnotationType"value="your.company.package.Mandatory"/>
</bean>
@Mandatory (target)(runtimeretentionpolicy)
packageyour.company.package;
importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
importjava.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public@interfaceMandatory{
}
25.3.2.Spring@AnnotationsSpring
9.5.6“ @Transactional”
6.8.1“SpringAspectJdomainobject”
6.2“@AspectJ”
3.11“Annotation-based”
3.12“Classpath”
25.4.JakartaCommonsAttributesorg.springframework.metadata.AttributesSpringJakartaCommons
AttributesCommonsAttributes2.2(http://jakarta.apache.org/commons/attributes/)JavaBean (JavaBeanSpring)CommonsAttributes
(fullyqualifiedname,FQN) FQN
JavaBeanBean
/**
*@@MyAttribute(myBooleanJavaBeanProperty=true)
*/
JavaBean(SpringIoC)CommonAttributesJava1.5JavaCommmonsAttributes1.jar$ANT_HOME/libjarSpring
CommonsAttributesjarAPIjar
XDocletxJavadoc.jar
JakartaCommonscommons-collections.jar2.CommonsAttributesant
<taskdefresource="org/apache/commons/attributes/anttasks.properties"/>
3.CommonsAttributesattribute-compiler“”
<targetname="compileAttributes">
<attribute-compilerdestdir="${commons.attributes.tempdir}">
<filesetdir="${src.dir}"includes="**/*.java"/>
</attribute-compiler>
</target>
javacCommonsAttributesMavenCommonsAttributes(Springweb)jar
<attribute-indexerjarFile="myCompiledSources.jar">
<classpathrefid="master-classpath"/>
</attribute-indexer>
SpringjPetStore/attributesSpringAttributesCommonsAttributes CommonsAttributesAPISpring
25.5.SpringAOPSpringAOP.NET
25.5.1.SpringAOP
<beanclass="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"/>
<beanclass="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor">
<propertyname="transactionInterceptor"ref="txInterceptor"/>
</bean>
<beanid="txInterceptor"class="org.springframework.transaction.interceptor.TransactionInterceptor">
<propertyname="transactionManager"ref="transactionManager"/>
<propertyname="transactionAttributeSource">
<beanclass="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource">
<propertyname="attributes"ref="attributes"/>
</bean>
</property>
</bean>
<beanid="attributes"class="org.springframework.metadata.commons.CommonsAttributes"/>
AOPbeancreatoradvisorbeanorg.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
beanadvisor("auto-proxy")beanAOPadvisoradvisor (advisor)
beanCommons AttributesAttributesorg.springframework.metadata.Attributes
25.5.2.bean“”
V.Spring
26.26.1.26.2.SpringMVC
26.2.1.26.3.SimpleJdbcTemplate@RepositoryDAO
26.3.1.26.3.2.DataAccessObject26.3.3.
26
26.1.26.2.SpringMVC
26.2.1.26.3.SimpleJdbcTemplate@RepositoryDAO
26.3.1.26.3.2.DataAccessObject26.3.3.
26.1.SpringFramework Spring2.0
26.2.SpringMVCSpring2.0SpringMVCWeb SpringMVCGroovy'FortuneController.groovy''war/WEB-INF/groovy''war/WEB-INF/fortune-servlet.xml'SpringMVC'fortune'beanGroovy
<lang:groovy/>'refresh-check-delay''fortune'beanrefreshablebeanrefreshable3Tomcat'/WEB-INF/groovy''FortuneController.groovy''fortune'bean…………SpringMVCFortuneFortuneServiceGroovyFortuneServiceWebFortuneFortune
26.2.1.samples/showcases/dynamvcweb-appApacheAnt>=1.4GroovyJDK1.4Ant>=1.5“build.bat”"build.batbuild","build.batwarfile"XML"%JAVA_HOME%/jre/lib/ext"JDK1.4 “warfile.bat”WARWAR"dist"
26.3. SimpleJdbcTemplate@RepositoryDAOSpringJava5HibernateJDBCDAO@RepositoryDAO
26.3.1.PartCarModel CarPartsInventory
26.3.2.DataAccessObject3 CarPartsInventoryDAO HibernateJDBC JdbcCarPartsInventoryImplJDBCSimpleJdbcTemplateDAOSimpleJdbcTemplateJava5DAOTemplateHibernateCarPartsInventoryImplHibernateTemplatePartSpringHibernate PlainHibernateCarPartsInventoryImpl
HibernateTemplateHibernate3APIHibernate3APISpringDataAccessExceptions HibernateTemplateSpring2.0@Repository PlainHibernateCarPartsInventoryImplPersistenceExceptionTranslatorPostProcessorHibernateSpringDataAccessExceptions
26.3.3.samples/showcases/java5-dao ApacheAntJava5VM anttests
A.XMLSchema-basedconfiguration
A.1.IntroductionA.2.XMLSchema-basedconfiguration
A.2.1.ReferencingtheschemasA.2.2.TheutilschemaA.2.3.ThejeeschemaA.2.4.ThelangschemaA.2.5.ThejmsschemaA.2.6.Thetx(transaction)schemaA.2.7.TheaopschemaA.2.8.ThecontextschemaA.2.9.ThetoolschemaA.2.10.Thebeansschema
A.3.SettingupyourIDEA.3.1.SettingupEclipseA.3.2.SettingupIntelliJIDEAA.3.3.Integrationissues
DTDsupport?Authoring Spring configurationfilesusingtheolderDTDstyleisstillfullysupported.Nothingwillbreak if you foregothe use of the new XMLSchema-based approach toauthoring Spring XMLconfiguration files. All that youloseoutonistheopportunitytohavemoresuccinctandclearerconfiguration. Regardless ofwhether the XML configurationis DTD- or Schema-based, intheend it all boils down to thesame object model in thecontainer (namely one ormoreBeanDefinitioninstances).
A.1.IntroductionThisappendixdetailstheXMLSchema-basedconfigurationintroducedinSpring2.0.ThecentralmotivationformovingtoXMLSchemabasedconfigurationfileswastomake Spring XML configuration easier.The 'classic' <bean/>-based approach isgood, but its generic-nature comeswitha price in terms of configurationoverhead.FromtheSpringIoCcontainerspoint-of-view,everything is a bean. That's greatnews for the Spring IoC container,because if everything is a bean theneverything can be treated in the exactsamefashion.Thesame,however,isnottrue from a developer's point-of-view.The objects defined in a Spring XMLconfiguration file are not all generic,vanilla beans. Usually, each beanrequiressomedegreeofspecificconfiguration.Spring2.0'snewXMLSchema-basedconfigurationaddressesthisissue.The <bean/> element is still present, and if you wanted to, you couldcontinuetowritetheexactsamestyleofSpringXMLconfigurationusingonly<bean/>elements.ThenewXMLSchema-basedconfigurationdoes,however, make Spring XML configuration files substantially clearer toread.Inaddition,itallowsyoutoexpresstheintentofabeandefinition.The key thing to remember is that the new custom tagswork best forinfrastructure or integration beans: for example, AOP, collections,transactions, integration with 3rd-party frameworks such as Mule, etc.,whiletheexistingbeantagsarebestsuitedtoapplication-specificbeans,suchasDAOs,servicelayerobjects,validators,etc.The examples included below will hopefully convince you that theinclusion of XMLSchema support in Spring 2.0was a good idea. Thereceptioninthecommunityhasbeenencouraging;also,pleasenotethe
fact that this new configuration mechanism is totally customisable andextensible. This means you can write your own domain-specificconfigurationtagsthatwouldbetterrepresentyourapplication'sdomain;theprocessinvolvedindoingsoiscoveredintheappendixentitled B,ExtensibleXMLauthoring.
A.2.XMLSchema-basedconfiguration
A.2.1.ReferencingtheschemasTo switch over from theDTD-style to the newXMLSchema-style, youneedtomakethefollowingchange.
<?xmlversion="1.0"encoding="UTF-8"?>
<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
<!--<bean/>definitionshere-->
</beans>
TheequivalentfileintheXMLSchema-stylewouldbe...
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<!--<bean/>definitionshere-->
</beans>
The 'xsi:schemaLocation' fragment is not actually required,but can be included to reference a local copy of a schema(whichcanbeusefulduringdevelopment).
TheaboveSpringXMLconfigurationfragmentisboilerplatethatyoucancopyandpaste (!) and then plug <bean/> definitions into like you havealways done. However, the entire point of switching over is to takeadvantageofthenewSpring2.0XMLtagssincetheymakeconfigurationeasier.ThesectionentitledA.2.2“The utilschema”demonstrateshowyou
canstartimmediatelybyusingsomeofthemorecommonutilitytags.The rest of this chapter is devoted to showing examples of the newSpringXMLSchemabasedconfiguration,withat leastoneexample foreverynewtag.Theformatfollowsabeforeandafterstyle,withabeforesnippetofXMLshowingtheold(butstill100%legalandsupported)style,followed immediatelybyanafterexampleshowingtheequivalent in thenewXMLSchema-basedstyle.
A.2.2.TheutilschemaFirstupiscoverageoftheutiltags.Asthenameimplies,theutiltagsdeal with common, utility configuration issues, such as configuringcollections,referencingconstants,andsuchlike.To use the tags in the util schema, you need to have the followingpreamble at the top of your Spring XML configuration file; theemboldenedtext inthesnippetbelowreferencesthecorrectschemasothatthetagsintheutilnamespaceareavailabletoyou.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-2.5.xsd"
<!--<bean/>definitionshere-->
</beans>
A.2.2.1.<util:constant/>Before...
<beanid="..."class="...">
<propertyname="isolation">
<beanid="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
</property>
</bean>
TheaboveconfigurationusesaSpringFactoryBean implementation, theFieldRetrievingFactoryBean,tosetthevalueofthe'isolation'propertyon a bean to the value of the'java.sql.Connection.TRANSACTION_SERIALIZABLE' constant. This is allwell and good, but it is a tad verbose and (unneccessarily) exposesSpring'sinternalplumbingtotheenduser.The following XMLSchema-based version ismore concise and clearlyexpresses thedeveloper's intent ('inject thisconstantvalue'),and it justreadsbetter.
<beanid="..."class="...">
<propertyname="isolation">
<util:constantstatic-field="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
</property>
</bean>
A.2.2.1.1.Settingabeanpropertyorconstructorargfromafieldvalue
FieldRetrievingFactoryBean is a FactoryBean which retrieves a static ornon-staticfieldvalue.Itistypicallyusedforretrievingpublicstaticfinalconstants,whichmaythenbeusedtosetapropertyvalueorconstructorargforanotherbean.Findbelowanexamplewhichshowshowastatic field isexposed,byusingthestaticFieldproperty:
<beanid="myField"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean">
<propertyname="staticField"value="java.sql.Connection.TRANSACTION_SERIALIZABLE"/>
</bean>
There is also a convenience usage form where the static field isspecifiedasthebeanname:
<beanid="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
Thisdoesmeanthatthereisnolongeranychoiceinwhatthebeanidis(soanyotherbeanthatreferstoitwillalsohavetousethislongername),butthisformisveryconcisetodefine,andveryconvenienttouseasaninner bean since the id doesn't have to be specified for the beanreference:
<beanid="..."class="...">
<propertyname="isolation">
<beanid="java.sql.Connection.TRANSACTION_SERIALIZABLE"
class="org.springframework.beans.factory.config.FieldRetrievingFactoryBean"/>
</property>
</bean>
Itisalsopossibletoaccessanon-static(instance)fieldofanotherbean,asdescribedintheAPIdocumentationfortheFieldRetrievingFactoryBeanclass.Injecting enum values into beans as either property or constructorargumentsisveryeasytodoinSpring,inthatyoudon'tactuallyhavetodoanythingorknowanythingabout theSpring internals(orevenaboutclasses such as the FieldRetrievingFactoryBean). Let's look at anexampletoseehoweasyinjectinganenumvalueis;considerthisJDK5enum:
packagejavax.persistence;
publicenumPersistenceContextType{
TRANSACTION,
EXTENDED
}
NowconsiderasetteroftypePersistenceContextType:
packageexample;
publicclassClient{
privatePersistenceContextTypepersistenceContextType;
publicvoidsetPersistenceContextType(PersistenceContextTypetype){
this.persistenceContextType=type;
}
}
..andthecorrespondingbeandefinition:
<beanclass="example.Client">
<propertyname="persistenceContextType"value="TRANSACTION"/>
</bean>
Thisworks forclassic type-safeemulatedenums(onJDK1.4andJDK1.3)aswell;Springwillautomaticallyattempttomatchthestringpropertyvaluetoaconstantontheenumclass.
A.2.2.2.<util:property-path/>Before...
<!--targetbeantobereferencedbyname-->
<beanid="testBean"class="org.springframework.beans.TestBean"scope="prototype">
<propertyname="age"value="10"/>
<propertyname="spouse">
<beanclass="org.springframework.beans.TestBean">
<propertyname="age"value="11"/>
</bean>
</property>
</bean>
<!--willresultin10,whichisthevalueofproperty'age'ofbean'testBean'-->
<beanid="testBean.age"class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
TheaboveconfigurationusesaSpringFactoryBean implementation, thePropertyPathFactoryBean, to create a bean (of type int) called'testBean.age' that has a value equal to the 'age' property of the'testBean'bean.After...
<!--targetbeantobereferencedbyname-->
<beanid="testBean"class="org.springframework.beans.TestBean"scope="prototype">
<propertyname="age"value="10"/>
<propertyname="spouse">
<beanclass="org.springframework.beans.TestBean">
<propertyname="age"value="11"/>
</bean>
</property>
</bean>
<!--willresultin10,whichisthevalueofproperty'age'ofbean'testBean'-->
<util:property-pathid="name"path="testBean.age"/>
Thevalueofthe'path'attributeofthe<property-path/> tag followstheform'beanName.beanProperty'.
A.2.2.2.1.Using<util:property-path/> to setabeanpropertyorconstructor-argument
PropertyPathFactoryBeanisaFactoryBeanthatevaluatesapropertypathonagiventargetobject.Thetargetobjectcanbespecifieddirectlyorviaabeanname.Thisvaluemaythenbeusedinanotherbeandefinitionasapropertyvalueorconstructorargument.Here'sanexamplewhereapathisusedagainstanotherbean,byname:
//targetbeantobereferencedbyname
<beanid="person"class="org.springframework.beans.TestBean"scope="prototype">
<propertyname="age"value="10"/>
<propertyname="spouse">
<beanclass="org.springframework.beans.TestBean">
<propertyname="age"value="11"/>
</bean>
</property>
</bean>
//willresultin11,whichisthevalueofproperty'spouse.age'ofbean'person'
<beanid="theAge"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<propertyname="targetBeanName"value="person"/>
<propertyname="propertyPath"value="spouse.age"/>
</bean>
Inthisexample,apathisevaluatedagainstaninnerbean:
<!--willresultin12,whichisthevalueofproperty'age'oftheinnerbean-->
<beanid="theAge"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean">
<propertyname="targetObject">
<beanclass="org.springframework.beans.TestBean">
<propertyname="age"value="12"/>
</bean>
</property>
<propertyname="propertyPath"value="age"/>
</bean>
Thereisalsoashortcutform,wherethebeannameisthepropertypath.
<!--willresultin10,whichisthevalueofproperty'age'ofbean'person'-->
<beanid="person.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
Thisformdoesmeanthatthereisnochoiceinthenameofthebean.Anyreference to itwill alsohave to use the same id,which is thepath.Ofcourse,ifusedasaninnerbean,thereisnoneedtorefertoitatall:
<beanid="..."class="...">
<propertyname="age">
<beanid="person.age"
class="org.springframework.beans.factory.config.PropertyPathFactoryBean"/>
</property>
</bean>
Theresulttypemaybespecificallysetintheactualdefinition.Thisisnotnecessary formostusecases,butcanbeofuse forsome.Please seetheJavadocsformoreinfoonthisfeature.
A.2.2.3.<util:properties/>Before...
<!--createsajava.util.Propertiesinstancewithvaluesloadedfromthesuppliedlocation-->
<beanid="jdbcConfiguration"class="org.springframework.beans.factory.config.PropertiesFactoryBean">
<propertyname="location"value="classpath:com/foo/jdbc-production.properties"/>
</bean>
TheaboveconfigurationusesaSpringFactoryBean implementation, thePropertiesFactoryBean, to instantiate a java.util.Properties instancewithvaluesloadedfromthesuppliedResourcelocation).After...
<!--createsajava.util.Propertiesinstancewithvaluesloadedfromthesuppliedlocation-->
<util:propertiesid="jdbcConfiguration"location="classpath:com/foo/jdbc-production.properties"/>
A.2.2.4.<util:list/>Before...
<!--createsajava.util.Listinstancewithvaluesloadedfromthesupplied
<beanid="emails"class="org.springframework.beans.factory.config.ListFactoryBean">
<propertyname="sourceList">
<list>
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</list>
</property>
</bean>
TheaboveconfigurationusesaSpringFactoryBean implementation, theListFactoryBean, to create a java.util.List instance initialized withvaluestakenfromthesupplied'sourceList'.After...
<!--createsajava.util.Listinstancewithvaluesloadedfromthesupplied
<util:listid="emails">
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</util:list>
You can also explicitly control the exact type of List that will beinstantiated and populated via the use of the 'list-class' attribute onthe <util:list/> element. For example, if we really need ajava.util.LinkedList to be instantiated, we could use the followingconfiguration:
<util:listid="emails"list-class="java.util.LinkedList">
<value>jackshaftoe@vagabond.org</value>
<value>eliza@thinkingmanscrumpet.org</value>
<value>vanhoek@pirate.org</value>
<value>d'Arcachon@nemesis.org</value>
</util:list>
If no 'list-class' attribute is supplied, a List implementation will bechosenbythecontainer.Finally, you can also control the merging behavior using the 'merge'attributeof the<util:list/>element;collectionmerging isdescribed inmoredetailinthesectionentitled3.3.2.4.1“” .
A.2.2.5.<util:map/>Before...
<!--createsajava.util.Mapinstancewithvaluesloadedfromthesupplied
<beanid="emails"class="org.springframework.beans.factory.config.MapFactoryBean">
<propertyname="sourceMap">
<map>
<entrykey="pechorin"value="pechorin@hero.org"/>
<entrykey="raskolnikov"value="raskolnikov@slums.org"/>
<entrykey="stavrogin"value="stavrogin@gov.org"/>
<entrykey="porfiry"value="porfiry@gov.org"/>
</map>
</property>
</bean>
TheaboveconfigurationusesaSpringFactoryBean implementation, theMapFactoryBean, to create a java.util.Map instance initialized with key-
valuepairstakenfromthesupplied'sourceMap'.After...
<!--createsajava.util.Mapinstancewithvaluesloadedfromthesupplied
<util:mapid="emails">
<entrykey="pechorin"value="pechorin@hero.org"/>
<entrykey="raskolnikov"value="raskolnikov@slums.org"/>
<entrykey="stavrogin"value="stavrogin@gov.org"/>
<entrykey="porfiry"value="porfiry@gov.org"/>
</util:map>
You can also explicitly control the exact type of Map that will beinstantiatedandpopulatedviatheuseofthe'map-class'attributeonthe<util:map/>element.Forexample,ifwereallyneedajava.util.TreeMaptobeinstantiated,wecouldusethefollowingconfiguration:
<util:mapid="emails"map-class="java.util.TreeMap">
<entrykey="pechorin"value="pechorin@hero.org"/>
<entrykey="raskolnikov"value="raskolnikov@slums.org"/>
<entrykey="stavrogin"value="stavrogin@gov.org"/>
<entrykey="porfiry"value="porfiry@gov.org"/>
</util:map>
If no 'map-class' attribute is supplied, a Map implementation will bechosenbythecontainer.Finally, you can also control the merging behavior using the 'merge'attribute of the <util:map/> element; collectionmerging is described inmoredetailinthesectionentitled3.3.2.4.1“” .
A.2.2.6.<util:set/>Before...
<!--createsajava.util.Setinstancewithvaluesloadedfromthesupplied
<beanid="emails"class="org.springframework.beans.factory.config.SetFactoryBean">
<propertyname="sourceSet">
<set>
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</set>
</property>
</bean>
TheaboveconfigurationusesaSpringFactoryBean implementation, theSetFactoryBean,tocreateajava.util.Setinstanceinitializedwithvaluestakenfromthesupplied'sourceSet'.After...
<!--createsajava.util.Setinstancewithvaluesloadedfromthesupplied
<util:setid="emails">
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</util:set>
You can also explicitly control the exact type of Set that will beinstantiatedandpopulatedviatheuseofthe'set-class'attributeonthe<util:set/>element.Forexample,ifwereallyneedajava.util.TreeSettobeinstantiated,wecouldusethefollowingconfiguration:
<util:setid="emails"set-class="java.util.TreeSet">
<value>pechorin@hero.org</value>
<value>raskolnikov@slums.org</value>
<value>stavrogin@gov.org</value>
<value>porfiry@gov.org</value>
</util:set>
If no 'set-class' attribute is supplied, a Set implementation will bechosenbythecontainer.Finally, you can also control the merging behavior using the 'merge'attribute of the <util:set/> element; collectionmerging is described inmoredetailinthesectionentitled3.3.2.4.1“” .
A.2.3.ThejeeschemaThe jee tags deal with JEE (Java Enterprise Edition)-related
configurationissues,suchaslookingupaJNDIobjectanddefiningEJBreferences.To use the tags in the jee schema, you need to have the followingpreamble at the top of your Spring XML configuration file; theemboldened text in the followingsnippet references thecorrectschemasothatthetagsinthejeenamespaceareavailabletoyou.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jee="http://www.springframework.org/schema/jee"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jeehttp://www.springframework.org/schema/jee/spring-jee-2.5.xsd"
<!--<bean/>definitionshere-->
</beans>
A.2.3.1.<jee:jndi-lookup/>(simple)Before...
<beanid="dataSource"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="jdbc/MyDataSource"/>
</bean>
<beanid="userDao"class="com.foo.JdbcUserDao">
<!--Springwilldothecastautomatically(asusual)-->
<propertyname="dataSource"ref="dataSource"/>
</bean>
After...
<jee:jndi-lookupid="dataSource"jndi-name="jdbc/MyDataSource"/>
<beanid="userDao"class="com.foo.JdbcUserDao">
<!--Springwilldothecastautomatically(asusual)-->
<propertyname="dataSource"ref="dataSource"/>
</bean>
A.2.3.2. <jee:jndi-lookup/> (with single JNDI environmentsetting)Before...
<beanid="simple"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="jdbc/MyDataSource"/>
<propertyname="jndiEnvironment">
<props>
<propkey="foo">bar</prop>
</props>
</property>
</bean>
After...
<jee:jndi-lookupid="simple"jndi-name="jdbc/MyDataSource">
<jee:environment>foo=bar</jee:environment>
</jee:jndi-lookup>
A.2.3.3.<jee:jndi-lookup/> (withmultiple JNDI environmentsettings)Before...
<beanid="simple"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="jdbc/MyDataSource"/>
<propertyname="jndiEnvironment">
<props>
<propkey="foo">bar</prop>
<propkey="ping">pong</prop>
</props>
</property>
</bean>
After...
<jee:jndi-lookupid="simple"jndi-name="jdbc/MyDataSource">
<!--newline-separated,key-valuepairsfortheenvironment(standard
<jee:environment>
foo=bar
ping=pong
</jee:environment>
</jee:jndi-lookup>
A.2.3.4.<jee:jndi-lookup/>(complex)Before...
<beanid="simple"class="org.springframework.jndi.JndiObjectFactoryBean">
<propertyname="jndiName"value="jdbc/MyDataSource"/>
<propertyname="cache"value="true"/>
<propertyname="resourceRef"value="true"/>
<propertyname="lookupOnStartup"value="false"/>
<propertyname="expectedType"value="com.myapp.DefaultFoo"/>
<propertyname="proxyInterface"value="com.myapp.Foo"/>
</bean>
After...
<jee:jndi-lookupid="simple"
jndi-name="jdbc/MyDataSource"
cache="true"
resource-ref="true"
lookup-on-startup="false"
expected-type="com.myapp.DefaultFoo"
proxy-interface="com.myapp.Foo"/>
A.2.3.5.<jee:local-slsb/>(simple)The <jee:local-slsb/> tag configures a reference to an EJBStatelessSessionBean.Before...
<beanid="simple"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<propertyname="jndiName"value="ejb/RentalServiceBean"/>
<propertyname="businessInterface"value="com.foo.service.RentalService"/>
</bean>
After...
<jee:local-slsbid="simpleSlsb"jndi-name="ejb/RentalServiceBean"
business-interface="com.foo.service.RentalService"/>
A.2.3.6.<jee:local-slsb/>(complex)
<beanid="complexLocalEjb"
class="org.springframework.ejb.access.LocalStatelessSessionProxyFactoryBean">
<propertyname="jndiName"value="ejb/RentalServiceBean"/>
<propertyname="businessInterface"value="com.foo.service.RentalService"/>
<propertyname="cacheHome"value="true"/>
<propertyname="lookupHomeOnStartup"value="true"/>
<propertyname="resourceRef"value="true"/>
</bean>
After...
<jee:local-slsbid="complexLocalEjb"
jndi-name="ejb/RentalServiceBean"
business-interface="com.foo.service.RentalService"
cache-home="true"
lookup-home-on-startup="true"
resource-ref="true">
A.2.3.7.<jee:remote-slsb/>The <jee:remote-slsb/> tag configures a reference to a remote EJBStatelessSessionBean.Before...
<beanid="complexRemoteEjb"
class="org.springframework.ejb.access.SimpleRemoteStatelessSessionProxyFactoryBean">
<propertyname="jndiName"value="ejb/MyRemoteBean"/>
<propertyname="businessInterface"value="com.foo.service.RentalService"/>
<propertyname="cacheHome"value="true"/>
<propertyname="lookupHomeOnStartup"value="true"/>
<propertyname="resourceRef"value="true"/>
<propertyname="homeInterface"value="com.foo.service.RentalService"/>
<propertyname="refreshHomeOnConnectFailure"value="true"/>
</bean>
After...
<jee:remote-slsbid="complexRemoteEjb"
jndi-name="ejb/MyRemoteBean"
business-interface="com.foo.service.RentalService"
cache-home="true"
lookup-home-on-startup="true"
resource-ref="true"
home-interface="com.foo.service.RentalService"
refresh-home-on-connect-failure="true">
A.2.4.ThelangschemaThe lang tags deal with exposing objects that have been written in adynamic language such as JRuby or Groovy as beans in the Springcontainer.These tags (and the dynamic language support) are comprehensivelycoveredin thechapterentitled 24 .Pleasedoconsult thatchapter forfulldetailsonthissupportandthelangtagsthemselves.Intheinterestofcompleteness,tousethetagsinthelangschema,youneed to have the following preamble at the top of your Spring XMLconfigurationfile;theemboldenedtextinthefollowingsnippetreferencesthecorrectschemasothatthetagsinthelangnamespaceareavailabletoyou.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:lang="http://www.springframework.org/schema/lang"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/langhttp://www.springframework.org/schema/lang/spring-lang-2.5.xsd"
<!--<bean/>definitionshere-->
</beans>
A.2.5.ThejmsschemaThejms tagsdealwithconfiguringJMS-relatedbeanssuchasSpring'sMessageListenerContainers.These tags are detailed in the section of the JMSchapterentitled19.6“JMS” .Pleasedoconsultthatchapterforfulldetailsonthissupportandthejmstagsthemselves.In the interestofcompleteness, touse the tags in thejmsschema, youneed to have the following preamble at the top of your Spring XMLconfigurationfile;theemboldenedtextinthefollowingsnippetreferencesthecorrectschemasothatthetagsinthejmsnamespaceareavailabletoyou.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jms="http://www.springframework.org/schema/jms"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/jmshttp://www.springframework.org/schema/jms/spring-jms-2.5.xsd"
<!--<bean/>definitionshere-->
</beans>
A.2.6.Thetx(transaction)schemaThe tx tags deal with configuring all of those beans in Spring'scomprehensive support for transactions.These tagsare covered in thechapterentitled9 .
You are strongly encouraged to look at the 'spring-tx-2.5.xsd'filethatshipswiththeSpringdistribution.Thisfileis(of course), the XML Schema for Spring's transactionconfiguration, and covers all of the various tags in the txnamespace,includingattributedefaultsandsuchlike.Thisfileisdocumentedinline,andthustheinformationisnotrepeatedhere in the interests of adhering to the DRY (Don't Repeat
Yourself)principle.In the interest of completeness, to use the tags in thetx schema, youneed to have the following preamble at the top of your Spring XMLconfigurationfile;theemboldenedtextinthefollowingsnippetreferencesthecorrectschemasothatthetagsinthetxnamespaceareavailabletoyou.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
<!--<bean/>definitionshere-->
</beans>
Oftenwhenusingthetags inthetxnamespaceyouwillalsobe using the tags from the aop namespace (since thedeclarativetransactionsupportinSpringisimplementedusingAOP). The above XML snippet contains the relevant linesneededtoreferencetheaopschemasothatthetagsintheaopnamespaceareavailabletoyou.
A.2.7.TheaopschemaTheaoptagsdealwithconfiguringallthingsAOPinSpring:thisincludesSpring'sownproxy-basedAOP frameworkandSpring's integrationwiththeAspectJAOPframework.Thesetagsarecomprehensivelycoveredinthechapterentitled6 SpringAOP .In the interestofcompleteness, touse the tags in theaopschema, youneed to have the following preamble at the top of your Spring XMLconfigurationfile;theemboldenedtextinthefollowingsnippetreferences
thecorrectschemasothatthetagsintheaopnamespaceareavailabletoyou.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop-2.5.xsd"
<!--<bean/>definitionshere-->
</beans>
A.2.8.ThecontextschemaThecontexttagsdealwithApplicationContextconfigurationthatrelatestoplumbing-thatis,notusuallybeansthatareimportanttoanend-userbut rather beans that do a lot of grunt work in Spring, such asBeanfactoryPostProcessors.Thefollowingsnippetreferencesthecorrectschemasothatthetagsinthecontextnamespaceareavailabletoyou.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context-2.5.xsd"
<!--<bean/>definitionshere-->
</beans>
ThecontextschemawasonlyintroducedinSpring2.5.
A.2.8.1.<property-placeholder/>
Thiselementactivatesthereplacementof${...}placeholders,resolvedagainst the specified properties file (as a Spring resource location). Thiselement is a convenience mechanism that sets up aPropertyPlaceholderConfigurer foryou; ifyouneedmorecontrolover thePropertyPlaceholderConfigurer,justdefineoneyourselfexplicitly.
A.2.8.2.<annotation-config/>ActivatestheSpringinfrastructureforvariousannotationstobedetectedinbeanclasses:Spring's@Requiredand@Autowired,aswellasJSR250's@PostConstruct, @PreDestroy and @Resource (if available), and JPA's@PersistenceContext and @PersistenceUnit (if available). Alternatively,you can choose to activate the individual BeanPostProcessors for thoseannotationsexplictly.
This element does not activate processing of Spring's@Transactional annotation. Use the <tx:annotation-driven/>
elementforthatpurpose.
A.2.8.3.<component-scan/>Thiselementisdetailedinthesectionentitled3.11“Annotation-based” .
A.2.8.4.<load-time-weaver/>Thiselementisdetailedinthesectionentitled6.8.4“SpringAspectJLTW” .
A.2.8.5.<spring-configured/>Thiselementisdetailedinthesectionentitled6.8.1“SpringAspectJdomainobject” .
A.2.8.6.<mbean-export/>This element is detailed in the section entitled 20.4.3 “ <context:mbean-
export/>” .
A.2.9.ThetoolschemaThetooltagsareforusewhenyouwanttoaddtooling-specificmetadata
to your custom configuration elements. This metadata can then beconsumed by tools that are aware of thismetadata, and the tools canthendoprettymuchwhatevertheywantwithit(validation,etc.).Thetool tagsarenotdocumented in thisreleaseofSpringas theyarecurrentlyundergoingreview.Ifyouareathirdpartytoolvendorandyouwould like to contribute to this reviewprocess, thendomail theSpringmailing list. The currently supported tool tags can be found in the file'spring-tool-2.5.xsd' in the'src/org/springframework/beans/factory/xml' directory of the Springsourcedistribution.
A.2.10.ThebeansschemaLastbutnotleastwehavethetagsinthebeansschema.Theseare thesame tags that have been in Spring since the very dawn of theframework. Examples of the various tags in the beans schema are notshown here because they are quite comprehensively covered in thesectionentitled3.3.2“” (andindeedinthatentirechapter).Onethingthat isnewtothebeanstagsthemselvesinSpring2.0istheideaofarbitrarybeanmetadata. InSpring2.0 it isnowpossible toaddzero or more key / value pairs to <bean/> XML definitions. What, ifanything, is done with this extra metadata is totally up to your owncustomlogic(andso is typicallyonlyofuse ifyouarewritingyourowncustomtagsasdescribedintheappendixentitledB,ExtensibleXMLauthoring).Findbelowanexampleofthe<meta/>taginthecontextofasurrounding<bean/>(pleasenotethatwithoutanylogictointerpretitthemetadataiseffectivelyuselessas-is).
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
<beanid="foo"class="x.y.Foo">
<metakey="cacheName"value="foo"/>
<propertyname="name"value="Rick"/>
</bean>
</beans>
Inthecaseoftheaboveexample,youwouldassumethatthereissomelogic that will consume the bean definition and set up some cachinginfrastructureusingthesuppliedmetadata.
A.3.SettingupyourIDEThisfinalsectiondocumentsthestepsinvolvedinsettingupanumberofpopularJavaIDEstoeffect theeasiereditingofSpring'sXMLSchema-based configuration files. If your favourite Java IDE or editor is notincludedinthelistofdocumentedIDEs, thenpleasedo raisean issueandan example with your favorite IDE/editormay be included in the nextrelease.
A.3.1.SettingupEclipseThe following steps illustrate setting up Eclipse to be XSD-aware. Theassumption in the following steps is that you already have an Eclipseprojectopen(eitherabrandnewprojectoranalreadyexistingone).
ThefollowingstepswerecreatedusingEclipse3.2.Thesetupwill probably be the same (or similar) on an earlier or laterversionofEclipse.StepOneCreateanewXMLfile.Youcannamethisfilewhateveryouwant.Intheexamplebelow,thefileisnamed'context.xml'.Copyandpastethefollowingtextintothefilesothatitmatchesthescreenshot.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-2.5.xsd">
</beans>
Contributingdocumentation...Patches showing how toconfigure an Eclipse XMLeditor are welcomed. Anysuch contributions are bestsubmitted as patches via theSpringFrameworkJIRAIssueTrackerandmay be featuredinthenextrelease.
StepTwoAs can be seen in the above screenshot (unless you have acustomisedversionofEclipsewith thecorrectplugins) theXMLfilewillbetreatedasplain text.There isnoXMLeditingsupportoutofthe box in Eclipse, and as such there is not even any syntaxhighlightingofelementsandattributes.Toaddressthis,youwillhavetoinstallanXMLeditorpluginforEclipse...
A.1.EclipseXMLeditors
XMLEditor LinkTheEclipseWebToolsPlatform(WTP) http://www.eclipse.org/webtools/
AlistofEclipseXMLplugins http://eclipse-plugins.2y.net/eclipse/plugins.jsp?category=XML
Unfortunately, precisely becausethere is no standard XML editor forEclipse,thereare(bartheonebelow)no further stepsshowingyouhow toconfigure XML Schema support inEclipse... each XML editor pluginwould require itsveryowndedicatedsection, and this isSpring referencedocumentation, not Eclipse XML
editordocumentation.Youwillhavetoread the documentation that comeswith your XML editor plugin (good luck there) and figure it out foryourself.SpringIDEThere is a dedicated Spring Framework plugin for Eclipse calledSpring IDE and it isprettydarn cool. (There'sa consideredandnon-biasedopinionforyou!)ThispluginmakesusingSpringeveneasier,and ithasmore than just support for thecoreSpringFramework...SpringWebFlow is supported too. Details of how to install SpringIDEcanbefoundontheSpringIDEinstallationpage.
WebToolsPlatform(WTP)forEclipseIfyouareusingtheWebToolsPlatform(WTP)forEclipse,youdon'tneedtodoanythingotherthanopenaSpringXMLconfigurationfileusing the WTP platform's XML editor. As can be seen in thescreenshotbelow,youimmediatelygetsomeslickIDE-levelsupportforautocompletingtagsandsuchlike.
A.3.2.SettingupIntelliJIDEAThe following steps illustrate setting up the IntelliJ IDEA IDE to be XSD-aware.TheassumptioninthefollowingstepsisthatyoualreadyhaveanIDEA project open (either a brand new project or an already existingone).RepeatasrequiredforsettingupIDEAtoreferencetheotherSpringXSDfiles.
StepOneCreateanewXMLfile(youcannamethisfilewhateveryouwant).Intheexamplebelow,thefileisnamed'context.xml'.Copyandpastethefollowingtextintothefilesothatitmatchesthescreenshot.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/utilhttp://www.springframework.org/schema/util/spring-util-2.5.xsd">
</beans>
StepTwoAscanbeseenintheabovescreenshot,theXMLfilehasanumberofnastyredcontextualerrormarkers.Torectifythis,IDEAhastobemadeawareofthelocationofthereferencedXSDnamespace(s).Todothis,simplypositionthecursoroverthesquigglyredarea(seethe screenshot below); then press the Alt-Enter keystrokecombination, and press the Enter key again when the popupbecomesactivetofetchtheexternalresource.
StepThreeIf the external resource could not be fetched (maybe no active
Internet connection is available), you can manually configure theresourcetoreferencea localcopyof theXSDfile.Simplyopenupthe'Settings'dialog (using theCtrl-A-Skeystrokecombinationorviathe'File|Settings'menu),andclickonthe'Resources'button.
StepFourAscanbeseeninthefollowingscreenshot,thiswillbringupadialogthat allows you to add an explicit reference to a local copy of theutilschemafile.(YoucanfindallofthevariousSpringXSDfilesinthe'src'directoryoftheSpringdistribution.)
StepFiveClickingthe'Add'buttonwillbringupanotherdialogthatallowsyouto explicitly to associate a namespace URI with the path to therelevantXSD file.As can be seen in the following screenshot, the'http://www.springframework.org/schema/util'namespaceisbeingassociated with the file resource'C:\bench\spring\src\org\springframework\beans\factory\xml\spring-
util-2.5.xsd'.
StepSixExitingoutofthenesteddialogsbyclickingthe'OK'buttonwill thenbring back the main editing window, and as can be seen in thefollowing screenshot, the contextual error markers havedisappeared; typing the '<' character into the editing window nowalso brings up a handy dropdown box that contains all of theimportedtagsfromtheutilnamespace.
A.3.3.IntegrationissuesThis final section details integration issues that may arise when youswitchovertousingtheaboveXSD-styleforSpring2.0configuration.Thissection isquitesmallat themoment (andhopefully itwillstay thatway).IthasbeenincludedintheSpringdocumentationasaconveniencetoSpringuserssothatifyouencounteranissuewhenswitchingovertotheXSD-styleinsomespecificenvironmentyoucanrefertothissectionfortheauthoritativeanswer.
A.3.3.1.XMLparsingerrorsintheResinv.3applicationserverIf you are using the XSD-style for Spring 2.0 XML configuration anddeployingtov.3ofCaucho'sResinapplicationserver,youwillneedtosetsomeconfigurationoptionspriortostartupsothatanXSD-awareparserisavailabletoSpring.Please do read this resource, http://www.caucho.com/resin-3.0/xml/jaxp.xtp#xerces,forfurtherdetails.
B.ExtensibleXMLauthoring
B.1.IntroductionB.2.AuthoringtheschemaB.3.CodingaNamespaceHandlerB.4.CodingaBeanDefinitionParserB.5.Registeringthehandlerandtheschema
B.5.1.'META-INF/spring.handlers'B.5.2.'META-INF/spring.schemas'
B.6.UsingacustomextensioninyourSpringXMLconfigurationB.7.Meatierexamples
B.7.1.NestingcustomtagswithincustomtagsB.7.2.Customattributeson'normal'elements
B.8.FurtherResources
B.1.IntroductionSinceversion2.0,Springhas featuredamechanism forschema-basedextensionsto the basicSpringXML format for defining and configuringbeans. This section is devoted to detailing how you would go aboutwriting your own custom XML bean definition parsers and integratingsuchparsersintotheSpringIoCcontainer.To facilitate the authoring of configuration files using a schema-awareXMLeditor,Spring's extensibleXML configurationmechanism is basedon XML Schema. If you are not familiar with Spring's current XMLconfigurationextensionsthatcomewiththestandardSpringdistribution,pleasefirstreadtheappendixentitledA,XMLSchema-basedconfiguration.Creating new XML configuration extensions can be done by followingthese(relatively)simplesteps:
AuthoringanXMLschematodescribeyourcustomelement(s).
Coding a custom NamespaceHandler implementation (this is an easystep,don'tworry).Coding one or more BeanDefinitionParser implementations (this iswheretherealworkisdone).RegisteringtheaboveartifactswithSpring(thistooisaneasystep).
Whatfollowsisadescriptionofeachofthesesteps.Fortheexample,wewillcreateanXMLextension(acustomXMLelement) thatallowsus toconfigure objects of the type SimpleDateFormat (from the java.textpackage) in an easy manner. When we are done, we will be able todefinebeandefinitionsoftypeSimpleDateFormatlikethis:
<myns:dateformatid="dateFormat"
pattern="yyyy-MM-ddHH:mm"
lenient="true"/>
(Don'tworryaboutthefact thatthisexample isverysimple;muchmoredetailed examples follow afterwards. The intent in this first simpleexampleistowalkyouthroughthebasicstepsinvolved.)
B.2.AuthoringtheschemaCreating an XML configuration extension for use with Spring's IoCcontainer starts with authoring an XML Schema to describe theextension. What follows is the schema we'll use to configureSimpleDateFormatobjects.
<!--myns.xsd(insidepackageorg/springframework/samples/xml)-->
<?xmlversion="1.0"encoding="UTF-8"?>
<xsd:schemaxmlns="http://www.mycompany.com/schema/myns"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
targetNamespace="http://www.mycompany.com/schema/myns"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:importnamespace="http://www.springframework.org/schema/beans"/>
<xsd:elementname="dateformat">
<xsd:complexType>
<xsd:complexContent>
<xsd:extensionbase="beans:identifiedType">
<xsd:attributename="lenient"type="xsd:boolean"/>
<xsd:attributename="pattern"type="xsd:string"use="required"/>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
(Theemphasizedlinecontainsanextensionbaseforalltagsthatwillbeidentifiable (meaning theyhaveanidattribute thatwill be used as thebeanidentifierinthecontainer).WeareabletousethisattributebecauseweimportedtheSpring-provided'beans'namespace.)Theabove schemawill be used to configureSimpleDateFormat objects,directly inanXMLapplication context fileusing the<myns:dateformat/>element.
<myns:dateformatid="dateFormat"
pattern="yyyy-MM-ddHH:mm"
lenient="true"/>
Note that after we've created the infrastructure classes, the abovesnippetofXMLwillessentiallybeexactlythesameasthefollowingXMLsnippet. In other words, we're just creating a bean in the container,identified by the name 'dateFormat' of type SimpleDateFormat, with acoupleofpropertiesset.
<beanid="dateFormat"class="java.text.SimpleDateFormat">
<constructor-argvalue="yyyy-HH-ddHH:mm"/>
<propertyname="lenient"value="true"/>
</bean>
Theschema-basedapproach tocreatingconfiguration formatallows for tight integration with an IDE that has a schema-awareXMLeditor.Usingaproperlyauthoredschema,youcanuse autocompletion to have a user choose between severalconfigurationoptionsdefinedintheenumeration.
B.3.CodingaNamespaceHandlerInadditiontotheschema,weneedaNamespaceHandlerthatwillparseallelements of this specific namespace Spring encounters while parsingconfigurationfiles.TheNamespaceHandlershouldinourcasetakecareoftheparsingofthemyns:dateformatelement.The NamespaceHandler interface is pretty simple in that it features justthreemethods:
init() - allows for initializationof theNamespaceHandler andwill becalledbySpringbeforethehandlerisusedBeanDefinitionparse(Element,ParserContext)-calledwhenSpringencountersa top-levelelement (notnested insideabeandefinitionoradifferentnamespace).Thismethodcanregisterbeandefinitionsitselfand/orreturnabeandefinition.BeanDefinitionHolder decorate(Node, BeanDefinitionHolder,
ParserContext) - called when Spring encounters an attribute ornestedelementofadifferentnamespace.Thedecorationofoneormorebeandefinitionsisusedforexamplewiththeout-of-the-boxscopesSpring2.0supports.We'llstartbyhighlightingasimpleexample,withoutusingdecoration,afterwhichwewillshowdecorationinasomewhatmoreadvancedexample.
Although it is perfectly possible to code your own NamespaceHandler forthe entire namespace (and hence provide code that parses each andeveryelementinthenamespace),itisoftenthecasethateachtop-levelXMLelement inaSpringXMLconfigurationfileresults inasinglebeandefinition (as in our case, where a single <myns:dateformat/> elementresults in a single SimpleDateFormat bean definition). Spring features anumber of convenience classes that support this scenario. In thisexample,we'llmakeusetheNamespaceHandlerSupportclass:
packageorg.springframework.samples.xml;
importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;
publicclassMyNamespaceHandlerextendsNamespaceHandlerSupport{
publicvoidinit(){
registerBeanDefinitionParser("dateformat",newSimpleDateFormatBeanDefinitionParser());
}
}
The observant readerwill notice that there isn't actually awhole lot ofparsing logic in this class. Indeed... the NamespaceHandlerSupport classhas a built in notion of delegation. It supports the registration of anynumber of BeanDefinitionParser instances, to which it will delegate towhen it needs to parse an element in it's namespace. This cleanseparation of concerns allows a NamespaceHandler to handle theorchestration of the parsing of all of the custom elements in it'snamespace,while delegating to BeanDefinitionParsers to do the gruntworkoftheXMLparsing;thismeansthateachBeanDefinitionParserwillcontainjustthelogicforparsingasinglecustomelement,aswecanseeinthenextstep
B.4.CodingaBeanDefinitionParserABeanDefinitionParserwillbeused if theNamespaceHandler encountersanXMLelementof thetypethathasbeenmappedtothespecificbeandefinitionparser(whichis'dateformat'inthiscase).Inotherwords,theBeanDefinitionParser is responsible for parsing one distinct top-levelXMLelementdefinedintheschema.Intheparser,we'llhaveaccesstotheXMLelement (and thus it's subelements too) so thatwe canparseourcustomXMLcontent,ascanbeseeninthefollowingexample:
packageorg.springframework.samples.xml;
importorg.springframework.beans.factory.support.BeanDefinitionBuilder;
importorg.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
importorg.springframework.util.StringUtils;
importorg.w3c.dom.Element;
importjava.text.SimpleDateFormat;
publicclassSimpleDateFormatBeanDefinitionParserextendsAbstractSingleBeanDefinitionParser{
protectedClassgetBeanClass(Elementelement){
returnSimpleDateFormat.class;
}
protectedvoiddoParse(Elementelement,BeanDefinitionBuilderbean){
//thiswillneverbenullsincetheschemaexplicitlyrequiresthatavaluebesupplied
Stringpattern=element.getAttribute("pattern");
bean.addConstructorArg(pattern);
//thishoweverisanoptionalproperty
Stringlenient=element.getAttribute("lenient");
if(StringUtils.hasText(lenient)){
bean.addPropertyValue("lenient",Boolean.valueOf(lenient));
}
}
}
WeusetheSpring-provided
AbstractSingleBeanDefinitionParsertohandlealotofthebasicgruntworkofcreatingasingleBeanDefinition.
WesupplytheAbstractSingleBeanDefinitionParsersuperclasswiththetypethatoursingleBeanDefinitionwillrepresent.
In this simple case, this is all that we need to do. The creation of oursingle BeanDefinition is handled by theAbstractSingleBeanDefinitionParsersuperclass,asistheextractionandsettingofthebeandefinition'suniqueidentifier.
B.5.RegisteringthehandlerandtheschemaThecodingisfinished!AllthatremainstobedoneistosomehowmaketheSpringXMLparsing infrastructureawareofourcustomelement;wedothisbyregisteringourcustomnamespaceHandlerandcustomXSDfilein two special purpose properties files. These properties files are bothplaced in a 'META-INF' directory in your application, and can, forexample,bedistributedalongsideyourbinaryclassesinaJARfile.TheSpring XML parsing infrastructurewill automatically pick up your newextension by consuming these special properties files, the formats ofwhicharedetailedbelow.
B.5.1.'META-INF/spring.handlers'Thepropertiesfilecalled'spring.handlers'containsamappingofXMLSchemaURIs to namespace handler classes. So for our example, weneedtowritethefollowing:
http\://www.mycompany.com/schema/myns=org.springframework.samples.xml.MyNamespaceHandler
(The':'characterisavaliddelimiterintheJavapropertiesformat,andsothe':'characterintheURIneedstobeescapedwithabackslash.)The firstpart (thekey)of thekey-valuepair is theURIassociatedwithyourcustomnamespaceextension,andneedstomatchexactlythevalueof the 'targetNamespace' attribute as specified in your custom XSDschema.
B.5.2.'META-INF/spring.schemas'Theproperties file called'spring.schemas' containsamappingof XMLSchemalocations(referredtoalongwiththeschemadeclarationinXMLfilesthatusetheschemaaspartofthe'xsi:schemaLocation'attribute)toclasspathresources.ThisfileisneededtopreventSpringfromabsolutelyhaving to useadefaultEntityResolver that requires Internet access toretrievetheschemafile.Ifyouspecifythemappinginthispropertiesfile,Spring will search for the schema on the classpath (in this case'myns.xsd'inthe'org.springframework.samples.xml'package):
http\://www.mycompany.com/schema/myns/myns.xsd=org/springframework/samples/xml/myns.xsd
TheupshotofthisisthatyouareencouragedtodeployyourXSDfile(s)right alongside the NamespaceHandler and BeanDefinitionParser classesontheclasspath.
B.6. Using a custom extension in your Spring XMLconfigurationUsing a custom extension that you yourself have implemented is nodifferent fromusingoneof the 'custom'extensions thatSpringprovidesstraight out of the box. Find below an example of using the custom<dateformat/>elementdevelopedinthepreviousstepsinaSpringXMLconfigurationfile.
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:myns="http://www.mycompany.com/schema/myns"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.mycompany.com/schema/mynshttp://www.mycompany.com/schema/myns/myns.xsd">
<!--asatop-levelbean-->
<myns:dateformatid="defaultDateFormat"pattern="yyyy-MM-ddHH:mm"lenient="true"/>
<beanid="jobDetailTemplate"abstract="true">
<propertyname="dateFormat">
<!--asaninnerbean-->
<myns:dateformatpattern="HH:mmMM-dd-yyyy"/>
</property>
</bean>
</beans>
B.7.MeatierexamplesFindbelowsomemuchmeatierexamplesofcustomXMLextensions.
B.7.1.NestingcustomtagswithincustomtagsThis example illustrates how you might go about writing the variousartifactsrequiredtosatisfyatargetofthefollowingconfiguration:
<?xmlversion="1.0"encoding="UTF-8"?>
<beansxmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:foo="http://www.foo.com/schema/component"
xsi:schemaLocation="
http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.foo.com/schema/componenthttp://www.foo.com/schema/component/component.xsd">
<foo:componentid="bionic-family"name="Bionic-1">
<foo:componentname="Sport-1"/>
<foo:componentname="Rock-1"/>
</foo:component>
</beans>
The above configuration actually nests custom extensions within eachother. The class that is actually configured by the above<foo:component/>elementistheComponentclass(showndirectlybelow).NoticehowtheComponentclassdoesnotexposeasettermethodforthe'components' property; this makes it hard (or rather impossible) toconfigureabeandefinitionfortheComponentclassusingsetterinjection.
packagecom.foo;
importjava.util.ArrayList;
importjava.util.List;
publicclassComponent{
privateStringname;
privateListcomponents=newArrayList();
//mmm,thereisnosettermethodforthe'components'
publicvoidaddComponent(Componentcomponent){
this.components.add(component);
}
publicListgetComponents(){
returncomponents;
}
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
}
The typicalsolution to this issue is tocreateacustomFactoryBean thatexposesasetterpropertyforthe'components'property.
packagecom.foo;
importorg.springframework.beans.factory.FactoryBean;
importjava.util.Iterator;
importjava.util.List;
publicclassComponentFactoryBeanimplementsFactoryBean{
privateComponentparent;
privateListchildren;
publicvoidsetParent(Componentparent){
this.parent=parent;
}
publicvoidsetChildren(Listchildren){
this.children=children;
}
publicObjectgetObject()throwsException{
if(this.children!=null&&this.children.size()>0){
for(Iteratorit=children.iterator();it.hasNext();){
ComponentchildComponent=(Component)it.next();
this.parent.addComponent(childComponent);
}
}
returnthis.parent;
}
publicClassgetObjectType(){
returnComponent.class;
}
publicbooleanisSingleton(){
returntrue;
}
}
This is all verywell, anddoesworknicely, but exposesa lot ofSpringplumbing to the end user.What we are going to do is write a customextension that hides awayall of thisSpring plumbing. Ifwe stick to thestepsdescribedpreviously,we'llstartoffbycreatingtheXSDschematodefinethestructureofourcustomtag.
<?xmlversion="1.0"encoding="UTF-8"standalone="no"?>
<xsd:schemaxmlns="http://www.foo.com/schema/component"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foo.com/schema/component"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:elementname="component">
<xsd:complexType>
<xsd:choiceminOccurs="0"maxOccurs="unbounded">
<xsd:elementref="component"/>
</xsd:choice>
<xsd:attributename="id"type="xsd:ID"/>
<xsd:attributename="name"use="required"type="xsd:string"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>
We'llthencreateacustomNamespaceHandler.
packagecom.foo;
importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;
publicclassComponentNamespaceHandlerextendsNamespaceHandlerSupport{
publicvoidinit(){
registerBeanDefinitionParser("component",newComponentBeanDefinitionParser());
}
}
Next up is the custom BeanDefinitionParser. Remember that what wearecreatingisaBeanDefinitiondescribingaComponentFactoryBean.
packagecom.foo;
importorg.springframework.beans.factory.support.AbstractBeanDefinition;
importorg.springframework.beans.factory.support.BeanDefinitionBuilder;
importorg.springframework.beans.factory.support.ManagedList;
importorg.springframework.beans.factory.xml.AbstractBeanDefinitionParser;
importorg.springframework.beans.factory.xml.ParserContext;
importorg.springframework.util.xml.DomUtils;
importorg.w3c.dom.Element;
importjava.util.List;
publicclassComponentBeanDefinitionParserextendsAbstractBeanDefinitionParser{
protectedAbstractBeanDefinitionparseInternal(Elementelement,ParserContextparserContext){
BeanDefinitionBuilderfactory=BeanDefinitionBuilder.rootBeanDefinition(ComponentFactoryBean.class);
BeanDefinitionBuilderparent=parseComponent(element);
factory.addPropertyValue("parent",parent.getBeanDefinition());
ListchildElements=DomUtils.getChildElementsByTagName(element,"component");
if(childElements!=null&&childElements.size()>0){
parseChildComponents(childElements,factory);
}
returnfactory.getBeanDefinition();
}
privatestaticBeanDefinitionBuilderparseComponent(Elementelement){
BeanDefinitionBuildercomponent=BeanDefinitionBuilder.rootBeanDefinition(Component.class);
component.addPropertyValue("name",element.getAttribute("name"));
returncomponent;
}
privatestaticvoidparseChildComponents(ListchildElements,BeanDefinitionBuilderfactory){
ManagedListchildren=newManagedList(childElements.size());
for(inti=0;i<childElements.size();++i){
ElementchildElement=(Element)childElements.get(i);
BeanDefinitionBuilderchild=parseComponent(childElement);
children.add(child.getBeanDefinition());
}
factory.addPropertyValue("children",children);
}
}
Lastly, the various artifacts need to be registeredwith the Spring XMLinfrastructure.
#in'META-INF/spring.handlers'
http\://www.foo.com/schema/component=com.foo.ComponentNamespaceHandler
#in'META-INF/spring.schemas'
http\://www.foo.com/schema/component/component.xsd=com/foo/component.xsd
B.7.2.Customattributeson'normal'elementsWriting your own customparser and the associated artifacts isn't hard,butsometimesitisnottherightthingtodo.Considerthescenariowhereyou need to addmetadata to already existing bean definitions. In thiscaseyoucertainlydon'twanttohavetogooffandwriteyourownentirecustomextension; rather you justwant toaddanadditionalattribute totheexistingbeandefinitionelement.Bywayofanotherexample, let'ssaythattheserviceclassthatyouaredefiningabeandefinitionforaserviceobjectthatwill(unknowntoit)be
accessing a clustered JCache, and you want to ensure that the namedJCacheinstanceiseagerlystartedwithinthesurroundingcluster:
<beanid="checkingAccountService"class="com.foo.DefaultCheckingAccountService"
jcache:cache-name="checking.account">
<!--otherdependencieshere...-->
</bean>
WhatwearegoingtodohereiscreateanotherBeanDefinitionwhenthe'jcache:cache-name' attribute is parsed; this BeanDefinition will theninitialize the named JCache for us. We will also modify the existingBeanDefinition for the 'checkingAccountService' so that it will have adependencyonthisnewJCache-initializingBeanDefinition.
packagecom.foo;
publicclassJCacheInitializer{
privateStringname;
publicJCacheInitializer(Stringname){
this.name=name;
}
publicvoidinitialize(){
//lotsofJCacheAPIcallstoinitializethenamedcache...
}
}
Nowontothecustomextension.Firstly,theauthoringoftheXSDschemadescribingthecustomattribute(quiteeasyinthiscase).
<?xmlversion="1.0"encoding="UTF-8"standalone="no"?>
<xsd:schemaxmlns="http://www.foo.com/schema/jcache"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.foo.com/schema/jcache"
elementFormDefault="qualified">
<xsd:attributename="cache-name"type="xsd:string"/>
</xsd:schema>
Next,theassociatedNamespaceHandler.
packagecom.foo;
importorg.springframework.beans.factory.xml.NamespaceHandlerSupport;
publicclassJCacheNamespaceHandlerextendsNamespaceHandlerSupport{
publicvoidinit(){
super.registerBeanDefinitionDecoratorForAttribute("cache-name",
newJCacheInitializingBeanDefinitionDecorator());
}
}
Next, the parser. Note that in this case, because we are going to beparsinganXMLattribute,wewriteaBeanDefinitionDecoratorratherthanaBeanDefinitionParser.
packagecom.foo;
importorg.springframework.beans.factory.config.BeanDefinitionHolder;
importorg.springframework.beans.factory.support.AbstractBeanDefinition;
importorg.springframework.beans.factory.support.BeanDefinitionBuilder;
importorg.springframework.beans.factory.xml.BeanDefinitionDecorator;
importorg.springframework.beans.factory.xml.ParserContext;
importorg.w3c.dom.Attr;
importorg.w3c.dom.Node;
importjava.util.ArrayList;
importjava.util.Arrays;
importjava.util.List;
publicclassJCacheInitializingBeanDefinitionDecoratorimplementsBeanDefinitionDecorator{
privatestaticfinalString[]EMPTY_STRING_ARRAY=newString[0];
publicBeanDefinitionHolderdecorate(
Nodesource,BeanDefinitionHolderholder,ParserContextctx){
StringinitializerBeanName=registerJCacheInitializer(source,ctx);
createDependencyOnJCacheInitializer(holder,initializerBeanName);
returnholder;
}
privatevoidcreateDependencyOnJCacheInitializer(BeanDefinitionHolderholder,StringinitializerBeanName){
AbstractBeanDefinitiondefinition=((AbstractBeanDefinition)holder.getBeanDefinition());
String[]dependsOn=definition.getDependsOn();
if(dependsOn==null){
dependsOn=newString[]{initializerBeanName};
}else{
Listdependencies=newArrayList(Arrays.asList(dependsOn));
dependencies.add(initializerBeanName);
dependsOn=(String[])dependencies.toArray(EMPTY_STRING_ARRAY);
}
definition.setDependsOn(dependsOn);
}
privateStringregisterJCacheInitializer(Nodesource,ParserContextctx){
StringcacheName=((Attr)source).getValue();
StringbeanName=cacheName+"-initializer";
if(!ctx.getRegistry().containsBeanDefinition(beanName)){
BeanDefinitionBuilderinitializer=BeanDefinitionBuilder.rootBeanDefinition(JCacheInitializer.class);
initializer.addConstructorArg(cacheName);
ctx.getRegistry().registerBeanDefinition(beanName,initializer.getBeanDefinition());
}
returnbeanName;
}
}
Lastly, the various artifacts need to be registeredwith the Spring XMLinfrastructure.
#in'META-INF/spring.handlers'
http\://www.foo.com/schema/jcache=com.foo.JCacheNamespaceHandler
#in'META-INF/spring.schemas'
http\://www.foo.com/schema/jcache/jcache.xsd=com/foo/jcache.xsd
B.8.FurtherResourcesFindbelow links to further resources concerningXMLSchemaand theextensibleXMLsupportdescribedinthischapter.
TheXMLSchemaPart1:StructuresSecondEdition
TheXMLSchemaPart2:DatatypesSecondEdition
C.spring-beans-2.0.dtd
<!--
SpringXMLBeansDTD,version2.0
Authors:RodJohnson,JuergenHoeller,AlefArendsen,ColinSampaleanu,RobHarrop
Thisdefinesasimpleandconsistentwayofcreatinganamespace
ofJavaBeansobjects,managedbyaSpringBeanFactory,readby
XmlBeanDefinitionReader(withDefaultBeanDefinitionDocumentReader).
ThisdocumenttypeisusedbymostSpringfunctionality,including
webapplicationcontexts,whicharebasedonbeanfactories.
Each"bean"elementinthisdocumentdefinesaJavaBean.
Typicallythebeanclassisspecified,alongwithJavaBeanproperties
and/orconstructorarguments.
Abeaninstancecanbea"singleton"(sharedinstance)ora"prototype"
(independentinstance).Furtherscopescanbeprovidedbyextended
beanfactories,forexampleinawebenvironment.
Referencesamongbeansaresupported,thatis,settingaJavaBeanproperty
oraconstructorargumenttorefertoanotherbeaninthesamefactory
(oranancestorfactory).
Asalternativetobeanreferences,"innerbeandefinitions"canbeused.
Singletonflagsofsuchinnerbeandefinitionsareeffectivelyignored:
Innerbeansaretypicallyanonymousprototypes.
Thereisalsosupportforlists,sets,maps,andjava.util.Properties
asbeanpropertytypesorconstructorargumenttypes.
Forsimplepurposes,thisDTDissufficient.AsofSpring2.0,
XSD-basedbeandefinitionsaresupportedasmorepowerfulalternative.
XMLdocumentsthatconformtothisDTDshoulddeclarethefollowingdoctype:
<!DOCTYPEbeansPUBLIC"-//SPRING//DTDBEAN2.0//EN"
"http://www.springframework.org/dtd/spring-beans-2.0.dtd">
-->
<!--
Thedocumentroot.Adocumentcancontainbeandefinitionsonly,
importsonly,oramixtureofboth(typicallywithimportsfirst).
-->
<!ELEMENTbeans(
description?,
(import|alias|bean)*
)>
<!--
Defaultvaluesforallbeandefinitions.Canbeoverriddenat
the"bean"level.Seethoseattributedefinitionsfordetails.
-->
<!ATTLISTbeansdefault-lazy-init(true|false)"false">
<!ATTLISTbeansdefault-autowire(no|byName|byType|constructor|autodetect)"no">
<!ATTLISTbeansdefault-dependency-check(none|objects|simple|all)"none">
<!ATTLISTbeansdefault-init-methodCDATA#IMPLIED>
<!ATTLISTbeansdefault-destroy-methodCDATA#IMPLIED>
<!ATTLISTbeansdefault-merge(true|false)"false">
<!--
Elementcontaininginformativetextdescribingthepurposeoftheenclosing
element.Alwaysoptional.
UsedprimarilyforuserdocumentationofXMLbeandefinitiondocuments.
-->
<!ELEMENTdescription(#PCDATA)>
<!--
SpecifiesanXMLbeandefinitionresourcetoimport.
-->
<!ELEMENTimportEMPTY>
<!--
TherelativeresourcelocationoftheXMLbeandefinitionfiletoimport,
forexample"myImport.xml"or"includes/myImport.xml"or"../myImport.xml".
-->
<!ATTLISTimportresourceCDATA#REQUIRED>
<!--
Definesanaliasforabean,whichcanresideinadifferentdefinitionfile.
-->
<!ELEMENTaliasEMPTY>
<!--
Thenameofthebeantodefineanaliasfor.
-->
<!ATTLISTaliasnameCDATA#REQUIRED>
<!--
Thealiasnametodefineforthebean.
-->
<!ATTLISTaliasaliasCDATA#REQUIRED>
<!--
Allowsforarbitrarymetadatatobeattachedtoabeandefinition.
-->
<!ELEMENTmetaEMPTY>
<!--
Specifiesthekeynameofthemetadataparameterbeingdefined.
-->
<!ATTLISTmetakeyCDATA#REQUIRED>
<!--
SpecifiesthevalueofthemetadataparameterbeingdefinedasaString.
-->
<!ATTLISTmetavalueCDATA#REQUIRED>
<!--
Definesasingle(usuallynamed)bean.
Abeandefinitionmaycontainnestedtagsforconstructorarguments,
propertyvalues,lookupmethods,andreplacedmethods.Mixingconstructor
injectionandsetterinjectiononthesamebeanisexplicitlysupported.
-->
<!ELEMENTbean(
description?,
(meta|constructor-arg|property|lookup-method|replaced-method)*
)>
<!--
Beanscanbeidentifiedbyanid,toenablereferencechecking.
ThereareconstraintsonavalidXMLid:ifyouwanttoreferenceyourbean
inJavacodeusinganamethat'sillegalasanXMLid,usetheoptional
"name"attribute.Ifneitherisgiven,thebeanclassnameisusedasid
(withanappendedcounterlike"#2"ifthereisalreadyabeanwiththatname).
-->
<!ATTLISTbeanidID#IMPLIED>
<!--
Optional.Canbeusedtocreateoneormorealiasesillegalinanid.
Multiplealiasescanbeseparatedbyanynumberofspaces,commas,or
semi-colons(orindeedanymixtureofthethree).
-->
<!ATTLISTbeannameCDATA#IMPLIED>
<!--
Eachbeandefinitionmustspecifythefullyqualifiednameoftheclass,
exceptifitpureservesasparentforchildbeandefinitions.
-->
<!ATTLISTbeanclassCDATA#IMPLIED>
<!--
Optionallyspecifyaparentbeandefinition.
Willusethebeanclassoftheparentifnonespecified,butcan
alsooverrideit.Inthelattercase,thechildbeanclassmustbe
compatiblewiththeparent,i.e.accepttheparent'spropertyvalues
andconstructorargumentvalues,ifany.
Achildbeandefinitionwillinheritconstructorargumentvalues,
propertyvaluesandmethodoverridesfromtheparent,withtheoption
toaddnewvalues.Ifinitmethod,destroymethod,factorybeanand/orfactory
methodarespecified,theywilloverridethecorrespondingparentsettings.
Theremainingsettingswillalwaysbetakenfromthechilddefinition:
dependson,autowiremode,dependencycheck,scope,lazyinit.
-->
<!ATTLISTbeanparentCDATA#IMPLIED>
<!--
Thescopeofthisbean:typically"singleton"(onesharedinstance,
whichwillbereturnedbyallcallstogetBean()withtheid),
or"prototype"(independentinstanceresultingfromeachcallto
getBean().Defaultis"singleton".
Singletonsaremostcommonlyused,andareidealformulti-threaded
serviceobjects.Furtherscopes,suchas"request"or"session",
mightbesupportedbyextendedbeanfactories(forexample,ina
webenvironment).
Note:Thisattributewillnotbeinheritedbychildbeandefinitions.
Hence,itneedstobespecifiedperconcretebeandefinition.
Innerbeandefinitionsinheritthesingletonstatusoftheircontaining
beandefinition,unlessexplicitlyspecified:Theinnerbeanwillbea
singletonifthecontainingbeanisasingleton,andaprototypeif
thecontainingbeanhasanyotherscope.
-->
<!ATTLISTbeanscopeCDATA#IMPLIED>
<!--
Isthisbean"abstract",i.e.notmeanttobeinstantiateditselfbut
ratherjustservingasparentforconcretechildbeandefinitions.
Defaultis"false".Specify"true"totellthebeanfactorytonottryto
instantiatethatparticularbeaninanycase.
Note:Thisattributewillnotbeinheritedbychildbeandefinitions.
Hence,itneedstobespecifiedperabstractbeandefinition.
-->
<!ATTLISTbeanabstract(true|false)#IMPLIED>
<!--
Ifthisbeanshouldbelazilyinitialized.
Iffalse,itwillgetinstantiatedonstartupbybeanfactories
thatperformeagerinitializationofsingletons.
Note:Thisattributewillnotbeinheritedbychildbeandefinitions.
Hence,itneedstobespecifiedperconcretebeandefinition.
-->
<!ATTLISTbeanlazy-init(true|false|default)"default">
<!--
Indicateswhetherornotthisbeanshouldbeconsideredwhenlooking
forcandidatestosatisfyanotherbeansautowiringrequirements.
-->
<!ATTLISTbeanautowire-candidate(true|false)#IMPLIED>
<!--
Optionalattributecontrollingwhetherto"autowire"beanproperties.
Thisisanautomagicalprocessinwhichbeanreferencesdon'tneedtobecoded
explicitlyintheXMLbeandefinitionfile,butSpringworksoutdependencies.
Thereare5modes:
1."no"
ThetraditionalSpringdefault.Noautomagicalwiring.Beanreferences
mustbedefinedintheXMLfileviathe<ref>element.Werecommendthis
inmostcasesasitmakesdocumentationmoreexplicit.
2."byName"
Autowiringbypropertyname.IfabeanofclassCatexposesadogproperty,
Springwilltrytosetthistothevalueofthebean"dog"inthecurrentfactory.
Ifthereisnomatchingbeanbyname,nothingspecialhappens;
usedependency-check="objects"toraiseanerrorinthatcase.
3."byType"
Autowiringifthereisexactlyonebeanofthepropertytypeinthebeanfactory.
Ifthereismorethanone,afatalerrorisraised,andyoucan'tusebyType
autowiringforthatbean.Ifthereisnone,nothingspecialhappens;
usedependency-check="objects"toraiseanerrorinthatcase.
4."constructor"
Analogousto"byType"forconstructorarguments.Ifthereisn'texactlyonebean
oftheconstructorargumenttypeinthebeanfactory,afatalerrorisraised.
5."autodetect"
Chooses"constructor"or"byType"throughintrospectionofthebeanclass.
Ifadefaultconstructorisfound,"byType"getsapplied.
ThelattertwoaresimilartoPicoContainerandmakebeanfactoriessimpleto
configureforsmallnamespaces,butdoesn'tworkaswellasstandardSpring
behaviourforbiggerapplications.
Notethatexplicitdependencies,i.e."property"and"constructor-arg"elements,
alwaysoverrideautowiring.Autowirebehaviorcanbecombinedwithdependency
checking,whichwillbeperformedafterallautowiringhasbeencompleted.
Note:Thisattributewillnotbeinheritedbychildbeandefinitions.
Hence,itneedstobespecifiedperconcretebeandefinition.
-->
<!ATTLISTbeanautowire(no|byName|byType|constructor|autodetect|default)"default">
<!--
Optionalattributecontrollingwhethertocheckwhetherallthis
beansdependencies,expressedinitsproperties,aresatisfied.
Defaultisnodependencychecking.
"simple"typedependencycheckingincludesprimitivesandString;
"objects"includescollaborators(otherbeansinthefactory);
"all"includesbothtypesofdependencychecking.
Note:Thisattributewillnotbeinheritedbychildbeandefinitions.
Hence,itneedstobespecifiedperconcretebeandefinition.
-->
<!ATTLISTbeandependency-check(none|objects|simple|all|default)"default">
<!--
Thenamesofthebeansthatthisbeandependsonbeinginitialized.
Thebeanfactorywillguaranteethatthesebeansgetinitializedbefore.
Notethatdependenciesarenormallyexpressedthroughbeanpropertiesor
constructorarguments.Thispropertyshouldjustbenecessaryforotherkinds
ofdependencieslikestatics(*ugh*)ordatabasepreparationonstartup.
Note:Thisattributewillnotbeinheritedbychildbeandefinitions.
Hence,itneedstobespecifiedperconcretebeandefinition.
-->
<!ATTLISTbeandepends-onCDATA#IMPLIED>
<!--
Optionalattributeforthenameofthecustominitializationmethod
toinvokeaftersettingbeanproperties.Themethodmusthavenoarguments,
butmaythrowanyexception.
-->
<!ATTLISTbeaninit-methodCDATA#IMPLIED>
<!--
Optionalattributeforthenameofthecustomdestroymethodtoinvoke
onbeanfactoryshutdown.Themethodmusthavenoarguments,
butmaythrowanyexception.
Note:Onlyinvokedonbeanswhoselifecycleisunderfullcontrol
ofthefactory-whichisalwaysthecaseforsingletons,butnot
guaranteedforanyotherscope.
-->
<!ATTLISTbeandestroy-methodCDATA#IMPLIED>
<!--
Optionalattributespecifyingthenameofafactorymethodtouseto
createthisobject.Useconstructor-argelementstospecifyarguments
tothefactorymethod,ifittakesarguments.Autowiringdoesnotapply
tofactorymethods.
Ifthe"class"attributeispresent,thefactorymethodwillbeastatic
methodontheclassspecifiedbythe"class"attributeonthisbean
definition.Oftenthiswillbethesameclassasthatoftheconstructed
object-forexample,whenthefactorymethodisusedasanalternative
toaconstructor.However,itmaybeonadifferentclass.Inthatcase,
thecreatedobjectwill*not*beoftheclassspecifiedinthe"class"
attribute.ThisisanalogoustoFactoryBeanbehavior.
Ifthe"factory-bean"attributeispresent,the"class"attributeisnot
used,andthefactorymethodwillbeaninstancemethodontheobject
returnedfromagetBeancallwiththespecifiedbeanname.Thefactory
beanmaybedefinedasasingletonoraprototype.
Thefactorymethodcanhaveanynumberofarguments.Autowiringisnot
supported.Useindexedconstructor-argelementsinconjunctionwiththe
factory-methodattribute.
SetterInjectioncanbeusedinconjunctionwithafactorymethod.
MethodInjectioncannot,asthefactorymethodreturnsaninstance,
whichwillbeusedwhenthecontainercreatesthebean.
-->
<!ATTLISTbeanfactory-methodCDATA#IMPLIED>
<!--
Alternativetoclassattributeforfactory-methodusage.
Ifthisisspecified,noclassattributeshouldbeused.
Thisshouldbesettothenameofabeaninthecurrentor
ancestorfactoriesthatcontainstherelevantfactorymethod.
ThisallowsthefactoryitselftobeconfiguredusingDependency
Injection,andaninstance(ratherthanstatic)methodtobeused.
-->
<!ATTLISTbeanfactory-beanCDATA#IMPLIED>
<!--
Beandefinitionscanspecifyzeroormoreconstructorarguments.
Thisisanalternativeto"autowireconstructor".
Argumentscorrespondtoeitheraspecificindexoftheconstructorargument
listoraresupposedtobematchedgenericallybytype.
Note:Asinglegenericargumentvaluewilljustbeusedonce,ratherthan
potentiallymatchedmultipletimes(asofSpring1.1).
constructor-argelementsarealsousedinconjunctionwiththefactory-method
elementtoconstructbeansusingstaticorinstancefactorymethods.
-->
<!ELEMENTconstructor-arg(
description?,
(bean|ref|idref|value|null|list|set|map|props)?
)>
<!--
Theconstructor-argtagcanhaveanoptionalindexattribute,
tospecifytheexactindexintheconstructorargumentlist.Onlyneeded
toavoidambiguities,e.g.incaseof2argumentsofthesametype.
-->
<!ATTLISTconstructor-argindexCDATA#IMPLIED>
<!--
Theconstructor-argtagcanhaveanoptionaltypeattribute,
tospecifytheexacttypeoftheconstructorargument.Onlyneeded
toavoidambiguities,e.g.incaseof2singleargumentconstructors
thatcanbothbeconvertedfromaString.
-->
<!ATTLISTconstructor-argtypeCDATA#IMPLIED>
<!--
Ashort-cutalternativetoachildelement"refbean=".
-->
<!ATTLISTconstructor-argrefCDATA#IMPLIED>
<!--
Ashort-cutalternativetoachildelement"value".
-->
<!ATTLISTconstructor-argvalueCDATA#IMPLIED>
<!--
Beandefinitionscanhavezeroormoreproperties.
PropertyelementscorrespondtoJavaBeansettermethodsexposed
bythebeanclasses.Springsupportsprimitives,referencestoother
beansinthesameorrelatedfactories,lists,mapsandproperties.
-->
<!ELEMENTproperty(
description?,meta*,
(bean|ref|idref|value|null|list|set|map|props)?
)>
<!--
ThepropertynameattributeisthenameoftheJavaBeanproperty.
ThisfollowsJavaBeanconventions:anameof"age"wouldcorrespond
tosetAge()/optionalgetAge()methods.
-->
<!ATTLISTpropertynameCDATA#REQUIRED>
<!--
Ashort-cutalternativetoachildelement"refbean=".
-->
<!ATTLISTpropertyrefCDATA#IMPLIED>
<!--
Ashort-cutalternativetoachildelement"value".
-->
<!ATTLISTpropertyvalueCDATA#IMPLIED>
<!--
AlookupmethodcausestheIoCcontainertooverridethegivenmethodandreturn
thebeanwiththenamegiveninthebeanattribute.ThisisaformofMethodInjection.
It'sparticularlyusefulasanalternativetoimplementingtheBeanFactoryAware
interface,inordertobeabletomakegetBean()callsfornon-singletoninstances
atruntime.Inthiscase,MethodInjectionisalessinvasivealternative.
-->
<!ELEMENTlookup-methodEMPTY>
<!--
Nameofalookupmethod.Thismethodshouldtakenoarguments.
-->
<!ATTLISTlookup-methodnameCDATA#IMPLIED>
<!--
Nameofthebeaninthecurrentorancestorfactoriesthatthelookupmethod
shouldresolveto.Oftenthisbeanwillbeaprototype,inwhichcasethe
lookupmethodwillreturnadistinctinstanceoneveryinvocation.This
isusefulforsingle-threadedobjects.
-->
<!ATTLISTlookup-methodbeanCDATA#IMPLIED>
<!--
Similartothelookupmethodmechanism,thereplaced-methodelementisusedtocontrol
IoCcontainermethodoverriding:MethodInjection.Thismechanismallowstheoverriding
ofamethodwitharbitrarycode.
-->
<!ELEMENTreplaced-method(
(arg-type)*
)>
<!--
NameofthemethodwhoseimplementationshouldbereplacedbytheIoCcontainer.
Ifthismethodisnotoverloaded,there'snoneedtousearg-typesubelements.
Ifthismethodisoverloaded,arg-typesubelementsmustbeusedforall
overridedefinitionsforthemethod.
-->
<!ATTLISTreplaced-methodnameCDATA#IMPLIED>
<!--
BeannameofanimplementationoftheMethodReplacerinterfaceinthecurrent
orancestorfactories.Thismaybeasingletonorprototypebean.Ifit's
aprototype,anewinstancewillbeusedforeachmethodreplacement.
Singletonusageisthenorm.
-->
<!ATTLISTreplaced-methodreplacerCDATA#IMPLIED>
<!--
Subelementofreplaced-methodidentifyinganargumentforareplacedmethod
intheeventofmethodoverloading.
-->
<!ELEMENTarg-type(#PCDATA)>
<!--
SpecificationofthetypeofanoverloadedmethodargumentasaString.
Forconvenience,thismaybeasubstringoftheFQN.E.g.allthe
followingwouldmatch"java.lang.String":
-java.lang.String
-String
-Str
Asthenumberofargumentswillbecheckedalso,thisconveniencecanoften
beusedtosavetyping.
-->
<!ATTLISTarg-typematchCDATA#IMPLIED>
<!--
Definesareferencetoanotherbeaninthisfactoryoranexternal
factory(parentorincludedfactory).
-->
<!ELEMENTrefEMPTY>
<!--
Referencesmustspecifyanameofthetargetbean.
The"bean"attributecanreferenceanynamefromanybeaninthecontext,
tobecheckedatruntime.
Localreferences,usingthe"local"attribute,havetousebeanids;
theycanbecheckedbythisDTD,thusshouldbepreferredforreferences
withinthesamebeanfactoryXMLfile.
-->
<!ATTLISTrefbeanCDATA#IMPLIED>
<!ATTLISTreflocalIDREF#IMPLIED>
<!ATTLISTrefparentCDATA#IMPLIED>
<!--
Definesastringpropertyvalue,whichmustalsobetheidofanother
beaninthisfactoryoranexternalfactory(parentorincludedfactory).
Whilearegular'value'elementcouldinsteadbeusedforthesameeffect,
usingidrefinthiscaseallowsvalidationoflocalbeanidsbytheXML
parser,andnamecompletionbysupportingtools.
-->
<!ELEMENTidrefEMPTY>
<!--
IDrefsmustspecifyanameofthetargetbean.
The"bean"attributecanreferenceanynamefromanybeaninthecontext,
potentiallytobecheckedatruntimebybeanfactoryimplementations.
Localreferences,usingthe"local"attribute,havetousebeanids;
theycanbecheckedbythisDTD,thusshouldbepreferredforreferences
withinthesamebeanfactoryXMLfile.
-->
<!ATTLISTidrefbeanCDATA#IMPLIED>
<!ATTLISTidreflocalIDREF#IMPLIED>
<!--
Containsastringrepresentationofapropertyvalue.
Thepropertymaybeastring,ormaybeconvertedtotherequired
typeusingtheJavaBeansPropertyEditormachinery.Thismakesit
possibleforapplicationdeveloperstowritecustomPropertyEditor
implementationsthatcanconvertstringstoarbitrarytargetobjects.
Notethatthisisrecommendedforsimpleobjectsonly.
ConfiguremorecomplexobjectsbypopulatingJavaBean
propertieswithreferencestootherbeans.
-->
<!ELEMENTvalue(#PCDATA)>
<!--
Thevaluetagcanhaveanoptionaltypeattribute,tospecifythe
exacttypethatthevalueshouldbeconvertedto.Onlyneeded
ifthetypeofthetargetpropertyorconstructorargumentis
toogeneric:forexample,incaseofacollectionelement.
-->
<!ATTLISTvaluetypeCDATA#IMPLIED>
<!--
DenotesaJavanullvalue.Necessarybecauseanempty"value"tag
willresolvetoanemptyString,whichwillnotberesolvedtoa
nullvalueunlessaspecialPropertyEditordoesso.
-->
<!ELEMENTnull(#PCDATA)>
<!--
Alistcancontainmultipleinnerbean,ref,collection,orvalueelements.
Javalistsareuntyped,pendinggenericssupportinJava1.5,
althoughreferenceswillbestronglytyped.
Alistcanalsomaptoanarraytype.Thenecessaryconversion
isautomaticallyperformedbytheBeanFactory.
-->
<!ELEMENTlist(
(bean|ref|idref|value|null|list|set|map|props)*
)>
<!--
Enable/disablemergingforcollectionswhenusingparent/childbeans.
-->
<!ATTLISTlistmerge(true|false|default)"default">
<!--
SpecifythedefaultJavatypefornestedvalues.
-->
<!ATTLISTlistvalue-typeCDATA#IMPLIED>
<!--
Asetcancontainmultipleinnerbean,ref,collection,orvalueelements.
Javasetsareuntyped,pendinggenericssupportinJava1.5,
althoughreferenceswillbestronglytyped.
-->
<!ELEMENTset(
(bean|ref|idref|value|null|list|set|map|props)*
)>
<!--
Enable/disablemergingforcollectionswhenusingparent/childbeans.
-->
<!ATTLISTsetmerge(true|false|default)"default">
<!--
SpecifythedefaultJavatypefornestedvalues.
-->
<!ATTLISTsetvalue-typeCDATA#IMPLIED>
<!--
ASpringmapisamappingfromastringkeytoobject.
Mapsmaybeempty.
-->
<!ELEMENTmap(
(entry)*
)>
<!--
Enable/disablemergingforcollectionswhenusingparent/childbeans.
-->
<!ATTLISTmapmerge(true|false|default)"default">
<!--
SpecifythedefaultJavatypefornestedentrykeys.
-->
<!ATTLISTmapkey-typeCDATA#IMPLIED>
<!--
SpecifythedefaultJavatypefornestedentryvalues.
-->
<!ATTLISTmapvalue-typeCDATA#IMPLIED>
<!--
Amapentrycanbeaninnerbean,ref,value,orcollection.
Thekeyoftheentryisgivenbythe"key"attributeorchildelement.
-->
<!ELEMENTentry(
key?,
(bean|ref|idref|value|null|list|set|map|props)?
)>
<!--
Eachmapelementmustspecifyitskeyasattributeoraschildelement.
AkeyattributeisalwaysaStringvalue.
-->
<!ATTLISTentrykeyCDATA#IMPLIED>
<!--
Ashort-cutalternativetoa"key"elementwitha"refbean="childelement.
-->
<!ATTLISTentrykey-refCDATA#IMPLIED>
<!--
Ashort-cutalternativetoachildelement"value".
-->
<!ATTLISTentryvalueCDATA#IMPLIED>
<!--
Ashort-cutalternativetoachildelement"refbean=".
-->
<!ATTLISTentryvalue-refCDATA#IMPLIED>
<!--
Akeyelementcancontainaninnerbean,ref,value,orcollection.
-->
<!ELEMENTkey(
(bean|ref|idref|value|null|list|set|map|props)
)>
<!--
Propselementsdifferfrommapelementsinthatvaluesmustbestrings.
Propsmaybeempty.
-->
<!ELEMENTprops(
(prop)*
)>
<!--
Enable/disablemergingforcollectionswhenusingparent/childbeans.
-->
<!ATTLISTpropsmerge(true|false|default)"default">
<!--
Elementcontentisthestringvalueoftheproperty.
Notethatwhitespaceistrimmedofftoavoidunwantedwhitespace
causedbytypicalXMLformatting.
-->
<!ELEMENTprop(#PCDATA)>
<!--
Eachpropertyelementmustspecifyitskey.
-->
<!ATTLISTpropkeyCDATA#REQUIRED>
D.spring.tld
D.1.IntroductionD.2.ThebindtagD.3.TheescapeBodytagD.4.ThehasBindErrorstagD.5.ThehtmlEscapetagD.6.ThemessagetagD.7.ThenestedPathtagD.8.ThethemetagD.9.Thetransformtag
D.1.IntroductionOneoftheviewtechnologiesyoucanusewiththeSpringFrameworkisJava Server Pages (JSPs). To help you implement views using JavaServer Pages the Spring Framework provides you with some tags forevaluating errors, setting themes and outputting internationalizedmessages.Pleasenote that thevarious tagsgeneratedby this form tag libraryarecompliantwiththeXHTML-1.0-StrictspecificationandattendantDTD.Thisappendixdescribesthespring.tldtaglibrary.
D.2“The bindtag”
D.3“The escapeBodytag”
D.4“The hasBindErrorstag”
D.5“The htmlEscapetag”
D.6“The messagetag”
D.7“The nestedPathtag”
D.8“The themetag”
D.9“The transformtag”
D.2.ThebindtagProvidesBindStatusobjectforthegivenbindpath.TheHTMLescapingflag participates in a page-wide or application-wide setting (i.e. byHtmlEscapeTagora"defaultHtmlEscape"context-paraminweb.xml).
D.1.Attributes
Attribute Required? RuntimeExpression?Description
htmlEscape false true
SetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.
ignoreNestedPath false true Setwhethertoignoreanestedpath,ifany.Defaultistonotignore.
path true true
Thepathtothebeanorbeanpropertytobindstatusinformationfor.Forinstanceaccount.name,company.address.zipCodeorjustemployee.Thestatusobjectwillexportedtothepagescope,specificallyforthisbeanorbeanproperty
D.3.TheescapeBodytagEscapes its enclosed body content, applying HTML escaping and/orJavaScript escaping. The HTML escaping flag participates in a page-wide or application-wide setting (i.e. by HtmlEscapeTag or a"defaultHtmlEscape"context-paraminweb.xml).
D.2.Attributes
Attribute Required? RuntimeExpression?Description
htmlEscape false true
SetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.
javaScriptEscape false true SetJavaScriptescapingforthistag,asbooleanvalue.Defaultisfalse.
D.4.ThehasBindErrorstagProvidesErrorsinstanceincaseofbinderrors.TheHTMLescapingflagparticipates in a page-wide or application-wide setting (i.e. byHtmlEscapeTagora"defaultHtmlEscape"context-paraminweb.xml).
D.3.Attributes
AttributeRequired? RuntimeExpression?Description
htmlEscape false trueSetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.
name true true
Thenameofthebeanintherequest,thatneedstobeinspectedforerrors.Iferrorsareavailableforthisbean,theywillbeboundunderthe'errors'key.
D.5.ThehtmlEscapetagSets default HTML escape value for the current page. Overrides a"defaultHtmlEscape"context-paraminweb.xml,ifany.
D.4.Attributes
Attribute Required? RuntimeExpression?Description
defaultHtmlEscape true trueSetthedefaultvalueforHTMLescaping,tobeputintothecurrentPageContext.
D.6.ThemessagetagRetrieves the message with the given code, or text if code isn'tresolvable. The HTML escaping flag participates in a page-wide orapplication-widesetting(i.e.byHtmlEscapeTagora"defaultHtmlEscape"context-paraminweb.xml).
D.5.Attributes
Attribute Required? RuntimeExpression?Description
arguments false true
Setoptionalmessageargumentsforthistag,asa(comma-)delimitedString(eachStringargumentcancontainJSPEL),anObjectarray(usedasargumentarray),orasingleObject(usedassingleargument).
argumentSeparator false trueTheseparatorcharactertobeusedforsplittingtheargumentsstringvalue;defaultstoa'comma'(',').
code false trueThecode(key)tousewhenlookingupthemessage.Ifcodeisnotprovided,thetextattributewillbeused.
htmlEscape false true
SetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.
javaScriptEscape false true SetJavaScriptescapingforthistag,asbooleanvalue.Defaultisfalse.
message false true
AMessageSourceResolvableargument(directorthroughJSPEL).FitsnicelywhenusedinconjunctionwithSpring'sownvalidationerrorclasseswhichallimplementtheMessageSourceResolvableinterface.Forexample,thisallowsyoutoiterateoveralloftheerrorsinaform,passingeacherror(usingaruntimeexpression)asthevalueofthis'message'attribute,thuseffectingtheeasydisplayofsucherrormessages.
Thescopetousewhenexportingthe
scope false trueresulttoavariable.Thisattributeisonlyusedwhenvarisalsoset.Possiblevaluesarepage,request,sessionandapplication.
text false true
Defaulttexttooutputwhenamessageforthegivencodecouldnotbefound.Ifbothtextandcodearenotset,thetagwilloutputnull.
var false true
Thestringtousewhenbindingtheresulttothepage,request,sessionorapplicationscope.Ifnotspecified,theresultgetsoutputtedtothewriter(i.e.typicallydirectlytotheJSP).
D.7.ThenestedPathtagSetsanestedpathtobeusedbythebindtag'spath.
D.6.Attributes
AttributeRequired? RuntimeExpression?Description
path true true
Setthepaththatthistagshouldapply.E.g.'customer'toallowbindpathslike'address.street'ratherthan'customer.address.street'.
D.8.ThethemetagRetrieves the thememessagewith the given code, or text if code isn'tresolvable. The HTML escaping flag participates in a page-wide orapplication-widesetting(i.e.byHtmlEscapeTagora"defaultHtmlEscape"context-paraminweb.xml).
D.7.Attributes
Attribute Required? RuntimeExpression?Description
arguments false true
Setoptionalmessageargumentsforthistag,asa(comma-)delimitedString(eachStringargumentcancontainJSPEL),anObjectarray(usedasargumentarray),orasingleObject(usedassingleargument).
argumentSeparator false trueTheseparatorcharactertobeusedforsplittingtheargumentsstringvalue;defaultstoa'comma'(',').
code false trueThecode(key)tousewhenlookingupthemessage.Ifcodeisnotprovided,thetextattributewillbeused.
htmlEscape false true
SetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.
javaScriptEscape false true SetJavaScriptescapingforthistag,asbooleanvalue.Defaultisfalse.
message false true AMessageSourceResolvableargument(directorthroughJSPEL).
scope false true
Thescopetousewhenexportingtheresulttoavariable.Thisattributeisonlyusedwhenvarisalsoset.Possiblevaluesarepage,request,sessionandapplication.
text false true
Defaulttexttooutputwhenamessageforthegivencodecouldnotbefound.Ifbothtextandcodearenotset,thetagwilloutputnull.
var false true
Thestringtousewhenbindingtheresulttothepage,request,sessionorapplicationscope.Ifnotspecified,theresultgetsoutputtedtothewriter(i.e.typicallydirectlytotheJSP).
D.9.ThetransformtagProvides transformation of variables to Strings, using an appropriatecustomPropertyEditor fromBindTag(canonlybeused insideBindTag).TheHTMLescapingflagparticipates inapage-wideorapplication-widesetting(i.e.byHtmlEscapeTagora'defaultHtmlEscape'context-paraminweb.xml).
D.8.Attributes
AttributeRequired? RuntimeExpression?Description
htmlEscape false trueSetHTMLescapingforthistag,asbooleanvalue.OverridesthedefaultHTMLescapingsettingforthecurrentpage.
scope false true
Thescopetousewhenexportedtheresulttoavariable.Thisattributeisonlyusedwhenvarisalsoset.Possiblevaluesarepage,request,sessionandapplication.
value true true
Thevaluetotransform.Thisistheactualobjectyouwanttohavetransformed(forinstanceaDate).UsingthePropertyEditorthatiscurrentlyinusebythe'spring:bind'tag.
var false true
Thestringtousewhenbindingtheresulttothepage,request,sessionorapplicationscope.Ifnotspecified,theresultgetsoutputtedtothewriter(i.e.typicallydirectlytotheJSP).
E.spring-form.tld
E.1.IntroductionE.2.ThecheckboxtagE.3.ThecheckboxestagE.4.TheerrorstagE.5.TheformtagE.6.ThehiddentagE.7.TheinputtagE.8.ThelabeltagE.9.TheoptiontagE.10.TheoptionstagE.11.ThepasswordtagE.12.TheradiobuttontagE.13.TheradiobuttonstagE.14.TheselecttagE.15.Thetextareatag
E.1.IntroductionOneoftheviewtechnologiesyoucanusewiththeSpringFrameworkisJava Server Pages (JSPs). To help you implement views using JavaServer Pages the Spring Framework provides you with some tags forevaluating errors, setting themes and outputting internationalizedmessages.Pleasenote that thevarious tagsgeneratedby this form tag libraryarecompliantwiththeXHTML-1.0-StrictspecificationandattendantDTD.Thisappendixdescribesthespring-form.tldtaglibrary.
E.2“The checkboxtag”
E.3“The checkboxestag”
E.4“The errorstag”
E.5“The formtag”
E.6“The hiddentag”
E.7“The inputtag”
E.8“The labeltag”
E.9“The optiontag”
E.10“The optionstag”
E.11“The passwordtag”
E.12“The radiobuttontag”
E.13“The radiobuttonstag”
E.14“The selecttag”
E.15“The textareatag”
E.2.ThecheckboxtagRendersanHTML'input'tagwithtype'checkbox'.
E.1.Attributes
Attribute Required? RuntimeExpression?Description
accesskey false true HTMLStandardAttribute
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
label false true Valuetobedisplayedaspartofthetag
lang false true HTMLStandardAttribute
onblur false true HTMLEventAttribute
onchange false true HTMLEventAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onfocus false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path true true Pathtopropertyfordatabinding
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
value false true HTMLOptionalAttribute
E.3.ThecheckboxestagRendersmultipleHTML'input'tagswithtype'checkbox'.
E.2.Attributes
Attribute Required? RuntimeExpression?Description
accesskey false true HTMLStandardAttribute
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
delimiter false trueDelimitertousebetweeneach'input'tagwithtype'checkbox'.Thereisnodelimiterbydefault.
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
element false trueSpecifiestheHTMLelementthatisusedtoencloseeach'input'tagwithtype'checkbox'.Defaultsto'span'.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
itemLabel false true Valuetobedisplayedaspartofthe'input'tagswithtype'checkbox'
items true trueTheCollection,Maporarrayofobjectsusedtogeneratethe'input'tagswithtype'checkbox'
Nameofthepropertymappedto'value'
itemValue false true attributeofthe'input'tagswithtype'checkbox'
lang false true HTMLStandardAttribute
onblur false true HTMLEventAttribute
onchange false true HTMLEventAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onfocus false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path true true Pathtopropertyfordatabinding
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
E.4.TheerrorstagRendersfielderrorsinanHTML'span'tag.
E.3.Attributes
Attribute Required? RuntimeExpression? Description
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
delimiter false true Delimiterfordisplayingmultipleerrormessages.Defaultstothebrtag.
dir false true HTMLStandardAttribute
element false true SpecifiestheHTMLelementthatisusedtorendertheenclosingerrors.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
lang false true HTMLStandardAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path false true Pathtoerrorsobjectfordatabinding
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
E.5.TheformtagRendersanHTML'form'tagandexposesabindingpathtoinnertagsforbinding.
E.4.Attributes
Attribute Required? RuntimeExpression?Description
acceptCharset false true
Specifiesthelistofcharacterencodingsforinputdatathatisacceptedbytheserverprocessingthisform.Thevalueisaspace-and/orcomma-delimitedlistofcharsetvalues.Theclientmustinterpretthislistasanexclusive-orlist,i.e.,theserverisabletoacceptanysinglecharacterencodingperentityreceived.
action false true HTMLRequiredAttribute
commandName false trueNameofthemodelattributeunderwhichtheformobjectisexposed.Defaultsto'command'.
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
enctype false true HTMLOptionalAttribute
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
lang false true HTMLStandardAttribute
method false true HTMLOptionalAttribute
modelAttribute false trueNameofthemodelattributeunderwhichtheformobjectisexposed.Defaultsto'command'.
name false true HTMLStandardAttribute-addedforbackwardscompatibilitycases
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
onreset false true HTMLEventAttribute
onsubmit false true HTMLEventAttribute
title false true HTMLStandardAttribute
E.6.ThehiddentagRendersanHTML'input'tagwithtype'hidden'usingtheboundvalue.
E.5.Attributes
AttributeRequired? RuntimeExpression? Description
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
path true true Pathtopropertyfordatabinding
E.7.TheinputtagRendersanHTML'input'tagwithtype'text'usingtheboundvalue.
E.6.Attributes
Attribute Required? RuntimeExpression?Description
accesskey false true HTMLStandardAttribute
alt false true HTMLOptionalAttribute
autocomplete false true CommonOptionalAttribute
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
lang false true HTMLStandardAttribute
maxlength false true HTMLOptionalAttribute
onblur false true HTMLEventAttribute
onchange false true HTMLEventAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onfocus false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
onselect false true HTMLEventAttribute
path true true Pathtopropertyfordatabinding
readonly false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willmaketheHTMLelementreadonly.
size false true HTMLOptionalAttribute
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
E.8.ThelabeltagRendersaformfieldlabelinanHTML'label'tag.
E.7.Attributes
Attribute Required? RuntimeExpression?Description
cssClass false true Equivalentto"class"-HTMLOptionalAttribute.
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedonlywhenerrorsarepresent.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
for false true HTMLStandardAttribute
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
lang false true HTMLStandardAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path true true Pathtoerrorsobjectfordatabinding
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
E.9.TheoptiontagRendersasingleHTML'option'.Sets'selected'asappropriatebasedonboundvalue.
E.8.Attributes
Attribute Required? RuntimeExpression?Description
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
label false true HTMLOptionalAttribute
lang false true HTMLStandardAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
value true true HTMLOptionalAttribute
E.10.TheoptionstagRendersalistofHTML'option'tags.Sets'selected'asappropriatebasedonboundvalue.
E.9.Attributes
Attribute Required? RuntimeExpression?Description
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
itemLabel false true Nameofthepropertymappedtotheinnertextofthe'option'tag
items true true TheCollection,Maporarrayofobjectsusedtogeneratetheinner'option'tags
itemValue false true Nameofthepropertymappedto'value'attributeofthe'option'tag
lang false true HTMLStandardAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
E.11.ThepasswordtagRendersanHTML'input'tagwithtype'password'usingtheboundvalue.
E.10.Attributes
Attribute Required? RuntimeExpression?Description
accesskey false true HTMLStandardAttribute
alt false true HTMLOptionalAttribute
autocomplete false true CommonOptionalAttribute
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
lang false true HTMLStandardAttribute
maxlength false true HTMLOptionalAttribute
onblur false true HTMLEventAttribute
onchange false true HTMLEventAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onfocus false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
onselect false true HTMLEventAttribute
path true true Pathtopropertyfordatabinding
readonly false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willmaketheHTMLelementreadonly.
showPassword false true Isthepasswordvaluetobeshown?Defaultstofalse.
size false true HTMLOptionalAttribute
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
E.12.TheradiobuttontagRendersanHTML'input'tagwithtype'radio'.
E.11.Attributes
Attribute Required? RuntimeExpression?Description
accesskey false true HTMLStandardAttribute
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
label false true Valuetobedisplayedaspartofthetag
lang false true HTMLStandardAttribute
onblur false true HTMLEventAttribute
onchange false true HTMLEventAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onfocus false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path true true Pathtopropertyfordatabinding
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
value false true HTMLOptionalAttribute
E.13.TheradiobuttonstagRendersmultipleHTML'input'tagswithtype'radio'.
E.12.Attributes
Attribute Required? RuntimeExpression?Description
accesskey false true HTMLStandardAttribute
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
delimiter false trueDelimitertousebetweeneach'input'tagwithtype'radio'.Thereisnodelimiterbydefault.
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
element false trueSpecifiestheHTMLelementthatisusedtoencloseeach'input'tagwithtype'radio'.Defaultsto'span'.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
itemLabel false true Valuetobedisplayedaspartofthe'input'tagswithtype'radio'
items true true TheCollection,Maporarrayofobjectsusedtogeneratethe'input'tagswithtype'radio'
itemValue false true Nameofthepropertymappedto'value'attributeofthe'input'tagswithtype'radio'
lang false true HTMLStandardAttribute
onblur false true HTMLEventAttribute
onchange false true HTMLEventAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onfocus false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path true true Pathtopropertyfordatabinding
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
E.14.TheselecttagRendersanHTML'select'element.Supportsdatabindingtotheselectedoption.
E.13.Attributes
Attribute Required? RuntimeExpression?Description
accesskey false true HTMLStandardAttribute
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
itemLabel false true Nameofthepropertymappedtotheinnertextofthe'option'tag
items false true TheCollection,Maporarrayofobjectsusedtogeneratetheinner'option'tags
itemValue false true Nameofthepropertymappedto'value'attributeofthe'option'tag
lang false true HTMLStandardAttribute
multiple false true HTMLOptionalAttribute
onblur false true HTMLEventAttribute
onchange false true HTMLEventAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onfocus false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
path true true Pathtopropertyfordatabinding
size false true HTMLOptionalAttribute
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
E.15.ThetextareatagRendersanHTML'textarea'.
E.14.Attributes
Attribute Required? RuntimeExpression?Description
accesskey false true HTMLStandardAttribute
cols false true HTMLRequiredAttribute
cssClass false true Equivalentto"class"-HTMLOptionalAttribute
cssErrorClass false trueEquivalentto"class"-HTMLOptionalAttribute.Usedwhentheboundfieldhaserrors.
cssStyle false true Equivalentto"style"-HTMLOptionalAttribute
dir false true HTMLStandardAttribute
disabled false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willdisabletheHTMLelement.
htmlEscape false true Enable/disableHTMLescapingofrenderedvalues.
id false true HTMLStandardAttribute
lang false true HTMLStandardAttribute
onblur false true HTMLEventAttribute
onchange false true HTMLEventAttribute
onclick false true HTMLEventAttribute
ondblclick false true HTMLEventAttribute
onfocus false true HTMLEventAttribute
onkeydown false true HTMLEventAttribute
onkeypress false true HTMLEventAttribute
onkeyup false true HTMLEventAttribute
onmousedown false true HTMLEventAttribute
onmousemove false true HTMLEventAttribute
onmouseout false true HTMLEventAttribute
onmouseover false true HTMLEventAttribute
onmouseup false true HTMLEventAttribute
onselect false true HTMLEventAttribute
path true true Pathtopropertyfordatabinding
readonly false trueHTMLOptionalAttribute.Settingthevalueofthisattributeto'true'(withoutthequotes)willmaketheHTMLelementreadonly.
rows false true HTMLRequiredAttribute
tabindex false true HTMLStandardAttribute
title false true HTMLStandardAttribute
F.Spring2.5
F.1.F.2.F.3.F.4.
F.1.SpringSpring Framework( http://www.redsaga.com)Spring(http://spring.jactiongroup.net)SpringFrameworkApache2.0()Apache2.0
F.2.SpringJava
F.3.DigitalSonicDenis
F.1.
Yanger Caoxg
DigitalSonic MarcoChen
downpour joyheros
jzk whimet
melthaw crazycy
pesome zhanglong
ginge Kxllen
Jin Java
Joo YuLimin
Echo yeshucheng
Denis
hanson2010 88250
max
(Spring2.5)
F.4.20080305312.594521
20080308SpringSpringzhanglongginge24http://wiki.redsaga.com/confluence/pages/viewpage.action?pageId=26792.020080312KxllenJinJavaJoo4538
20080315YuLiminEchoyeshucheng40crazycy18yeshucheng20080319511xmlcvs20080322Denis118420080326451511200803293hanson201088250max2520080402RodJohnson----SpringSourceInfoQ……2112
200804052.0XML261220080412Wiki
20080419~Denis20080426Denis2.0CVS2008050345161515CVS200805102.5max123061020080517
20080525
20080601
zhanglong20080608
2008061534568zhanglongpesome2008062245820080630
SpringFramework2.54
top related