spring 注解事务
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) { try { Document doc = doLoadDocument(inputSource, resource); return registerBeanDefinitions(doc, resource); } doc = <beans >跟标签, attributes = [default-autowire="default", default-lazy-init="true", default-merge="default", xmlns="http://www.springframework.org/schema/beans", xmlns:aop="http://www.springframework.org/schema/aop", xmlns:cache="http://www.springframework.org/s...... ....... ......ta/jpahema/cache/spring-cache.xsd"] children = [ [context:property-placeholder: null], [context:component-scan: null], [bean: dataSource], [bean: transactionManager], [aop:aspectj-autoproxy: null], [bean: jdbcTemplate], [tx:annotation-driven: null],]
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { NodeList nl = root.getChildNodes(); //解析<beans>根节点, for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { Element ele = (Element) node; if (delegate.isDefaultNamespace(ele)) { parseDefaultElement(ele, delegate); } else { delegate.parseCustomElement(ele); } } } }
解析[context:property-placeholder: null]标签, delegate.parseCustomElement(ele); //ele = context:property-placeholder标签 public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); //http://www.springframework.org/schema/context, NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); //ContextNamespaceHandler里面找到解析类PropertyPlaceholderBeanDefinitionParser, return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); //名字是org.springframework.context.support.PropertySourcesPlaceholderConfigurer#0,内容是PropertySourcesPlaceholderConfigurer加入到spring的容器,解析的是core.properties里面的数据库的连接用户名密码地址信息。 locations = [classpath*:config/core/core.properties], ignoreResourceNotFound = false, localOverride = fasle ignoreUnresolvablePlaceholders = false. }
解析[context:component-scan: null]标签:(把扫描的bean的定义加到spring的容器) public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele);//http://www.springframework.org/schema/context, NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);//ContextNamespaceHandler里面找到解析类ComponentScanBeanDefinitionParser, return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } public BeanDefinition parse(Element element, ParserContext parserContext) { String[] basePackages = StringUtils.tokenizeToStringArray(element.getAttribute(BASE_PACKAGE_ATTRIBUTE), ConfigurableApplicationContext.CONFIG_LOCATION_DELIMITERS);//[com.zhuguang.jack] ClassPathBeanDefinitionScanner scanner = configureScanner(parserContext, element); Set<BeanDefinitionHolder> beanDefinitions = scanner.doScan(basePackages);//ClassPathBeanDefinitionScanner,返回AnnotationServiceImpl的bean定义(并且已经加到容器中去了), registerComponents(parserContext.getReaderContext(), beanDefinitions, element); return null; }
protected ClassPathBeanDefinitionScanner configureScanner(ParserContext parserContext, Element element) { XmlReaderContext readerContext = parserContext.getReaderContext();//XmlReaderContext boolean useDefaultFilters = true; if (element.hasAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE)) { useDefaultFilters = Boolean.valueOf(element.getAttribute(USE_DEFAULT_FILTERS_ATTRIBUTE));//true } ClassPathBeanDefinitionScanner scanner = createScanner(readerContext, useDefaultFilters); scanner.setResourceLoader(readerContext.getResourceLoader());//ClassPathXmlApplicationContext scanner.setEnvironment(parserContext.getDelegate().getEnvironment()); scanner.setBeanDefinitionDefaults(parserContext.getDelegate().getBeanDefinitionDefaults()); scanner.setAutowireCandidatePatterns(parserContext.getDelegate().getAutowireCandidatePatterns()); if (element.hasAttribute(RESOURCE_PATTERN_ATTRIBUTE)) { scanner.setResourcePattern(element.getAttribute(RESOURCE_PATTERN_ATTRIBUTE)); } try { parseBeanNameGenerator(element, scanner); } try { parseScope(element, scanner);//解析context:component-scan标签的scope属性, } parseTypeFilters(element, scanner, readerContext, parserContext);//解析context:component-scan标签的TypeFilters属性, return scanner; }
protected ClassPathBeanDefinitionScanner createScanner(XmlReaderContext readerContext, boolean useDefaultFilters) { return new ClassPathBeanDefinitionScanner(readerContext.getRegistry(), useDefaultFilters); //里面有bean工厂, }
protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = new LinkedHashSet<BeanDefinitionHolder>(); for (String basePackage : basePackages) { Set<BeanDefinition> candidates = findCandidateComponents(basePackage); for (BeanDefinition candidate : candidates) {//AnnotationServiceImpl ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(candidate); candidate.setScope(scopeMetadata.getScopeName()); String beanName = this.beanNameGenerator.generateBeanName(candidate, this.registry); if (checkCandidate(beanName, candidate)) { BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(candidate, beanName); definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry); beanDefinitions.add(definitionHolder); registerBeanDefinition(definitionHolder, this.registry); //bean的定义注册到容器, } } } return beanDefinitions; }
public Set<BeanDefinition> findCandidateComponents(String basePackage) { try { String packageSearchPath = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + resolveBasePackage(basePackage) + "/" + this.resourcePattern; //classpath*:com/zhuguang/jack/**/*.class, Resource[] resources = this.resourcePatternResolver.getResources(packageSearchPath); //AnnotationServiceImpl.class,MyService.class,Test2.class for (Resource resource : resources) { if (resource.isReadable()) { MetadataReader metadataReader = this.metadataReaderFactory.getMetadataReader(resource); ScannedGenericBeanDefinition sbd = new ScannedGenericBeanDefinition(metadataReader); if (isCandidateComponent(sbd)) { candidates.add(sbd); } } } return candidates;//AnnotationServiceImpl }
解析<bean id="dataSource">标签: protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //Bean definition with name 'dataSource' and aliases []: Generic bean: class [com.mchange.v2.c3p0.ComboPooledDataSource]; if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); //注册到spring容器, } getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); //dataSource AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); //返回GenericBeanDefinition,里面的class = [com.mchange.v2.c3p0.ComboPooledDataSource] if (beanDefinition != null) { String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); //beanDefinition = Generic bean: class [com.mchange.v2.c3p0.ComboPooledDataSource],beanName = dataSource , aliasesArray = [], } }
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) { String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { //class属性, className = ele.getAttribute(CLASS_ATTRIBUTE).trim();//com.mchange.v2.c3p0.ComboPooledDataSource } try { String parent = null; AbstractBeanDefinition bd = createBeanDefinition(className, parent); //返回GenericBeanDefinition,里面的class = [com.mchange.v2.c3p0.ComboPooledDataSource] parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); return bd; } }
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, BeanDefinition containingBean, AbstractBeanDefinition bd) { String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); if (DEFAULT_VALUE.equals(lazyInit)) { lazyInit = this.defaults.getLazyInit(); } bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); //true, return bd; }
解析<bean id="transactionManager">标签: protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //beanDefinition = Generic bean: class [org.springframework.jdbc.datasource.DataSourceTransactionManager]; beanName = transactionManager, if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); //注册到spring的容器, } getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } } public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); //transactionManager AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); //Generic bean: class [org.springframework.jdbc.datasource.DataSourceTransactionManager]; if (beanDefinition != null) { } String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); //beanDefinition = Generic bean: class [org.springframework.jdbc.datasource.DataSourceTransactionManager]; beanName = transactionManager, } return null; }
解析<aop:aspectj-autoproxy/>标签: public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele);//http://www.springframework.org/schema/aop, NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); //handler = AopNamespaceHandler, return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); //AspectJAutoProxyBeanDefinitionParser } public BeanDefinition parse(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAspectJAnnotationAutoProxyCreatorIfNecessary(parserContext, element);//注册AnnotationAwareAspectJAutoProxyCreator,名字叫做org.springframework.aop.config.internalAutoProxyCreator,内容是class [org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator];到spring容器。最后包装成BeanComponentDefinition,名字还是叫org.springframework.aop.config.internalAutoProxyCreator,BeanComponentDefinition里面有AnnotationAwareAspectJAutoProxyCreator。 extendBeanDefinition(element, parserContext); return null; }
解析JdbcTemplate标签: protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //'jdbcTemplate' and aliases []: Generic bean: class [org.springframework.jdbc.core.JdbcTemplate]; if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); //注册到spring容器, } getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } } public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) { String id = ele.getAttribute(ID_ATTRIBUTE); //jdbcTemplate AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); //Generic bean: class [org.springframework.jdbc.core.JdbcTemplate]; if (beanDefinition != null) { String[] aliasesArray = StringUtils.toStringArray(aliases); return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); } }
解析[tx:annotation-driven: null]标签: public BeanDefinition parseCustomElement(Element ele, BeanDefinition containingBd) { String namespaceUri = getNamespaceURI(ele); NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); //TxNamespaceHandler return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); //AnnotationDrivenBeanDefinitionParser } public BeanDefinition parse(Element element, ParserContext parserContext) { String mode = element.getAttribute("mode"); if ("aspectj".equals(mode)) { } else { AopAutoProxyConfigurer.configureAutoProxyCreator(element, parserContext); } return null; }
public static void configureAutoProxyCreator(Element element, ParserContext parserContext) { AopNamespaceUtils.registerAutoProxyCreatorIfNecessary(parserContext, element);//增加注解事务的入口类InfrastructureAdvisorAutoProxyCreator到spring容器, String txAdvisorBeanName = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME; //internalTransactionAdvisor, if (!parserContext.getRegistry().containsBeanDefinition(txAdvisorBeanName)) { Object eleSource = parserContext.extractSource(element); //null RootBeanDefinition sourceDef = new RootBeanDefinition("org.springframework.transaction.annotation.AnnotationTransactionAttributeSource"); //事务属性的bean定义,里面有SpringTransactionAnnotationParser,去注解里面拿到属性值。 sourceDef.setSource(eleSource); sourceDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); String sourceName = parserContext.getReaderContext().registerWithGeneratedName(sourceDef); RootBeanDefinition interceptorDef = new RootBeanDefinition(TransactionInterceptor.class); interceptorDef.setSource(eleSource); interceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registerTransactionManager(element, interceptorDef); interceptorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName)); String interceptorName = parserContext.getReaderContext().registerWithGeneratedName(interceptorDef); RootBeanDefinition advisorDef = new RootBeanDefinition(BeanFactoryTransactionAttributeSourceAdvisor.class); //里面new TransactionAttributeSourcePointcut advisorDef.setSource(eleSource); advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); advisorDef.getPropertyValues().add("transactionAttributeSource", new RuntimeBeanReference(sourceName)); advisorDef.getPropertyValues().add("adviceBeanName", interceptorName); //TransactionInterceptor if (element.hasAttribute("order")) { advisorDef.getPropertyValues().add("order", element.getAttribute("order")); } parserContext.getRegistry().registerBeanDefinition(txAdvisorBeanName, advisorDef); //internalTransactionAdvisor,BeanFactoryTransactionAttributeSourceAdvisor CompositeComponentDefinition compositeDef = new CompositeComponentDefinition(element.getTagName(), eleSource); compositeDef.addNestedComponent(new BeanComponentDefinition(sourceDef, sourceName)); //AnnotationTransactionAttributeSource,AnnotationTransactionAttributeSource#0 compositeDef.addNestedComponent(new BeanComponentDefinition(interceptorDef, interceptorName)); //TransactionInterceptor,TransactionInterceptor#0 compositeDef.addNestedComponent(new BeanComponentDefinition(advisorDef, txAdvisorBeanName));//BeanFactoryTransactionAttributeSourceAdvisor,internalTransactionAdvisor parserContext.registerComponent(compositeDef); } }
public static void registerAutoProxyCreatorIfNecessary( ParserContext parserContext, Element sourceElement) { BeanDefinition beanDefinition = AopConfigUtils.registerAutoProxyCreatorIfNecessary(parserContext.getRegistry(), parserContext.extractSource(sourceElement)); useClassProxyingIfNecessary(parserContext.getRegistry(), sourceElement); registerComponentIfNecessary(beanDefinition, parserContext); }
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) { if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { //internalAutoProxyCreator BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); //AnnotationAwareAspectJAutoProxyCreator if (!cls.getName().equals(apcDefinition.getBeanClassName())) {//cls = InfrastructureAdvisorAutoProxyCreator, int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); int requiredPriority = findPriorityForClass(cls); if (currentPriority < requiredPriority) { apcDefinition.setBeanClassName(cls.getName()); } } return null; } RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); beanDefinition.setSource(source); beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); return beanDefinition; }
此时bean工厂里面有
[internalAutoProxyCreator,
PropertySourcesPlaceholderConfigurer#0,
annotationServiceImpl,
internalConfigurationAnnotationProcessor,
internalAutowiredAnnotationProcessor,
internalRequiredAnnotationProcessor,
internalCommonAnnotationProcessor,
dataSource,
transactionManager,
jdbcTemplate,
AnnotationTransactionAttributeSource#0,
TransactionInterceptor#0,
internalTransactionAdvisor,
ConfigurationClassPostProcessor.importAwareProcessor,
ConfigurationClassPostProcessor.enhancedConfigurationProcessor]
public static void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List<BeanFactoryPostProcessor> beanFactoryPostProcessors) { if (beanFactory instanceof BeanDefinitionRegistry) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); //internalConfigurationAnnotationProcessor for (String ppName : postProcessorNames) { if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) { priorityOrderedPostProcessors.add(beanFactory.getBean(ppName, BeanDefinitionRegistryPostProcessor.class));//ConfigurationClassPostProcessor } } invokeBeanDefinitionRegistryPostProcessors(priorityOrderedPostProcessors, registry);//注册ImportAwareBeanPostProcessor,EnhancedConfigurationBeanPostProcessor到spring容器, postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); //internalConfigurationAnnotationProcessor boolean reiterate = true; while (reiterate) { reiterate = false; postProcessorNames = beanFactory.getBeanNamesForType(BeanDefinitionRegistryPostProcessor.class, true, false); //internalConfigurationAnnotationProcessor } invokeBeanFactoryPostProcessors(registryPostProcessors, beanFactory); invokeBeanFactoryPostProcessors(regularPostProcessors, beanFactory); } String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);//PropertySourcesPlaceholderConfigurer invokeBeanFactoryPostProcessors(priorityOrderedPostProcessors, beanFactory); //PropertySourcesPlaceholderConfigurer,解析jdbc的用户名密码地址。 }
public static void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) { String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false); //[internalAutoProxyCreator, internalAutowiredAnnotationProcessor, internalRequiredAnnotationProcessor, internalCommonAnnotationProcessor, ConfigurationClassPostProcessor.importAwareProcessor, ConfigurationClassPostProcessor.enhancedConfigurationProcessor] registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors); //[ConfigurationClassPostProcessor$ImportAwareBeanPostProcessor@acdb094, ConfigurationClassPostProcessor$EnhancedConfigurationBeanPostProcessor@674bd420, CommonAnnotationBeanPostProcessor@2b0f373b, AutowiredAnnotationBeanPostProcessor@2ceb80a1, RequiredAnnotationBeanPostProcessor@4b45dcb8] List<BeanPostProcessor> orderedPostProcessors = new ArrayList<BeanPostProcessor>(); for (String ppName : orderedPostProcessorNames) { BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);//internalAutoProxyCreator(AnnotationAwareAspectJAutoProxyCreator),initializeBean方法里面的invokeAwareMethods方法设置this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory), orderedPostProcessors.add(pp); if (pp instanceof MergedBeanDefinitionPostProcessor) { internalPostProcessors.add(pp); } } registerBeanPostProcessors(beanFactory, internalPostProcessors);//[CommonAnnotationBeanPostProcessor@2b0f373b, AutowiredAnnotationBeanPostProcessor@2ceb80a1, RequiredAnnotationBeanPostProcessor@4b45dcb8] beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext)); }
getBean(beanName); //internalAutoProxyCreator getBean(AnnotationTransactionAttributeSource);解析AnnotationTransactionAttributeSource,createBeanInstance方法才会去调用构造函数,注册SpringTransactionAnnotationParser,JtaTransactionAnnotationParser,Ejb3TransactionAnnotationParser。findAdvisorBeans()方法会设置AnnotationAwareAspectJAutoProxyCreator的advisorRetrievalHelper 的cachedAdvisorBeanNames属性 = internalTransactionAdvisor。(getbean(“”)的时候,会执行所有的BeanPostProcessors的postProcessAfterInitialization方法,然后会给这些所有的BeanPostProcessors设置一些属性值。同时也会给正在实例化的bean设置一些属性值。)然后getbean("internalTransactionAdvisor"), getBean(TransactionInterceptor);解析TransactionInterceptor,
MyService as = (MyService) context.getBean("annotationServiceImpl"); protected Object createBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {、 Object bean = resolveBeforeInstantiation(beanName, mbd); Object beanInstance = doCreateBean(beanName, mbd, args); return beanInstance; } protected Object resolveBeforeInstantiation(String beanName, RootBeanDefinition mbd) { if (!Boolean.FALSE.equals(mbd.beforeInstantiationResolved)) { if (mbd.hasBeanClass() && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) { bean = applyBeanPostProcessorsBeforeInstantiation(mbd.getBeanClass(), beanName); } } return bean; } protected Object applyBeanPostProcessorsBeforeInstantiation(Class<?> beanClass, String beanName) { for (BeanPostProcessor bp : getBeanPostProcessors()) { if (bp instanceof InstantiationAwareBeanPostProcessor) { Object result = ibp.postProcessBeforeInstantiation(beanClass, beanName); } return null; }
AnnotationAwareAspectJAutoProxyCreator类: public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) throws BeansException { Object cacheKey = getCacheKey(beanClass, beanName); //AnnotationServiceImpl_annotationServiceImpl,beanClass = class com.zhuguang.jack.service.AnnotationServiceImpl, if (beanName == null || !this.targetSourcedBeans.contains(beanName)) { if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { //是否有Aspect注解, this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } if (beanName != null) { TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { //null,不走, this.targetSourcedBeans.add(beanName); Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } } return null; }
protected boolean shouldSkip(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); //[org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'] } protected List<Advisor> findCandidateAdvisors() { List<Advisor> advisors = super.findCandidateAdvisors(); advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; }
public List<Advisor> findAdvisorBeans() { String[] advisorNames = null; synchronized (this) { advisorNames = this.cachedAdvisorBeanNames;//internalTransactionAdvisor,cachedAdvisorBeanNames是AnnotationAwareAspectJAutoProxyCreator的属性,在解析AnnotationTransactionAttributeSource时候设置的缓存。 } List<Advisor> advisors = new LinkedList<Advisor>(); for (String name : advisorNames) { if (isEligibleBean(name)) { else { try { advisors.add(this.beanFactory.getBean(name, Advisor.class)); //org.springframework.transaction.config.internalTransactionAdvisor,返回[org.springframework.transaction.interceptor.BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0'] } } } } return advisors; }
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) { for (BeanPostProcessor beanProcessor : getBeanPostProcessors()) { result = beanProcessor.postProcessAfterInitialization(result, beanName); } return result; }
AnnotationAwareAspectJAutoProxyCreator类: protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); // //BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' = TransactionInterceptor@7a138fc5, if (specificInterceptors != DO_NOT_PROXY) { this.advisedBeans.put(cacheKey, Boolean.TRUE); Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); //ProxyFactory: 1 interfaces [MyService]; 1 advisors [BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'TransactionInterceptor#0']; targetSource [[AnnotationServiceImpl@7c098bb3]]; this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } }
protected boolean shouldSkip(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); //BeanFactoryTransactionAttributeSourceAdvisor return super.shouldSkip(beanClass, beanName); //false } protected List<Advisor> findCandidateAdvisors() { List<Advisor> advisors = super.findCandidateAdvisors(); advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); return advisors; } protected List<Advisor> findCandidateAdvisors() { return this.advisorRetrievalHelper.findAdvisorBeans(); } public List<Advisor> findAdvisorBeans() { synchronized (this) { advisorNames = this.cachedAdvisorBeanNames; //internalTransactionAdvisor } for (String name : advisorNames) { advisors.add(this.beanFactory.getBean(name, Advisor.class)); //BeanFactoryTransactionAttributeSourceAdvisor } return advisors; }
protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); return advisors.toArray(); } protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { List<Advisor> candidateAdvisors = findCandidateAdvisors(); List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); extendAdvisors(eligibleAdvisors); return eligibleAdvisors; //BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' = TransactionInterceptor@7a138fc5, }
protected Object createProxy(Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) { ProxyFactory proxyFactory = new ProxyFactory(); proxyFactory.copyFrom(this); Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); //BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' for (Advisor advisor : advisors) { proxyFactory.addAdvisor(advisor); } return proxyFactory.getProxy(this.proxyClassLoader); }
protected Advisor[] buildAdvisors(String beanName, Object[] specificInterceptors) { Advisor[] commonInterceptors = resolveInterceptorNames();//[] List<Object> allInterceptors = new ArrayList<Object>(); if (specificInterceptors != null) { allInterceptors.addAll(Arrays.asList(specificInterceptors));//BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' if (commonInterceptors != null) { if (this.applyCommonInterceptorsFirst) { allInterceptors.addAll(0, Arrays.asList(commonInterceptors));//BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' } } } Advisor[] advisors = new Advisor[allInterceptors.size()]; for (int i = 0; i < allInterceptors.size(); i++) { advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i)); } return advisors;//BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'org.springframework.transaction.interceptor.TransactionInterceptor#0' }
as.saveTest1(111,111); // jdk动态代理,ProxyFactory: 1 interfaces [MyService]; 1 advisors [BeanFactoryTransactionAttributeSourceAdvisor: advice bean 'TransactionInterceptor#0']; targetSource [[AnnotationServiceImpl@7c098bb3]]; JdkDynamicAopProxy类: public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { if (target != null) { targetClass = target.getClass(); //AnnotationServiceImpl } List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); //advised = ProxyFactory,targetClass = AnnotationServiceImpl,method = saveTest1(int,int)。返回TransactionInterceptor@560cbf1a。 else { invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); retVal = invocation.proceed(); } }
public Object proceed() throws Throwable { // 链式调用, if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
TransactionInterceptor类: public Object invoke(final MethodInvocation invocation) throws Throwable { Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); //AnnotationServiceImpl return invokeWithinTransaction(invocation.getMethod(), targetClass, new InvocationCallback() { @Override public Object proceedWithInvocation() throws Throwable { return invocation.proceed();//执行方法,又进到 链式调用, } }); }
protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation) { final TransactionAttribute txAttr = getTransactionAttributeSource().getTransactionAttribute(method, targetClass); //getTransactionAttributeSource() = AnnotationTransactionAttributeSource, 获取AnnotationServiceImpl类saveTest1(int,int)方法上的事务注解属性。返回PROPAGATION_REQUIRES_NEW,ISOLATION_READ_COMMITTED; '',传播属性和隔离级别。 final PlatformTransactionManager tm = determineTransactionManager(txAttr); //DataSourceTransactionManager@23a9ba52实例, final String joinpointIdentification = methodIdentification(method, targetClass);//saveTest1方法名字, if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) { TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification); //开启事务txInfo,返回PROPAGATION_REQUIRES_NEW,ISOLATION_READ_COMMITTED; '', Object retVal = null; try { retVal = invocation.proceedWithInvocation(); //执行方法, } catch (Throwable ex) { completeTransactionAfterThrowing(txInfo, ex);//回滚事务txInfo, throw ex; } finally { cleanupTransactionInfo(txInfo); } commitTransactionAfterReturning(txInfo);//提交事务txInfo, return retVal; } }
public TransactionAttribute getTransactionAttribute(Method method, Class<?> targetClass) { //获取AnnotationServiceImpl类saveTest1(int,int)方法上的事务注解属性 Object cacheKey = getCacheKey(method, targetClass); Object cached = this.attributeCache.get(cacheKey); if (cached != null) { else { return (TransactionAttribute) cached; //PROPAGATION_REQUIRES_NEW,ISOLATION_READ_COMMITTED; '',传播属性和隔离级别。 } } }
protected TransactionInfo createTransactionIfNecessary(PlatformTransactionManager tm, TransactionAttribute txAttr, final String joinpointIdentification) { TransactionStatus status = null; if (txAttr != null) { if (tm != null) { status = tm.getTransaction(txAttr); //txAttr = PROPAGATION_REQUIRES_NEW,ISOLATION_READ_COMMITTED; '',返回//DefaultTransactionStatus@10b892d5 } } return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status); }
public final TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException { Object transaction = doGetTransaction(); //DataSourceTransactionManager$DataSourceTransactionObject@5aceec94,connectionHolder = null。 SuspendedResourcesHolder suspendedResources = suspend(null); //不挂起事务,因为没有事务, try { boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER); DefaultTransactionStatus status = newTransactionStatus(definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); //DefaultTransactionStatus@10b892d5 doBegin(transaction, definition); prepareSynchronization(status, definition); return status;//DefaultTransactionStatus@10b892d5 } }
protected Object doGetTransaction() { DataSourceTransactionObject txObject = new DataSourceTransactionObject(); txObject.setSavepointAllowed(isNestedTransactionAllowed()); ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager.getResource(obtainDataSource()); //null,第一次没有事务返回null。 txObject.setConnectionHolder(conHolder, false); return txObject; }
protected void doBegin(Object transaction, TransactionDefinition definition) { //开启事务, DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction; //DataSourceTransactionManager$DataSourceTransactionObject@5aceec94 Connection con = null; try { if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) { Connection newCon = obtainDataSource().getConnection(); txObject.setConnectionHolder(new ConnectionHolder(newCon), true); } txObject.getConnectionHolder().setSynchronizedWithTransaction(true); con = txObject.getConnectionHolder().getConnection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); if (con.getAutoCommit()) { txObject.setMustRestoreAutoCommit(true); con.setAutoCommit(false); } prepareTransactionalConnection(con, definition); txObject.getConnectionHolder().setTransactionActive(true); if (txObject.isNewConnectionHolder()) { TransactionSynchronizationManager.bindResource(obtainDataSource(), txObject.getConnectionHolder()); } } }
protected void commitTransactionAfterReturning(TransactionInfo txInfo) { //通过conn提交事务, if (txInfo != null && txInfo.hasTransaction()) { txInfo.getTransactionManager().commit(txInfo.getTransactionStatus()); } } public final void commit(TransactionStatus status) throws TransactionException { processCommit(defStatus); } private void processCommit(DefaultTransactionStatus status) throws TransactionException { doCommit(status); } protected void doCommit(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); try { con.commit(); } }
public class AnnotationServiceImpl implements MyService { @Autowired JdbcTemplate jdbcTemplate; @Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED) @Override public void saveTest1(int param1,int param2) { String sql = "insert into aa(id,name) values (?,?)"; int count = jdbcTemplate.update(sql, new Object[]{param1,param2}); throw new RuntimeException("saveTest1 异常"); }
protected void completeTransactionAfterThrowing(TransactionInfo txInfo, Throwable ex) { //回滚事务, if (txInfo != null && txInfo.hasTransaction()) { if (txInfo.transactionAttribute.rollbackOn(ex)) { try { txInfo.getTransactionManager().rollback(txInfo.getTransactionStatus()); //DataSourceTransactionManager,DefaultTransactionStatus } } } public final void rollback(TransactionStatus status) throws TransactionException { DefaultTransactionStatus defStatus = (DefaultTransactionStatus) status; processRollback(defStatus); } private void processRollback(DefaultTransactionStatus status) { doRollback(status); } protected void doRollback(DefaultTransactionStatus status) { DataSourceTransactionObject txObject = (DataSourceTransactionObject) status.getTransaction(); Connection con = txObject.getConnectionHolder().getConnection(); con.rollback(); }
@Service("annotationServiceImpl") @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Lazy(false) @Description("xx") public class AnnotationServiceImpl implements MyService { @Autowired JdbcTemplate jdbcTemplate; @Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED) @Override public void saveTest1(int param1,int param2) { String sql = "insert into aa(id,name) values (?,?)"; int count = jdbcTemplate.update(sql, new Object[]{param1,param2}); // saveTest2(param1,param2); } @Transactional(propagation = Propagation.REQUIRES_NEW,isolation = Isolation.READ_COMMITTED) @Override public void saveTest2(int param1,int param2) { String sql = "insert into aa(id) values (?)"; int count = jdbcTemplate.update(sql, new Object[]{param1,param2}); } }
public interface MyService { public void saveTest1(int param1,int para2); public void saveTest2(int param1,int para2); }
public class Test2 { public static void main(String[] args) { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath*:config" + "/spring/applicationContext-core.xml"); MyService as = (MyService) context.getBean("annotationServiceImpl"); as.saveTest1(111,111); } }
core.properties jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/upgrade?useUnicode=true&characterEncoding=utf-8&useSSL=false jdbc.username=root jdbc.password=123456
<?xml version="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:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:util="http://www.springframework.org/schema/util" xmlns:cache="http://www.springframework.org/schema/cache" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util.xsd http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd" default-lazy-init="true"> <aop:aspectj-autoproxy/> <!-- 导入外部属性文件 --> <context:property-placeholder location="classpath*:config/core/core.properties" /> <context:component-scan base-package="com.zhuguang.jack" use-default-filters="true" annotation-config="true"> </context:component-scan> <!-- 数据库连接池 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driver}"></property> <property name="jdbcUrl" value="${jdbc.url}"></property> <property name="user" value="${jdbc.username}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!--Transation--> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"></property> </bean> <tx:annotation-driven transaction-manager="transactionManager"/> </beans>
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.zhuguang.jack</groupId> <artifactId>spring-source-web</artifactId> <version>1.0-SNAPSHOT</version> <packaging>war</packaging> <name>spring-source-web Maven Webapp</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.source>1.8</maven.compiler.source> <maven.compiler.target>1.8</maven.compiler.target> <spring.version>4.0.3.RELEASE</spring.version> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.5</version> <scope>provided</scope> </dependency> <!-- <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${org.springframework.version}</version> </dependency> --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-orm</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aspects</artifactId> <version>${spring.version}</version> </dependency> <!-- Jackson核心--> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core --> <!-- 提供jackson核心支持 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.8.9</version> </dependency> <!-- Jackson注解--> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> <!-- Jackson数据绑定包使用的核心注释,用于值类型。该包提供Json注解支持 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.9.0</version> </dependency> <!--Jackson数据绑定--> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <!-- 对象序列化支持 --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.9</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring.version}</version> </dependency> <!--<dependency> <groupId>org.springframework</groupId> <artifactId>spring-instrument</artifactId> <version>${spring.version}</version> </dependency>--> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-tx</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.0.0.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context-support</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>${spring.version}</version> </dependency> <!-- c3p0新版本 --> <dependency> <groupId>com.mchange</groupId> <artifactId>c3p0</artifactId> <version>0.9.5.2</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.4.4</version> </dependency> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.45</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib</artifactId> <version>3.2.5</version> </dependency> <dependency> <groupId>cglib</groupId> <artifactId>cglib-nodep</artifactId> <version>3.2.5</version> </dependency> <!-- 日志相关依赖 --> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>1.7.10</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> <version>1.1.2</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson --> <dependency> <groupId>com.alibaba</groupId> <artifactId>fastjson</artifactId> <version>1.2.37</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb</artifactId> <version>1.9.5.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb-cross-store</artifactId> <version>1.9.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-mongodb-log4j</artifactId> <version>1.9.5.RELEASE</version> </dependency> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>3.1.0</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework.data/spring-data-redis --> <dependency> <groupId>org.springframework.data</groupId> <artifactId>spring-data-redis</artifactId> <version>2.2.0.RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.3.2</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> <!--用于文件上传--> <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileupload</artifactId> <version>1.3.1</version> </dependency> <dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency> <!--velocity 模板--> <dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity</artifactId> <version>1.7</version> </dependency> <dependency> <groupId>velocity-tools</groupId> <artifactId>velocity-tools-generic</artifactId> <version>1.4</version> </dependency> <dependency> <groupId>quartz</groupId> <artifactId>quartz</artifactId> <version>1.5.2</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-all</artifactId> <version>1.2.3</version> </dependency> </dependencies> <build> <finalName>spring-source-web</finalName> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>3.1.0</version> </plugin> <!-- see http://maven.apache.org/ref/current/maven-core/default-bindings.html#Plugin_bindings_for_war_packaging --> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>3.0.2</version> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.0</version> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.22.1</version> </plugin> <plugin> <artifactId>maven-war-plugin</artifactId> <version>3.2.2</version> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.5.2</version> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.8.2</version> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>aspectj-maven-plugin</artifactId> <version>1.3</version> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <version>2.4</version> <configuration> <forkMode>once</forkMode> <argLine> -javaagent:"${settings.localRepository}/org/springframework/spring-instrument/${spring.version}/spring-instrument-${spring.version}.jar" </argLine> </configuration> </plugin> </plugins> <defaultGoal>compile</defaultGoal> </build> </project>