首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

《partner4java 叙说Spring入门》之第一步:Spring概述与Spring IoC

2012-11-22 
《partner4java 讲述Spring入门》之第一步:Spring概述与Spring IoC(导读:希望在阅读的过程中,伴随着动手 --

《partner4java 讲述Spring入门》之第一步:Spring概述与Spring IoC

(导读:希望在阅读的过程中,伴随着动手 -- 把讲述的每一步Demo都自己书写一遍,若遇到问题一时解决不了,可发邮件给我:partner4java@163.com;demo下载地址--http://download.csdn.net/detail/partner4java/4779657 ;也可以结合视频:http://pan.baidu.com/share/link?shareid=122408&uk=4096755201 ,视频说实话应该不咋地,是第一次录制,不存在各种讲课技巧 )

第一步:扯蛋

?很多人可能接触了Spring MVC、SpringSecurity啥的,感觉Spring好混乱,亲,这都是单独项目(Spring被VMware收购之后很疯狂,开辟了大量项目)?Spring就是个IoC容器,然后实现了一部分aopalliance、AspectJ的规范(自己也定义一些AOP相关的接口)?至于牛人说的轻量级,只是Spring不需要借助EE容器,而EJB干的活Spring干起来也费劲

下面紧跟的很长一段,会讲一些“大道理”,就当天书看一眼吧
begin….


Spring的设计目标 :

?在Java EE的应用开发中,支持POJO和使用JavaBean的开发方式,使应用面向接口开发,充分支持OO(面向对象)的设计方法。?轻量级,无需像EJB依赖J2EE应用服务器。 ?把依赖关系的管理从Java对象中解放出来,交给IoC容器通过IoC容器实现的依赖反转。 ?一方面,他通过IoC容器来管理POJO对象,以及他们相互之间的耦合关系,使企业的信息资源可以以简单的Java语言来抽象和描述;另一方面,可以通过AOP,以动态和非侵入式的方式来增强服务的功能。 ?Spring的设计理念--面向接口开发而不依赖于具体的产品实现。?实现AOP多种方式,比如他集成了AspectJ框架,同时也有ProxyFactory代理工厂的模式,而在代理工厂的实现中,既有直接使用JVM动态代理Proxy实现,也有使用第三方代理类库的CGLIB的实现。《partner4java 叙说Spring入门》之第一步:Spring概述与Spring IoC

Spring架构图:

?Spring IoC:包含了最基本的IoC容器BeanFactory的接口和实现,还提供了一些列这个接口的实现。?Spring AOP:围绕着AOP增强功能,Spring继承了AspectJ作为AOP的一个特定实现,同时还在JVM动态代理/CGLIB的基础上,实现一个AOP框架,作为Spring继承其他模块的工具。在这个模块中,Spring AOP实现了一个完整的建立AOP代理对象,实现AOP拦截,直至实现各种Advice通知的过程。 ?SpringMVC:这个模块以DispatcherServlet为核心,实现了MVC模式,包括怎样与Web容器环境的继承,Web请求的拦击、分发、处理和ModelAndView数据的返回,以及如何集成各种UI视图展示和数据表现。 ?SpringJDBC/Spring ORM:对JDBC进行封装,提供了RDBMS的操作对象。同时对现有的ORM框架进行template等封装提供。 ?Spring的事务处理:Spring事务处理是通过Spring AOP实现自身功能增强的典型模块。在这个模块中,Spring把企业开发中事务处理的主要过程抽象出来,并且简单的通过AOP的切面增强实现了声明式事务的处理。 ?Spring应用:严格来说不属于Spring的范围。丰富了整个Spring生态圈,使Spring应用越来越广泛。 ?Spring远端调用:spring为应用屏蔽了各种通讯和调用细节的实现。可以使用HTTP调用器(以HTTP协议为基础),可以使用第三方的二进制通讯实现Hessian/Burlap,甚至还封装了传统Java技术中的RMI调用。 


end
天书告一段落


现在Spring不都分包了么?
大体看下包的作用

?spring-aop.jar:此JAR文件包含了所有你在应用中使用Spring AOP特性时需要的类。如果应用中使用了其他涉及AOP的Spring功能时,例如声明式事务管理,你也需要将此JAR文件包含进来。 ?spring-beans.jar:此文件包含了所有Spring依赖注入需要的代码。包括Bean工厂和相关支持类。 ?spring-context.jar: 大部分情况下,你会需要加入spring-context.jar文件,他包含了建立应用环境上下文需要的代码。此JAR包含了建立Spring应用环境上下文所需要的代码,他将主要的ApplicationContext接口和实现、说明、JNDI、调度、主题和验证一起纳入其中。?spring-context-support.jar:这个包文件包含了Spring的工具代码,其中包括缓存、说明、电子邮件、调度支持一级一个有趣的脚本语言支持。 ?spring-core.jar: 此文件包含了Spring框架的核心代码。它用来处理注解、枚举、任务执行、资源加载一级其它一些即便在Spring框架环境外也会有用的工具和异常类。?spring-jdbc.jar:此文件包含了JDBC支持类的代码,例如JdbcTemplate类和JdbcDaoSupport类。 spring-jms.jar: 此文件包含JMC的代码。

?spring-orm.jar: 此文件包含了对象-关系映射(ORM)工具需要的文件。把这个包加入到classpath上会提供对Hibernate3、iBATIS、JDO、JPA和TopLink的Spring支持?spring-test.jar: 此文件包含了使用Spring框架编写单元测试和继承测试的支持代码。他支持JUnit3、JUnit4和TestNG测试框架。另外,你也可以使用org.springframe-work.mock包中的类,他代表了JNDI类和Web相关类的模拟实现。?spring-tx.jar:此文件提供了核心的数据访问异常和事务技术支持。这两个概念彼此关系密切,因为一般情况下事务的同某些数据访问代码一起工作的。?spring-web.jar:此文件包含了Spring Web应用支持(工具类、绑定器、分段文件解析器)的代码。?spring-webmvc.jar:此文件 包含了Spring MVC代码。?spring-webmvc-portlet.jar:此文件包含创建基于porlet(而不是servlet)Web应用所需要的代码。?spring-webmvc-struts.jar:此文件包含了在Spring中使用Jakarta Struts框架所需的代码。 

哥,我走了,别说了,吓到我了,东西太多了
亲,别怕,其实Spring就那十个左右的注解就完事了
牛B的框架不会太难用,牛B的代码不会太难懂。我们要跻身于那批能写牛B的代码人群中。。。


第二步,简易IoC:


控制反转IoC  

begin:


控制反转和依赖注入:

?控制反转(IoC)。依赖注入(DI)。 ?实际上依赖注入是控制反转的一种特殊形式。 ?控制反转和依赖注入的核心目标是提供一个更为简单的机制去规定和组件之间的依赖关系(他通常被称作为对象的协助者),并在他们的生命周期中管理这些依赖。?一个需要某些特定依赖的组件通常被称为依赖对象或者目标。控制反转提供的服务使一个组件能够在他的生命周期中访问他的依赖和服务,使用这个这种方法与他的依赖进行交互,这是一件非常美妙的事情。?大体来说,控制反转可以分为两个子类型:依赖注入和依赖查找。这些字类型又能划分成控制反转服务的若干具体实现。以此定义我们可以清楚的知道,当我们谈论依赖注入时我们总是在谈论控制反转,反之则不然。


不依赖Spring,我们先简单的实现下控制反转:

?Helloworld背景:?我们要实现一个男人和多个女人,男人对女人有管理权限,但是这个男人还想能够随意的更换女人(当然所有男人都想,除非你懂得)。?问题:?当这个男人出生的时候(instance)的时候并不知道未来会是什么样的女人可以交予他管理

上下文依赖查找(CDL):

?在某些方面跟依赖拖拽相似,但是上下文依赖查找中,查找的过程是在容器管理的资源中进行的,而不是从集中注册表中,并且通常是作用在某些设置点上。《partner4java 叙说Spring入门》之第一步:Spring概述与Spring IoC


依赖注入方式:

?构造方法依赖注入:

在构造方法依赖注入中,组件的依赖从他们的构造方法中提供。组件声明一个或一组构造方法,将他们的依赖作为参数,控制反转容器就会降依赖在组件实例化时传给他。

?设置方法依赖注入:

在设置方法依赖注入中,控制反转容器通过JavaBean风格的设置方法为组件注入依赖。一个组件的设置方法向反转容器公开一组依赖。


XmlBeanFactory:

?XmlBeanFactory源于DefaultListableBeanFactory且简单的扩展了他,利用XmlBeanDefinitionReader进行自动配置?现在这个类已经@Deprecated了?代码写法和前面基本一样,只是配置格式有很多需要学习的

我们前面利用Properties形式的配置改成XML格式:

在类路径下创建文件:

/META-INF/spring/helloworld.xml

1、交给spring管理的基本单位<bean>;

2、一般需要一个标识id属性来进行区分;

3、然后class指定<bean>标签要交给Spring管理哪个类;

4、当你要利用依赖注入来实现某属性的赋值,可利用<property>标签;

5、<property>标签的name属性为对应调用的POJO的set方法,ref为一个bean的id(也就是传入的赋值类 -- 此类也是Spring管理的)。


为集合元素指定数据类型 :

?问题:
默认情况下,Spring将集合中所有元素作为字符串对待。
如果你不打算将集合元素作为字符串使用,就必须为他们指定数据类型。 ?解决方案:
可以使用<value>的type指定,也可以在集合标记中指定value-type 《partner4java 叙说Spring入门》之第一步:Spring概述与Spring IoC

使用工厂Bean和Utility Schema定义集合 :

?问题:
使用基本集合标记定义集合时,你不能指定集合的实体类,例如LinkedList、TreeSet或TreeMap,而且,你不能通过将集合定义为可供其他Bean引用的单独Bean在不同的Bean中共享集合。?解决方案:
两种方式
1、使用对应的集合工厂Bean,如ListFactoryBean、SetFactoryBean和MapFactoryBean。
2、引入util schema中使用集合标记,如<util:list>、<util:set>和<util:map>。 《partner4java 叙说Spring入门》之第一步:Spring概述与Spring IoC

bean的实例化模式:

?默认情况下,Spring中所有的bean均为单例。也就是Spring只维护一个单独的bean实例,所有的依赖对象都是用同一个实例,并且所有对BeanFactory.getBean(XXX)方法的调用都返回相同的实例。?对此测试下:打印了true(要是你的bean里有外部变量,你懂的,就等着掉坑吧)《partner4java 叙说Spring入门》之第一步:Spring概述与Spring IoC

非单例实例化模式:

?prototype:每次调用getBean()方法都返回一个bean的新实例。?request:每次在Web应用中调用getBean()方法将为每一个Http请求返回bean的唯一实例。此行为只在WebApplicationContext和他的子接口中实现。?session:每次调用getBean()方法将为每个HttpSession返回bean的唯一实例。跟request一样,此作用范围只在WebApplicatoinContext和他的子接口中有效。?globalsession:每次在portlet上下文中调用getBean()方法将为全局HttpSession返回bean的唯一实例。跟request和session一样,此实例化方式只被WebApplicationContext和他的子接口所支持。

选择一种实例化模式:

?单例适用:?无状态的共享对象:当有一个无状态且关联很多依赖的对象时,使用单例。如果无状态的差别,你就不需要做同步处理,当某个依赖对象在工作中需要使用这个bean时,你就不需要创建新的实例。?只读状态共享对象:这跟前一点相似,但是有一些只读的状态,比如说一个只读的属性。这种情况下,你仍然不需要做同步处理,因此为每一个请求创建bean的实例只会增加额外的开销而已。?共享状态的共享对象:如果你有一个必须共享状态的bean,单例便是理想选择。这种情况下,你需要确保状态写的同步尽量原子化。?具有可读状态的高吞吐量对象:如果某一个bean在你的应用程序中被大量的使用,你可能会发现保持单例并且对bean状态的所有写访问进行同步会比持续的创建上百个bean实例具有更好的性能。使用此方法时,在不牺牲连贯性的前提下尽量保持同步的原子性。当应用程序在一个较大的时间跨度内创建了大量的实例,或者当你的共享对象只有少量可写状态,再或者当创建新实例花销太大时,你会发现这个方法尤其有用。

使用非单例:

?具有可写状态的对象:如果你的bean有大量的可写状态,你会发现用以同步的成本比创建新实例来处理依赖对象的每一个请求的成本要高。 ?具有私有状态的对象:有时,依赖对象需要一个包含私有状态的bean以便他们能够同其他依赖此bean的对象区分开来独立运行。在这样的情况下,单例显然是不合适的。

亲,IoC知道是啥了么? 下面俩小时我们来具体说下各种基本使用 begin…


用依赖检查属性:

?问题:?在大规模的应用中,IoC容器中可能声明了几百个甚至几千上万个Bean,这些Bean之间的依赖往往非常复杂。?设置方法注入的不足之一是无法确定一个属性将会被注入。?检查所有必要的属性是否已经设置是非常困难的。

解决方案(依赖检查):

?dependency-check--?none*不执行任何依赖检查,任何属性都可以保持未设置状态?simple如果任何简单类型(原始和集合类型)的属性未设置,将抛出UnsatisfiedDependencyException异常?objects如果任何对象类型属性没有设置,将抛出UnsatisfiedDependencyException异常?all如果任何类型的属性为设置,将抛出UnsatisfiedDependencyException异常 ?不过在新的版本中已经废弃 ,以后遇到了面熟就行

用@Required注解检查属性:

?问题:
Spring的依赖检查功能仅能检查某些类型的所有属性。他的灵活性不够,不能仅检查特定的属性。?解决方案:
RequiredAnnotationBeanPostProcessor是一个Spring bean后处理器,检查带有@Required注解的所有bean属性是否设置。
bean后处理器是一类特殊的Spring bean,能够在每个Bean初始化之前执行附加的工作。
为了启用这个Bean后处理器进行属性检查,必须在Spring IoC容器中注册他。

(后处理器是什么我们后面会讲到)


检查不合格后报错:

Caused by: org.springframework.beans.factory.BeanInitializationException: Property 'username'is required for bean 'user'  


用法:
1、xml加上<context:annotation-config />
2、在你要检测的字段上加上注解



替换@Required:

?如果你有特殊语义的注意要替换@Required这个,只需要做两步:?1、定义一个注解
// ...}

这个注解也可以用于以属性为参数/多个参数的方法

// ...}

// ...}

也可以一种提供来自// ...}

这同样适用于集合类型:

// ...}

甚至是 Maps 也可以这样注解,只要这个 Map 的 key 类型为 // ...}

在缺省情况下,当出现// ...}

// ...}

// ...}

// ...}

// implementation elided for clarity}

要检测这些类并注册相应的bean,需要在XML中包含以下元素,其中'basePackage'是两个类的公共父包 (或者可以用逗号分隔的列表来分别指定包含各个类的包)。

过滤器类型表达式范例annotation

// ...}

// ...}

// ...}

各种特色方式的Bean创建 (因为有时候,我们的bean并不是 普通的形态):

使用Spring的FactoryBean创建bean:

?问题:
你可能希望用Spring的工厂Bean在Spring IoC容器中创建Bean。
工厂Bean(Factory Bean)是作为创建IoC容器中其他Bean的工厂的一个FactoryBean。概念上,工厂Bean与工厂方法非常类似,但是他是Bean构造期间可以Spring IoC容器识别为Spring专用Bean。?解决方案:
工厂Bean的要求是实现FactoryBean接口。为了方便,提供了抽象模板类AbstractFactoryBean供你扩展。
工厂Bean主要用于实现框架机制。如:
·在JNDI中查找对象(例如一个数据源)时,你可以使用JndiObjectFactoryBean。
·使用经典Spring AOP为一个Bean创建代理时,可以使用ProxyFactoryBean。
·在IoC容器中创建一个Hibernate会话工厂时,可以使用LocalSessionFactoryBean。?工作原理:
尽管你很少有必要编写自定义的工厂Bean,但是会发现通过一个实例来理解其内部机制很有帮助。
通过扩展AbstractFactoryBean类,你的工厂bean能够重载createInstance()方法以创建目标Bean实例。
此外,你必须getObjectType()方法中返回目标Bean的类型,是自动装配(Auto-wiring)功能正常工作。
名称之前添加&,可以得到工厂Bean的实例。
public class LogBeanPostProcessor implements BeanPostProcessor {        @Override      public Object postProcessBeforeInitialization(Object bean, String beanName)              throws BeansException {          System.out.println(beanName + " say hello world!");          return bean;      }        @Override      public Object postProcessAfterInitialization(Object bean, String beanName)              throws BeansException {          System.out.println(beanName + " say good buy!");          return bean;      }    }    <!-- 要在应用上线文中注册一个Bean后处理器,只要在Bean配置文件中声明他的一个实例就可以了。 应用上下文能够自动检测谁实现了BeanPostProcessor接口,并且注册他一处理容器中的所有其他Bean实例 -->  <bean class="com.partner4java.spring.postprocess.LogBeanPostProcessor" />    <bean id="helloResourceLoader" class="com.partner4java.spring.resource.HelloResourceLoader"      init-method="showResource" />            如果以配置文件的格式设置init-method,对BeanPostProcesser的执行没有什么威胁,BeanPostProcesser还是会先执行。  但是如果,以@PreDestroy和@PostConstruct的形式,BeanPostProcesser讲不能正常工作,因为BeanPostProcesser的默认优先级低于CommonAnnotationBeanPostProcesser。  不过可以同时实现PriorityOrdered接口来指定执行顺序。        

Spring BeanFactoryPostProcessor类 (“排队”“后”控制修改beanfactory管理的信息--如一些配置信息)

http://blog.csdn.net/partner4java/article/details/6969417

(比较晚了,明早还有事,后面可能整理的有点乱,改天再修改下)