spring启动componentscan类扫描加载过程

spring启动componentscan类扫描加载过程
spring启动componentscan类扫描加载过程

spring启动component-scan类扫描加载过程

有朋友最近问到了spring 加载类的过程,尤其是基于annotation 注解的加载过程,有些时候如果由于某些系统部署的问题,加载不到,很是不解!就针对这个问题,我这篇博客说说spring启动过程,用源码来说明,这部分内容也会在书中出现,只是表达方式会稍微有些区别,我将使用spring 3.0的版本来说明(虽然版本有所区别,但是变化并不是特别大),另外,这里会从WEB中使用spring开始,中途会穿插自己通过newClassPathXmlApplicationContext 的区别和联系。

要看这部分源码,其实在spring 3.0以上大家都一般会配置一个Servelet,如下所示:

view

sourceprint?1.<servlet>2.<servlet-name>spring</s ervlet-name>3.<servlet-class>org.springframework.we b.servlet.DispatcherServlet</servlet-class>4.<load-on-st artup>1</load-on-startup>5.</servlet>

当然servlet 的名字决定了,你自己获取SpringContext 的方式,在前面文章:《spring里头各种获取ApplicationContext 的方法》有详细的说明,这里就不细说了,我们就通过

DispatcherServlet来说明和跟踪(注意我们这里不说请求转发,就说bean的加载过程),我们知道servlet的规范中,如果load-on-startup被设定了,那么就会被初始化的时候装载,而servlet装载时会调用其init ()方法,那么自然是调用DispatcherServlet 的init 方法,通过源码一看,竟然没有,但是并不带表真的没有,你会发现在父类的父类中:

org.springframework.web.servlet.HttpServletBean有这个方法,如下图所示:

view sourceprint?01.public final void init() throws ServletException {02.if (logger.isDebugEnabled())

{03.logger.debug("Initializing servlet '" + getServletName() + "'");04.}05. 06.// Set bean properties from init parameters.07.try {08.PropertyValues pvs = new ServletConfigPropertyValues(getServletConfig(),

this.requiredProperties);09.BeanWrapper bw = PropertyAccessorFactory.forBeanPropertyAccess(this);10.Reso urceLoader resourceLoader = new ServletContextResourceLoader(getServletContext());11.bw.regis terCustomEditor(Resource.class, new

ResourceEditor(resourceLoader));12.initBeanWrapper(bw);13.b w.setPropertyValues(pvs, true);14.}15.catch (BeansException ex) {16.logger.error("Failed to set bean properties on servlet '" +

getServletName() + "'", ex);17.throw ex;18.}19. 20.// Let subclasses do whatever initialization they

like.21.initServletBean();22. 23.if (logger.isDebugEnabled()) {24.logger.debug("Servlet '" + getServletName() + "' configured successfully");25.}26.}

注意代码:initServletBean(); 其余的都和加载bean关系并不是特别大,跟踪进去会发I发现这个方法是在类:

org.springframework.web.servlet. FrameworkServlet类中(是DispatcherServlet 的父类、HttpServletBean 的子类),内部通过调用initWebApplicationContext ()来初始化一个WebApplicationContext ,源码片段(篇幅所限,不拷贝所有源码,仅仅截取片段)

接下来需要知道的是如何初始化这个context的(按照使用习惯,其实只要得到了ApplicationContext,就得到了bean的信息,所以在初始化ApplicationCotext的时候,就已经初始化好了bean的信息,至少至少,它初始化好了bean的路径,以及描述信息),所以我们一旦知道ApplicationCotext 是怎么初始化的,就基本知道bean 是如何加载的了。

这里的parent基本不用管,因为Root的ApplicationContext 的信息还根本没创建,所以主要是看

createWebApplicationContext这个方法,进去后,该方法前面部分,都是在设置一些相关的参数,例如我们需要将WEB 容器、以及容器的配置信息设置进去,然后会调用一个refresh() 方法,这个方法表面上是用来刷新的,其实也是用来做初始化bean用的,也就是配置修改后,如果你能调用它的这个方法,就可以重新装载spring 的信息,我们看看源码中的片段如下(同样,不相关的部分,我们就不贴太多了):

其实这个方法,不论是通过ClassPathXmlApplicationContext 还是WEB装载都会调用这里,我们看下ClassPathXmlApplicationContext 中调用的部分:

他们的区别在于,web 容器中,用servlet 装载了,servlet 中包装了一个XmlWebApplicationContext 而已,而ClassPathXmlApplicationContext 是直接调用的,他们共同点是,不论是XmlWebApplicationContext 、还是ClassPathXmlApplicationContext 都继承了类(间接继承):AbstractApplicationContext ,这个类中的refresh() 方法是共用的,也就是他们都调用的这个方法来加载bean 的,在这个方法中,通过obtainFreshBeanFactory方法来构造beanFactory 的,如下图所示:

是不是看到一层调用一层很烦人,其实回过头来想一想,它没一层都有自己的处理动作,毕竟spring不是简单的做一个bean加载,即使是这样,我们最少也需要做xml解析、类装载和实例化的过程,每个步骤可能都有很多需求,因此分离设计,使得代码更加具有扩展性,我们继续来看obtainFreshBeanFactory 方法的描述:

