《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的实现。
Spring架构图:
哥,我走了,别说了,吓到我了,东西太多了
亲,别怕,其实Spring就那十个左右的注解就完事了
牛B的框架不会太难用,牛B的代码不会太难懂。我们要跻身于那批能写牛B的代码人群中。。。
第二步,简易IoC:
控制反转IoC
begin:
控制反转和依赖注入:
不依赖Spring,我们先简单的实现下控制反转:
上下文依赖查找(CDL):
?在某些方面跟依赖拖拽相似,但是上下文依赖查找中,查找的过程是在容器管理的资源中进行的,而不是从集中注册表中,并且通常是作用在某些设置点上。
依赖注入方式:
?构造方法依赖注入:在构造方法依赖注入中,组件的依赖从他们的构造方法中提供。组件声明一个或一组构造方法,将他们的依赖作为参数,控制反转容器就会降依赖在组件实例化时传给他。
?设置方法依赖注入:在设置方法依赖注入中,控制反转容器通过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使用工厂Bean和Utility Schema定义集合 :
?问题:
使用基本集合标记定义集合时,你不能指定集合的实体类,例如LinkedList、TreeSet或TreeMap,而且,你不能通过将集合定义为可供其他Bean引用的单独Bean在不同的Bean中共享集合。?解决方案:
两种方式
1、使用对应的集合工厂Bean,如ListFactoryBean、SetFactoryBean和MapFactoryBean。
2、引入util schema中使用集合标记,如<util:list>、<util:set>和<util:map>。bean的实例化模式:
?默认情况下,Spring中所有的bean均为单例。也就是Spring只维护一个单独的bean实例,所有的依赖对象都是用同一个实例,并且所有对BeanFactory.getBean(XXX)方法的调用都返回相同的实例。?对此测试下:打印了true(要是你的bean里有外部变量,你懂的,就等着掉坑吧)非单例实例化模式:
?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 类型为
// ...}
在缺省情况下,当出现// ...}
要检测这些类并注册相应的bean,需要在XML中包含以下元素,其中'basePackage'是两个类的公共父包 (或者可以用逗号分隔的列表来分别指定包含各个类的包)。 各种特色方式的Bean创建 (因为有时候,我们的bean并不是 普通的形态): 使用Spring的FactoryBean创建bean:// ...}
// implementation elided for clarity}过滤器类型 表达式范例 annotation// ...}
// ...}
// ...}
你可能希望用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
(比较晚了,明早还有事,后面可能整理的有点乱,改天再修改下)