这里很多人可能会不太注意refreshBeanFactory ()这个方法,尤其是第一遍看这个代码的,如果你忽略掉,你可能会找不到bean在哪里加载的,前面提到了refresh 其实可以用以初始化,这里也是这样,refreshBeanFactory 如果没有初始化beanFactory 就是初始化它了,后面你看到的都是getBeanFactory 的代码,也就是已经初始化好了,这个refreshBeanFactory方法类AbstractRefreshableApplicationContext 中的方法,它是AbstractApplicationContext 的子类,同样不论是XmlWebApplicationContext、还是ClassPathXmlApplicationContext 都继承了它,因此都能调用到这个一样的初始化方法,来看看body部分的代码:

注意第一个红圈圈住的地方,是创建了一个beanFactory,然后下面的方法可以通过名称就能看出是“加载bean的定

义”,将beanFactory传入,自然要加载到beanFactory中了,createBeanFactory就是实例化一个beanFactory没别的,我们要看的是bean在哪里加载的,现在貌似还没看到重点,继续跟踪

loadBeanDefinitions (DefaultListableBeanFactory)方法

它由AbstractXmlApplicationContext 类中的方法实现,web 项目中将会由类:XmlWebApplicationContext 来实现,其实差不多,主要是看启动文件是在那里而已,如果在非web类项目中没有自定义的XmlApplicationContext,那么其实功能可以参考XmlWebApplicationContext ,可以认为是一样的功能。那么看看loadBeanDefinitions方法如下:

这里有一个XmlBeanDefineitionReader,是读取XML中spring 的相关信息(也就是解析SpringContext.xml的),这里通过getConfigLocations() 获取到的就是这个或多个文件的路径,会循环,通过XmlBeanDefineitionReader 来解析,跟踪到loadBeanDefinitions方法里面,会发现方法实现体在XmlBeanDefineitionReader的父类:AbstractBeanDefinitionReader中,代码如下:

这里大家会疑惑,为啥里面还有一个loadBeanDefinitions ,

大家要知道,我们目前只解析到我们的springContext.xml在哪里,但是还没解析到springContext.xml的内容是什么,可能有多个spring的配置文件,这里会出现多个Resource,所以是一个数组(这里如何通过location找到文件部分,在我们找class的时候自然明了,大家先不纠结这个问题)。

接下来有很多层调用,会以此调用:AbstractBeanDefinitionReader.loadBeanDefinitions(Resources []) 循环Resource数组,调用方法:XmlBeanDefinitionReader.loadBeanDefinitions(Resource ) 和上面这个类是父子关系,接下来会做:doLoadBeanDefinitions、registerBeanDefinitions 的操作,在注册beanDefinitions的时候,其实就是要真正开始解析XML 了

它调用了DefaultBeanDefinitionDocumentReader 类的registerBeanDefinitions方法,如下图所示:

中间有解析XML的过程,但是貌似我们不是很关心,我们就关系类是怎么加载的,虽然已经到XML解析部分了,所以主要看parseBeanDefinitions这个方法,里面会调用到BeanDefinitionParserDelegate类的parseCustomElement方法,用来解析bean的信息:

z

这里解析了XML的信息,跟踪进去,会发现用了NamespaceHandlerSupport 的parse方法,它会根据节点的类型,找到一种合适的解析BeanDefinitionParser(接口),他们预先被spring注册好了,放在一个HashMap中,例如我们在spring 的annotation扫描中,通常会配置:

view sourceprint?1.<context:component-scan

base-package="com.xxx" />此时根据名称

“component-scan ”就会找到对应的解析器来解析,而与之对应的就是ComponentScanBeanDefinitionParser 的parse 方法,这地方已经很明显有扫描bean的概念在里面了,这里的parse获取到后,中间有一个非常非常关键的步骤那就是定义了ClassPathBeanDefinitionScanner 来扫描类的信息,它扫描的是什么?是加载的类还是class文件呢?答案是后者,为何,因为有些类在初始化化时根本还没被加载,ClassLoader根本还没加载,只是ClassLoader可以找到这些class的路径而已:

注意这里的scanner创建后,最关键的是doScan 的功能,解析XML我想来看这个的不是问题,如果还不熟悉可以先看看,那么我们得到了类似:com.xxx 这样的信息,就要开始扫描类的列表,那么再哪里扫描呢?这里的doScan返回

了一个Set<BeanDefinitionHolder> 我们感到希望就在不远处,进去看看doScan 方法。

我们看到这么大一坨代码,其实我们目前不关心的代码,暂时可以不管,我们就看怎么扫描出来的,可以看出最关键的扫描代码是:findCandidateComponents(String basePackage) 方法,也就是通过每个basePackage 去找到有那些类是匹配的,我们这里假如配置了com.abc ,或配置了* 两种情况说明。

主要看红线部分,下面非红线部分,是已经拿到了类的定义,红线部分,会组装信息,如果我们配置了com.abc会组装为:classpath*:com/abc/**/*.class ,如果配置是* ,那么将会被组装为classpath*:*/**/*.class ,但是这个好像和我们用的东西不太一样,java中也没见这种URL可以获取到,spring到底是怎么搞的呢?就要看第二个红线部分的代码:

view sourceprint?1.Resource[] resources =

this.resourcePatternResolver.getResources(packageSearchPath);

它竟然神奇般的通过这个路径获取到了URL,你一旦跟踪你会发现,获取出来的全是.class的路径,包括jar包中的相关

class路径,这里有些细节,我们先不说,先看下这个resourcePatternResolover是什么类型的,看到定义部分是:view sourceprint?1.private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();为此胖哥还将其做了一个测试,用一个简单main方法写了一段:

view sourceprint?1.ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver();2. 3.Resource[] resources =

resourcePatternResolver.getResources("classpath*:com/abc/**/* .class");获取出来的果然是那样,胖哥开始猜测,这个和ClassLoader的getResource方法有关系了,因为太类似了,我们跟踪进去看下:

这个CLASSPATH_ALL_URL_PREFIX 就是字符串classpath*: , 我们传递参数进来的时候,自然会走第一个红圈圈住部分的代码,但是第二个红圈圈住部分的代码是干嘛的呢,胖哥告诉你先知道有这个,然后回头会有用,继续找findPathMatchingResources 方法,好了,越来越接近真相了。

这里有一个rootDirPath ,这个地方有个容易出错的,是如

果你配置的是com.abc,那么rootDirPath 部分应该是:classpath*:com/abc/ 而如果配置是* 那么classpath*: 只有这个结果,而不是classpath*:* (这里我就不说截取字符串的源码了),回到上一段代码,这里再次调用了getResources(String)方法,又回到前面一个方法,这一次,依然是以classpath*:开头,所以第一层if 语句会进去,而第二层不会,为什么?在里面的isPattern() 的实现中是这样写的:view sourceprint?1.public boolean isPattern(String path)

{2.return (path.indexOf('*') != -1 || path.indexOf('?') != -1);3.}

在匹配前,做了一个substring 的操作,会将“classpath*: ”这个字符串去掉,如果是配置的是com.abc就变成了

"com/abc/",而如果配置为*,那么得到的就是“”,也就是长度为0的字符串,因此在我们的这条路上,这个方法返回的是false,就会走到代码段findAllClassPathResources 中,这就是为什么上面提到会有用途的原因,好了,最最最最关键的地方来了哦。例如我们知道了一个com/abc/为前缀,此时要知道相关的classpath下面有哪些class是匹配的,如何做?自然用ClassLoader,我们看看Spring是不是这样做的:

果然不出所料,它也是用ClassLoader,只是它自己提供的getClassLoader()方法,也就是和spring的类使用同一个加载器范围内的,以保证可以识别到一样的classpath,自己模拟

的时候,可以用一个类

类名.class.getClassLoader().getResources("")

如果放为空,那么就是获取classpath的相关的根路径(classpath可能有很多,但是根路径,可以被合并),也就是如果你配置的*,获取到的将是这个,也许你在web项目中,你会获取到项目的根路径(classes下面,以及tomcat的lib 目录)。

如果写入一个:com/abc/ 那么得到的将是扫描相关classpath 下面所有的class和jar包中与之匹配的类名(前缀部分)的路径信息,但是需要注意的是,如果有两层jar包,而你想要扫描的类或者说想要通过spring加载的类在第二层jar 包中,这个方法是获取不到的,这不是spring没有去做这个事情,而是,java提供的getResources方法就是这样的,有朋友问我的时候,正好遇到了类似的事情,另外需要注意的是,getResources 这个方法是包含当前路径的一个递归文件查找(一般环境变量中都会配置. ),所以如果是一个jar 包,你要运行的话,切记放在某个根目录来跑,因为当前目录,就是根目录也会被递归下去,你的程序会被莫名奇怪地慢。

这里大家还可以通过以下简单的方式来测试调用路径的问题:

view

sourceprint?1.ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(true);2.Set< ;BeanDefinition> beanDefinitions =

provider.findCandidateComponents("com/abc");3.for(BeanDefi nition beanDefinition : beanDefinitions)

{4.System.out.println(beanDefinition.getBeanClassName() 5.+ " " + beanDefinition.getResourceDescription()6.+ " " + beanDefinition.getClass());7.}这是直接引用spring的源码部分的内容,如果这里可以获取到,且路径是正确的,一般情况下,都是可以加载到类的。

看了这么多,是不是有点晕,没关系,谁第一回看都这样,当你下一次看的时候,有个思路就好了,我这里并没有像UML一样理出他们的层次关系,和调用关系,仅仅针对代码调用逐层来说明,大家如果初步看就是,由Servlet初始化来创建ApplicationContext,在设置了Servelt相关参数后,获取servlet的配置文件路径或自己指定的配置文件路径(applicationContext.xml或其他的名字,可以一个或多个),然后通过系列的XML解析,以及针对每种不同的节点类型使用不同的加载方式,其中component-scan 用于指定扫描类的对应有一个Scanner,它会通过ClassLoader的getResources方法来获取到class的路径信息,那么class的

路径都能获取到,类的什么还拿不到呢?呵呵!

好,本文基本内容就说到这里,接下来我会提到spring MVC 的中的简单跳转的解析,其中有部分源码是这里看过的,只是还不是这里的重点而已。

而我想说的也是这点,其实本文虽然在说启动,其实有很多代码也没说,因为那样的话我就是一个复制咱贴机了;

其实看源码,要带着目的,大家要知道主体情况或实现的功能,不要就看源码而看源码,一个是根本记不下来,另一个这样看代码没有太大的意义。

当你有了疑问,遇到了难题不知道原因,或发现了新大陆,很有兴趣,那么去看看,也许看之前你会思考下如果我来实现会怎么做?再看看别人是怎么做的,有何区别,不断吸取这些开源框架中优秀的品质,包括代码的设计层次,了解它用到了什么,为何要这样设计,那么你的代码相信会越来越漂亮,你对开源界的代码也会越来越熟悉,熟悉得像自己亲人一样,呵呵。

SpringMVC配置的基本步骤

Springmvc框架配置步骤 小弟是个新手,有不对的地方请tell me,一起研究探讨。谢谢。 1062140832@https://www.360docs.net/doc/b017964301.html, 配置springmvc框架其实不是很难,要现有一个总体的认识,确定要分几步,每一步主要是干什么,不要太盲目。 以为web.xml是项目的入口,所以所有的配置文件,都必须引入到wem.xml中,不然,配置了等于没用。所以,要先从入口入手。 配置web.xml 1、首先引入springmvc-servlet.xml文件 springMVC org.springframework.web.servlet.DispatcherServlet contextConfigLocation /WEB-INF/spring/mvc/springmvc-servlet.xml 1 2、将spring加载到web.xml中 org.springframework.web.context.ContextLoaderListener 3、配置上下文路径 contextConfigLocation /WEB-INF/spring/spring.xml,/WEB-INF/spring/spring-*.xml 说明:如果有很多的关于spring的配置文件,建议分开写,比如事务一个文件(spring-transaction.xml),springmvc-hibernate.xml一个配置文件,这样方便读写。

事务策略

2009 年 7 月 14 日 混淆事务模型与事务策略是一个常见的错误。本系列关于 事务策略 的第二篇文章将概述 Java? 平台支持的三种事务模型,并介绍使用这些模型的四种主要事务策略。通过使用 Spring Framework 和 Enterprise JavaBeans (EJB) 3.0 规范中的示例,Mark Richards 将解释事务模型的运行原理以及它们如何形成开发各种事务策略(从基本的事务处理到高速事务处理系统)的基础。 开发人员、设计人员和架构师经常会混淆事务模型 与事务策略。我经常会让与客户接触的架构师和技术总监描述他们项目的事务策略。我通常会获得三种回应。有时,他们会说 “我们实际上并未在应用程序中使用事务。”另一些时候,我会听到迷惑的回答:“我不明白你的意思。”但是,我也会遇到非常自信的回答:“我们使用声明式事务。”在本文中,术语声明式事务 描述的是一个事务模型,但它绝不是一种事务策略。 Java 平台支持的三种事务模型包括: ? Local Transaction 模型 ? Programmatic Transaction 模型 ? Declarative Transaction 模型 这些模型描述事务在 Java 平台中的基本运行方式,以及它们是如何实现的。但是,它们仅提供了事务处理的规则和语义。如何应用事务模型则完全由您决定。举例来说,应该如何在 REQUIRED 和 MANDATORY 事务属性之间做出选择?您应该在何时何种情况下指定事务回滚指令?您应该在何时考虑 Programmatic Transaction 模型与 Declarative Transaction 模型的优劣?您应该如何优化高性能系统的事务?事务模型本身无法回答这些问题。您必须通过开发自己的事务策略或采用本文介绍的四种主要事务策略之一来解决它们。 如本系列的 第一篇文章 所述,许多常见的事务陷阱都会影响到事务行为,并且由此会降低数据的完整性和一致性。同样,缺乏有效的(或任何)事务策略将对您数据的完整性和一致性造成负面影响。本文所描述的事务模型是开发有效事务策略的基本元素。理解这些模型之间的差异以及它们的运行方式对于理解使用它们的事务策略非常重要。在介绍完三种事务模型之后,我将讨论适用于大多数业务应用程序(从简单的 Web 应用程序到大型的高速事务处理系统)的四种事务策略。 事务策略 系列的后续文章将详细讨论这些策略。 Local Transaction 模型 在 Local Transaction 模型中,事务由底层数据库资源管理程序(而非应用程序所在的容器或框架)管理,这便是它得名的原因。在这个模型中,您将管理连接,而不是事务。从 “了解事务陷阱” 一文可知,在使用对象关系映射框架,如 Hibernate 、TopLink 或 the Java Persistence API (JPA),执行数据库更新时,您不能使用 Local Transaction 模型。在使用数据访问对象(DAO )或基于 JDBC 的框架和数据库存储过程时,您可以使用它。 您可以采用以下两种方式来使用 Local Transaction 模型:让数据库来管理连接,或者以编程的方式管理连接。要让数据库管理连接,您需要将 JDBC Connection 对象上的 autoCommit 属性设置为 true (默认值),这将通知底层数据库管理系统(DBMS )在完成插入、更新或删除操作之后提交事务,或者在操作失败时返回任务。清单 1 展示了这种技巧,它在 TRADE 表中插入了一条股票交易命令: 清单 1. 包括一个更新的本地事务

spring配置文件各个属性详解

spring配置文件各个属性详解 分类:spring 2012-08-09 11:25 9316人阅读评论(2) 收藏举报springaophibernateattributesxhtmlwebsphere 目录(?)[+]一、引用外部属性文件 classpath:mail.properties classpath:jdbc.properties 我们定义了一个PropertyPlaceholderConfigurer类的实例,并将其位置属性设置为我们的属性文件。该类被实现为Bean工厂的后处理器,并将使用定义在文件中的属性来代替所有的占位符(${...}value)。 注意: 而在spring2.5的版本中提供了一种更简便的方式,如: 1. 这样以后要使用属性文件中的资源时,可以使用${属性名}来获得。 二、常用数据源的配置 第一种是:DBCP数据源,(需要加入2个jar文件,在spring中的lib下 jakarta-commons/commons-dbcp.jar和commons-pools.jar)主要配置如下:

spring6种配置datasource的方法

在Spring3中,配置DataSource的方法有6种。 JDBCSpringXMLMicrosoftHTML 在Spring3中,配置DataSource的方法有五种。 第一种:beans.xml Xml代码 1. 3. 4. 6. 7. 8. 第二种:beans.xml 2. 3. 4. 6. 7. 8. 9. 10. 在src文件夹里新建一个jdbc.properties文件,里面的内容为如下: Xml代码 1.jdbc.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriv er

spring框架

spring框架 Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。 控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。 面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务(transaction)管理)进行内聚性的开发。应用对象只实现它们应

该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。 容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB 容器,它们经常是庞大与笨重的,难以使用。 框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将应用逻辑的开发留给了你。 所有Spring的这些特征使你能够编写更干净、更可管理、并且更易于测试的代码。它们也为Spring中的各种模块提供了基础支持。

springMVC详解以及注解说明

springMVC详解以及注解说明 基于注释(Annotation)的配置有越来越流行的趋势,Spring 2.5 顺应这种趋势,提供了完全基于注释配置Bean、装配Bean 的功能,您可以使用基于注释的Spring IoC 替换原来基于XML 的配置。本文通过实例详细讲述了Spring 2.5 基于注释IoC 功能的使用。 概述 注释配置相对于XML 配置具有很多的优势: ? 它可以充分利用Java 的反射机制获取类结构信息,这些信息可以有效减少配置的工作。如使用JPA 注释配置ORM 映射时,我们就不需要指定PO 的属性名、类型等信息,如果关系表字段和PO 属性名、类型都一致,您甚至无需编写任务属性映射信息——因为这些信息都可以通过Java 反射机制获取。 ? 注释和Java 代码位于一个文件中,而XML 配置采用独立的配置文件,大多数配置信息在程序开发完成后都不会调整,如果配置信息和Java 代码放在一起,有助于增强程序的内聚性。而采用独立的XML 配置文件,程序员在编写一个功能时,往往需要在程序文件和配置文件中不停切换,这种思维上的不连贯会降低开发效率。 因此在很多情况下,注释配置比XML 配置更受欢迎,注释配置有进一步流行的趋势。Spring 2.5 的一大增强就是引入了很多注释类,现在您已经可以使用注释配置完成大部分XML 配置的功能。在这篇文章里,我们将向您讲述使用注释进行Bean 定义和依赖注入的内容。 Spring2.5的注释 Spring 2.5 提供了AutowiredAnnotationBeanPostProcessor、CommonAnnotationBeanPostProcessor、PersistenceAnnotationBeanPostProcessor 和RequiredAnnotationBeanPostProcessor这四个主要的关于Annotation 的BeanPostProcessor。 我们可以使用 来方便地、一次性的声明者四个BeanPostProcessor。 1.Autowired... 提供对Spring 特有的Autowired 和Qualifier 注释。

一个非常有趣的使用spring框架AOP例子

一个非常有趣的使用spring框架AOP例子 接触spring有一段时间了,不过都是看的多,写的少,工作忙,公司也不准备用。自己写过一些小东西用到,也只用到了BeanFactory组装对象,JdbcTemplate代替jdbc,事务管理。。。东抓一把,西抓一把,没形成系统。最近也在看spring自带的reference,一时手痒,写了个AOP的创建advice的例子,比之单纯地使用TransationProxyFactoryBean 对AOP的理解又深入了点,打算看看它的源代码,基于CGLIB的实现对类的代理不了解,倒是好奇它如何实现对接口的代理??也就是利用J2SE的动态代理技术。 例子如下:讲述一间书店开始打折促销,规则是每一名顾客只能买一本书,而且已经脱销了。。。。。你可以去掉TestAdvice里的注释看看各种运行结果,具体就不解释咯,在代码注释里。 首先,你必须对增强(advice)有所了解,增强就是在特定连接点执行的动作。advice contains the logic of your aspect。增强,分为4类: 前增强(before)在连接点之前调用 后增强(after)在连接点执行之后调用、 环绕增强(around)完整控制整个方法流程,必须调用MethodInvocation的proceed促使真实操作发生 异常增强针对某个异常抛出时调用 书店,一个buyBook业务: package com.denny_blue.springdemo.aop; public interface BuyBook { public void buyBook(String customer,String book)throws NoThisBookException; } 实现此接口的一个业务对象,如果顾客要买就抛出NoThisBookException异常。 package com.denny_blue.springdemo.aop; public class MyBuyBook implements BuyBook { public void buyBook(String customer,String book)throws NoThisBookException{ if(book.equals("")) throw new NoThisBookException("对不起,没有"+book+"存货了!"); System.out.println(customer+",你好,你已经购买了一本"+book+"!"); } }

多图详解Spring框架的设计理念与设计模式

Spring作为现在最优秀的框架之一,已被广泛的使用,51CTO也曾经针对Spring框架中的JDBC应用做过报道。本文将从另外一个视角试图剖析出Spring框架的作者设计Spring框架的骨骼架构的设计理念。 Rod Johson在2002年编著的《Expert one to one J2EE design and development》一书中,对Java EE正统框架臃肿、低效、脱离现实的种种现状提出了质疑,并积极寻求探索革新之道。以此书为指导思想,他编写了interface21框架,这是一个力图冲破Java EE传统开发的困境,从实际需求出发,着眼于轻便、灵巧,易于开发、测试和部署的轻量级开发框架。Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日,发布了1.0正式版。同年他又推出了一部堪称经典的力作《Expert one-to-one J2EE Development without EJB》,该书在Java世界掀起了轩然大波,不断改变着Java开发者程序设计和开发的思考方式。在该书中,作者根据自己多年丰富的实践经验,对EJB 的各种笨重臃肿的结构进行了逐一的分析和否定,并分别以简洁实用的方式替换之。至此一战功成,Rod Johnson 成为一个改变Java世界的大师级人物。 传统J2EE应用的开发效率低,应用服务器厂商对各种技术的支持并没有真正统一,导致J2EE的应用没有真正实现Write Once及Run Anywhere的承诺。Spring作为开源的中间件,独立于各种应用服务器,甚至无须应用服务器的支持,也能提供应用服务器的功能,如声明式事务等。 Spring致力于J2EE应用的各层的解决方案,而不是仅仅专注于某一层的方案。可以说Spring是企业应用开发的“一站式”选择,并贯穿表现层、业务层及持久层。然而,Spring并不想取代那些已有的框架,而与它们无缝地整合。 Spring简介 Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring 使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 ◆目的:解决企业应用开发的复杂性 ◆功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能 ◆范围:任何Java应用 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 ◆轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且 Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。 ◆控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。 ◆面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务()管理)进行内聚性的开发。应用对象只实现它们应该做的——完成业务逻辑——仅此而已。它们并不负责(甚至是意识)其它的系统级关注点,例如日志或事务支持。 ◆容器——Spring包含并管理应用对象的配置和生命周期,在这个意义上它是一种容器,你可以配置你的每个bean如何被创建——基于一个可配置原型(prototype),你的bean可以创建一个单独的实例或者每次需要时都生成一个新的实例——以及它们是如何相互关联的。然而,Spring不应该被混同于传统的重量级的EJB容器,它们经常是庞大与笨重的,难以使用。 ◆框架——Spring可以将简单的组件配置、组合成为复杂的应用。在Spring中,应用对象被声明式地组合,典型地是在一个XML文件里。Spring也提供了很多基础功能(事务管理、持久化框架集成等等),将

spring使用基于注解的AOP事务管理

spring使用基于注解的AOP事务管理 16.6 AOP事务管理 AOP事务管理利用了Spring AOP的基础设施,在大多数情况下,Spring AOP会创建一个JDK代理以拦截方法调用。你可以使用装载时编织以在装载期编织切面,这样就不需要代理了(如果你记不清什么是装载时编织,请参看第6章)。你有两种方式来配置Spring AOP 事务管理,基于注解的配置以及XML配置。 16.6.1 使用基于注解的AOP事务管理 你可以借助于AOP的自动代理,通过注解将事务性行为引入到现有的bean中。让我们以代码清单16-21开始吧,它展示了类DeclarativeTxBankService。 代码清单16-21 DeclarativeTxBankService实现 请注意@Transactional属性,为了让Spring的事务管理基础设施可以利用该属性创建恰当的切入点和通知,我们需要使用AOP的自动代理和注解驱动的事务支持。代码清单16-22展示了与该注解相对应的XML配置。 代码清单16-22 基于注解的事务管理的配置文件

该XML配置文件展示了标准的bankService bean声明,紧跟其后的是 标签。 标签使用@Transactional注解创建恰当的事务管理切面。接下来由通知匹配的bean。 1.探索tx:annotation-driven标签 标签是注解驱动的事务管理支持的核心。表16-3列出了 标签的所有属性。 表16-3 标签的属性 属性说明 transactionManager 指定到现有的PlatformTransaction Manager bean的引用,通知会使用该引用 mode 指定Spring事务管理框架创建通知bean的方式。 可用的值有proxy和aspectj。前者是默认值, 表示通知对象是个JDK代理;后者表示 Spring AOP会使用AspectJ创建代理 order 指定创建的切面的顺序。只要目标对象有多个通知就可以使用该属性 proxy-target-class 该属性如果为true就表示你想要代理目标类而不是bean所实现的所有接口

spring在web.xml中的配置

把如下代码添加到web.xml即可完成spring的基本配置 SetCharacterEncoding org.springframework.web.filter.CharacterEncodingFilter encoding UTF-8 forceEncoding true SetCharacterEncoding /* contextConfigLocation /WEB-INF/applicationContext.xml, /WEB-INF/action-servlet.xml org.springframework.web.context.ContextLoaderListener

Spring Bean 配置说明

Spring配置文件的根元素,包含一个或多个bean元素。 default-autowire属性:默认的bean自动装配模式。可选5种模式。 no:不使用自动装配。Bean的引用必须通过ref元素定义。 byName:通过属性名字进行自动装配。 byType:如果BeanFactory中正好有一个同属性类型一样的bean,就自动装配这个属性。如果有多于一个这样的bean,就抛出一个致命异常,它指出你可能不能对那个bean使用byType 的自动装配。如果没有匹配的bean,则什么都不会发生,属性不会被设置。如果这是你不想要的情况(什么都不发生),通过设置dependency-check="objects"属性值来指定在这种情况下应该抛出错误。 constructor:这个同byType类似,不过是应用于构造函数的参数。如果在BeanFactory中不是恰好有一个bean与构造函数参数相同类型,则一个致命的错误会产生。 autodetect:通过对bean 检查类的内部来选择constructor或byType。如果找到一个缺省的构造函数,那么就会应用byType。 default-dependency-check属性:默认的依赖检查模式。可选四种。 none :不进行依赖检查。没有指定值的bean属性仅仅是没有设值。 Simple:对基本类型和集合(除了合作者外,比如其他的bean,所有东西)进行依赖检查。Object:对合作者进行依赖检查。 all :对合作者,基本类型和集合都进行依赖检查。 default-lazy-init属性:默认延迟加载。True 或False 。 用于告诉Spring容器一个类以及它是如何配置的。 class属性:Java Bean 类名。 id属性:Java Bean在BeanFactory中的唯一标识,代码中通过BeanFactory获取JavaBean 实例时需以此作为索引名称。 name属性:同上,如果给bean增加别名,可以通过name属性指定一个或多个id。singleton属性:指定此Java Bean是否采用单例(Singleton)模式,如果设为“true”,则在BeanFactory作用范围内,只维护此Java Bean的一个实例,代码通过BeanFactory获得此Java Bean实例的引用。反之,如果设为“false”,则通过BeanFactory获取此Java Bean实例时,BeanFactory每次都将创建一个新的实例返回。 abstract属性:设定ApplicationContext是否对bean进行预先的初始化。 parent属性:定义一个模板。 autowire属性:bean自动装配模式。可选5种模式。 no:不使用自动装配。Bean的引用必须通过ref元素定义。 byName:通过属性名字进行自动装配。 byType:如果BeanFactory中正好有一个同属性类型一样的bean,就自动装配这个属性。如果有多于一个这样的bean,就抛出一个致命异常,它指出你可能不能对那个bean使用byType 的自动装配。如果没有匹配的bean,则什么都不会发生,属性不会被设置。如果这是你不

Spring分布式事务实现

Spring分布式事务实现 分布式事务是指操作多个数据库之间的事务,spring的org.springframework.transaction.jta.JtaTransactionManager,提供了分布式事务支持。如果使用WAS的JTA支持,把它的属性改为WebSphere对应的TransactionManager。 在tomcat下,是没有分布式事务的,不过可以借助于第三方软件jotm(Java Open Transaction Manager )和AtomikosTransactionsEssentials实现,在spring中分布式事务是通过jta(jotm,atomikos)来进行实现。 1、https://www.360docs.net/doc/b017964301.html,/ 2、https://www.360docs.net/doc/b017964301.html,/Main/TransactionsEssentials 一、使用JOTM例子 (1) Dao及实现 GenericDao接口: ? 1 2 3 4 public interface GenericDao { public int save(String ds, String sql, Object[] obj) throws Exception; public intfindRowCount(String ds, String sql); } GenericDaoImpl实现:? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 public class GenericDaoImpl implements GenericDao{ private JdbcTemplatejdbcTemplateA; private JdbcTemplatejdbcTemplateB; public void setJdbcTemplateA(JdbcTemplatejdbcTemplate) { this.jdbcTemplateA = jdbcTemplate; } public void setJdbcTemplateB(JdbcTemplatejdbcTemplate) { this.jdbcTemplateB = jdbcTemplate; } public int save(String ds, String sql, Object[] obj) throws Exception{ if(null == ds || "".equals(ds)) return -1; try{ if(ds.equals("A")){ return this.jdbcTemplateA.update(sql, obj); }else{ return this.jdbcTemplateB.update(sql, obj); } }catch(Exception e){ e.printStackTrace(); throw new Exception("执行" + ds + "数据库时失败!"); } } public intfindRowCount(String ds, String sql) {

spring配置

作者简介: Craig Walls是Texas-based公司的软件开发人员,有着超过13年的开发经验,涉及的领域有通信,金融,零售,教育以及软件业等。他是Spring Framework的狂热拥护者,频繁的在当地local user groups讨论组和相关会议上演讲Spring,并且他的Blog上也有很多关于Spring的内容。出版的著作有: z Spring in Action, 2nd Edition, 2007 z XDoclet in Action, 2003 他的Blog是: z https://www.360docs.net/doc/b017964301.html, 所参与的项目: z Committer to XDoclet project; z Originator of Portlet and Spring modules for XDoclet 本手册主要是将分布于文档中的那些零散的配置文件部分统一成一个比较系统的整体。结合Spring文档一起查阅也许能节省你一些时间。不过,并不推荐你全部掌握;很多陌生的元素或标签只应用于特定场合。本手册英文版本可以在:https://www.360docs.net/doc/b017964301.html,下载。 Spring配置全书 作者Craig Walls 译者superleo 关于Spring的配置 Spring Framework总是不断的改变着Java企业开发的方向,它用一种松耦合的方式来配置和组装应用程序对象和业务对象,比以往的Java企业开发来的更加简洁。一旦你开发了基于Spring 的应用程序,在Spring上下文配置的那些资源简直就是唾手可得。 依赖注入是Spring容器的核心 尽管Spring Framework可以做很多事,但依赖注入却是Spring容器提供的最基本的功能。 任何稍微复杂一点的应用程序都至少由两个或两个以上的对象协作在一起,共同完成一些业务逻辑。以往的Java企业开发,每个对象都要自己去主动获得他们所引用(或依赖)的对象,才可正常运作。这将导致代码之间的紧耦合,难以测试。

Spring中文开发详细手册

Spring开发教程 Spring教程 (1) Spring框架概述 (2) Spring是什么? (2) Spring的历史 (3) Spring的使命(Mission Statement) (3) Spring受到的批判 (3) Spring包含的模块 (4) 总结 (5) Spring的IoC容器 (6) 用户注册的例子 (6) 面向接口编程 (7) (用户持久化类)重构第一步——面向接口编程 (8) 重构第二步——工厂(Factory)模式 (9) 重构第三步——工厂(Factory)模式的改进 (9) 重构第四步-IoC容器 (10) 控制反转(IoC)/依赖注入(DI) (10) 什么是控制反转/依赖注入? (10) 依赖注入的三种实现形式 (11) BeanFactory (13) BeanFactory管理Bean(组件)的生命周期 (14) Bean的定义 (15) Bean的之前初始化 (19) Bean的准备就绪(Ready)状态 (21) Bean的销毁 (21) ApplicationContext (21) Spring的AOP框架 (21) Spring的数据层访问 (21) Spring的声明式事务 (21) Spring对其它企业应用支持 (22)

名词解释 容器: 框架: 框架 容器 组件: 服务: Spring框架概述 主要内容:介绍Spring的历史,Spring的概论和它的体系结构,重点阐述它在J2EE中扮演的角色。 目的:让学员全面的了解Spring框架,知道Spring框架所提供的功能,并能将Spring 框架和其它框架(WebWork/Struts、hibernate)区分开来。 Spring是什么? Spring是一个开源框架,它由Rod Johnson创建。它是为了解决企业应用开发的复杂性而创建的。Spring使用基本的JavaBean来完成以前只可能由EJB完成的事情。然而,Spring 的用途不仅限于服务器端的开发。从简单性、可测试性和松耦合的角度而言,任何Java应用都可以从Spring中受益。 ?目的:解决企业应用开发的复杂性 ?功能:使用基本的JavaBean代替EJB,并提供了更多的企业应用功能 ?范围:任何Java应用 简单来说,Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架。 ■轻量——从大小与开销两方面而言Spring都是轻量的。完整的Spring框架可以在一个大小只有1MB多的JAR文件里发布。并且Spring所需的处理开销也是微不足道的。此外,Spring是非侵入式的:典型地,Spring应用中的对象不依赖于Spring的特定类。 ■控制反转——Spring通过一种称作控制反转(IoC)的技术促进了松耦合。当应用了IoC,一个对象依赖的其它对象会通过被动的方式传递进来,而不是这个对象自己创建或者查找依赖对象。你可以认为IoC与JNDI相反——不是对象从容器中查找依赖,而是容器在对象初始化时不等对象请求就主动将依赖传递给它。 ■面向切面——Spring提供了面向切面编程的丰富支持,允许通过分离应用的业务逻辑与系统级服务(例如审计(auditing)和事务()管理)进行内聚性的开发。应用对象只实

spring MVC配置详解

牧涛 --<-<-<@态度决定一切→_→。。。 ?博客园 ?首页 ?新闻 ?新随笔 ?联系 ?管理 ?订阅 随笔- 171 文章- 3 评论- 79 spring MVC配置详解 现在主流的Web MVC框架除了Struts这个主力外,其次就是Spring MVC了,因此这也是作为一名程序员需要掌握的主流框架,框架选择多了,应对多变的需求和业务时,可实行的方案自然就多了。不过要想灵活运用Spring MVC来应对大多数的Web开发,就必须要掌握它的配置及原理。 一、Spring MVC环境搭建:(Spring 2.5.6 + Hibernate 3.2.0) 1. jar包引入 Spring 2.5.6:spring.jar、spring-webmvc.jar、commons-logging.jar、cglib -nodep-2.1_3.jar Hibernate 3.6.8:hibernate3.jar、hibernate-jpa-2.0-api-1.0.1.Final.jar、a ntlr-2.7.6.jar、commons-collections-3.1、dom4j-1.6.1.jar、javassist-3.12.0.G A.jar、jta-1.1.jar、slf4j-api-1.6.1.jar、slf4j-nop-1.6.4.jar、相应数据库的驱动jar 包 SpringMVC是一个基于DispatcherServlet(分发器)的MVC框架,每一个请求最先访问的都是DispatcherServlet,DispatcherServlet负责转发每一个Request请求给相应的Handler,Handler处理以后再返回相应的视图(View)和模型(Model),返回的视图和模型都可以不指定,即可以只返回Model或只返回View或都不返回。 DispatcherServlet是继承自HttpServlet的,既然SpringMVC是基于DispatcherSe rvlet的,那么我们先来配置一下DispatcherServlet,好让它能够管理我们希望它管理的内容。HttpServlet是在web.xml文件中声明的。 spring org.springframework.web.servlet.DispatcherServlet< /servlet-class>