第一章 IOC
一 、Spring 简介
Spring是一个轻量级的开源的J2EE框架,为企业级应用提供了一站式的解决方案,解决了企业级应用开发的复杂性
Spring是模块化的,总共有7个模块,可以选择使用需要的模块
两大核心:IOC、AOP
二、控制反转(IOC)、依赖注入 (DI)、面向切面编程(AOP)
在传统的开发中,当一个对象依赖另一个对象时,通常是在类中主动创建依赖对象,这样就增加了代码的耦合度,不利于代码的维护
控制反转的思想是 :对象不再自己主动创建依赖对象,而是把对象的创建和查找依赖对象的控制权交给了IOC容器
依赖注入和控制反转是一回事,只是描述的角度不同,IOC侧重于原理,DI侧重于实现
- 对象A需要操作数据库,以前我们总是要在A中自己编写代码来获得一个Connection对象,有了 spring我们就只需要告诉spring,A中需要一个Connection,至于这个Connection怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个Connection,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖 Connection才能正常运行,而这个Connection是由spring注入到A中的,依赖注入的名字就这么来的。那么DI是如何实现的呢? Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的
- A对象需要使用合作对象B来共同完成一件事,A要使用B,那么A就对B产生了依赖,也就是A和B之间存在一种耦合关系,并且是紧密耦合在一起,而使用了Spring之后就不一样了,创建合作对象B的工作是由Spring来做的,Spring创建好B对象,然后存储到一个容器里面,当A对象需要使用B对象时,Spring就从存放对象的那个容器里面取出A要使用的那个B对象,然后交给A对象使用,至于Spring是如何创建那个对象,以及什么时候创建好对象的,A对象不需要关心这些细节问题(你是什么时候生的,怎么生出来的我可不关心,能帮我干活就行),A得到Spring给我们的对象之后,两个人一起协作完成要完成的工作即可
AOP:在一个应用中,很多业务组件都需要关注一些功能,如事务管理、安全管理等,这些代码和业务组件的核心代码耦合在一起,不利于扩展和维护
AOP的思想是把这些系统级的服务从业务核心代码中分离出来
三、依赖注入
一个Java文件或者一个类,就是一个bean,在这个类中有属性、构造函数、方法。如果一个类A依赖于类B,那么在A 中可以引入一个B类型属性b,然后为这个属性b生成get/set方法,或者在A的构造函数中传入B类型的参数初始化b,这样在bean配置文件中就可以通过配置在A需要用到b的时候注入到A中了
Spring是通过反射的机制,调用set 构造方法实现了注入
bean的配置中,各种标签属性:http://blog.youkuaiyun.com/everyong/article/details/46517461
- 依赖注入有三种形式:属性注入、构造函数注入,工厂方法注入http://www.cnblogs.com/wkrbky/p/6369329.html
-
- set注入
<!--配置bean,配置后该类由spring管理--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <!--(1)依赖注入,配置当前类中相应的属性--> <property name="springDao" ref="springDao"></property> </bean> <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>
- 构造注入
<!--配置bean,配置后该类由spring管理--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置--> <constructor-arg ref="springDao"></constructor-arg> <constructor-arg ref="user"></constructor-arg> </bean> <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean> <bean name="user" class="com.bless.springdemo.vo.User"></bean> <!--参数不确定,比如同类型,使用index--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <constructor-arg index="0" ref="springDao"></constructor-arg> <constructor-arg index="1" ref="user"></constructor-arg> </bean> <!--不同类型是可以指定type--> <constructor-arg type="java.lang.String" ref=""/>
-
静态工厂的方法注入
<!--配置bean,配置后该类由spring管理--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction" > <property name="staticFactoryDao" ref="staticFactoryDao"></property> </property> </bean> <!--staticFactoryDao是从工厂类中的静态方法获得的--> <bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean>
-
实例工厂的方法注入
<!--配置bean,配置后该类由spring管理--> <bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <property name="factoryDao" ref="factoryDao"></property> </bean> <!--对象factoryDao是从工厂类daoFactory调用方法返回的--> <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean> <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>
- 注入值说明:
- 注入字面值 如基本数据类型及其包装类还有String类的 可直接采用字面值方式注入,即用<value> 注意特殊字< > & '' '' ''
- 注入null值 使用<null/>标签表示null
- 注入List、Map、Property
<!--设置List值--> <bean id="person" class="com.xxx.Person"> <property name="flist"> <list> <value>篮球</value> <value>音乐</value> <value>旅行</value> </list> </property> </bean> <!--集合合并tom是person的子类,merge设为false,那么tom就没有篮球,音乐,旅行--> <bean id="tom"parent="person"> <property name="flist"> <list merge="true"> <value>看书</value> <value>画画</value> </list> </property> </bean> <!--设置map值--> <bean id="person" class="com.xxx.Person"> <property name="fmap"> <map> <entry> <key> <value>key1</value> </key> <value>唱歌</value> </entry> <entry> <key> <value>key2</value> </key> <value>跳舞</value> </entry> <entry> <key> <ref bean="keyBean" /><!-- 对象类型 --> </key> <ref bean="valueBean" /> </entry> </map> </property> </bean> <!--配置java.Util.Properties类型的数据键和值都只能是字符串,没有value标签--> <bean id="person" class="com.xxx.Person"> <property name="fmap"> <props> <prop key="p1">唱歌</prop> <prop key="p2">跳舞</prop> <prop key="p3">读书</prop> </props> </property> </bean>
- set注入
- bean的自动装配问题
自动装配功能 就不需要ref进行手工装配bean ,可以减少配置文件的代码量,但不推荐使用,容易混乱 - bean配置的格式问题


<!--1、属性(set设值)注入--> <!--需要Car类中有brand的set()方法--> <bean id="car" class="com.gcl.sprint02.Car"> <property name="barnd"> <value>奔驰</value> </property> </bean> <!--2、构造函数注入,需要Car类中提供构造方法,参数的顺序与constructor-arg出现的顺序无关(跟web.xml的顺序相关不同)--> <!--通过类型匹配入参--> <bean id="car" class="com.gcl.sprint02.Car"> <constructor-arg type="String"> <value>奔驰</value> </constructor-arg> <constructor-arg type="Double"> <value>20000</value> </constructor-arg> </bean> <!--通过index匹配入参--> <bean id="car" class="com.gcl.sprint02.Car"> <constructor-arg index="0"value="奔驰" ></constructor-arg> <constructor-arg index="1"value="德国" ></constructor-arg> <constructor-arg index="2"value="2000" ></constructor-arg> </bean> <!--构造函数重载,通过index和type匹配入参--> <bean id="car" class="com.gcl.sprint02.Car"> <constructor-arg index="0"type="String"tvalue="奔驰" ></constructor-arg> <constructor-arg index="1"type="String"value="德国" ></constructor-arg> <constructor-arg index="2"type="int"value="20" ></constructor-arg> </bean> <!--3,非静态工厂方法注入,需要定义工厂类bean--> <!--car这个实例是通过CarFactory的creatCar()方法获得的--> <bean id="carFactory"calss="com.xxx.CarFactory"></bean> <bean id="car"factory-bean="carFactory"factory-method="creatCar"></bean> <!--4,静态工厂方法注入,不需要指向工厂类bean了,直接class指向CarFactory调用静态方法就行--> <bean id="car" class="com.xxx.CarFactory"factory-method="creatCar"></bean>
四、Spring开发包
首先下载springframework开发包:https://repo.spring.io/release/org/springframework/spring/
把需要的jar包加入到工程中,另外还需要一个Commons-logging的jar包
org.springframework.core.io.FileSystemResource;
org.springframework.core.io.Resource;
org.springframework.beans.factory.BeanFactory;
org.springframework.beans.factory.xml.XmlBeanFactory;
五、实例化IOC容器
- 获取配置文件——>实例化IOC容器——>获得一个bean实例
Spring实现IOC容器的方式有两种
-
- BeanFactory
spring框架的基础设施,面向spring本身 - ApplicationContext
BeanFactory的子接口,面向开发者,几乎所有的场合都可以使用ApprlicationContext而非底层的BeanFactory
两个实现类:
1,ClassPatnXmlApplicationContext:从类路径下加载配置文件
2,FileSystemXmlApplicationContext:从文件系统下加载配置文件
- BeanFactory


//1 读取配置文件 Resource res = new FileSystemResource("SpringLearn.xml"); //2 加载配置文件,启动IOC容器 BeanFactory f = new XmlBeanFactory(res); //从IOC容器中获取一个person对象 Person p =(Person) f.getBean("person");
第二章、AOP
一、AOP简介
- 什么是AOP
- AOP:Aspect Oriented Programming 面向切面编程,通过预编译或运行期动态代理实现程序功能的统一维护的一种技术
- 主要功能是:日志记录、性能统计、安全控制、事务处理、异常处理等
- AOP的实现方式
- 预编译 如AspectJ
- 运行期动态代理(JDK的动态代理、CGLib的动态代理)
如SpringAOP、JbossAOP
- 相关概念
Advice的类型 - 有接口和无接口的SpringAOP实现区别
- Spring AOP默认使用标准的JavaSE的动态代理作为AOP代理,这使得任何接口或接口集都可以被代理
- Spring AOP也可以使用CGLib代理(如果一个业务对象并没有实现任何接口,只有一个实现类)
- 切面配置
Spring所有的切面和通知器都必须包含在<aop:config>内(可以包含多个<aop:config>元素),然后可以配置aspect、pointcut、advice、Introductions、advisors等
切入点的expression:引入(Introductions):允许一个切面声明一个实现一个指定接口(IterfaceA)的通知对象,并提供一个该接口的实现类来代表这些对象;由<aop:declare-parents>元素申明匹配到的类型拥有一个新的父类对象
<bean id="theAspect"class="com.xxx.TheAspect"></bean> <bean id="abean"class="com.xxx.Abean"></bean> <!-- 首先定义一个切面类myAspect,然后定义切入点,例如 Abean类下的所有方法,然后配置通知, 前置通知 在切入点执行之前执行beforeM方法,这个方法在切面类TheAspect里面还有切入点terurn后、抛出异常后、执行后、、、 环绕通知:通知方法aroundM()的第一个参数必须是ProceedingJoinPoint类型的,例如pjp,在通知方法 aroundM()中,pjp.proceed();表示切入点方法的执行,在这行代码的前后可以写在业务逻辑代码前后需要做的事情--> <aop:config> <aop:aspect id="myAspect" ref="theAspect"> <aop:pointcut id="myPointcut" expression="execution(*com.xxx.Abean.*(..))"/> <aop:before method="beforeM"pointcut-ref="myPointcut"/> <aop:after-returning method="afterreturnM"pointcut-ref="myPointcut"/> <aop:after-throwing method="afterthrowingM"pointcut-ref="myPointcut"/> <aop:after method="afterM"pointcut-ref="myPointcut"/> <aop:around method="aroundM"pointcut-ref="myPointcut"/> <aop:around method="aroundMM"pointcut="execution(...........)"/> <!-- 匹配com.xxx.abc包下所有类的方法,这些类都有同一个父类InterfaceAimpl,而InterfaceAimpl类 实现了InterfaceA接口,所以匹配到的类都拥有InterfaceAimpl里面的所有方法,它们的类型也可以转换为InterfaceA类型 --> <aop:declare-parents types-matching="com.xxx.abc.*(+)" implement-interface="com.xxx.xxxx.InterfaceA" default-impl="com.xxx.xxxx.InterfaceAimpl"/> </aop:aspect> </aop:config>
二、Spring AOP的API
- 切入点Pointcut
NameMatchMethodPointcut:根据方法名字进行匹配,有一个成员变量mappedNames,匹配的方法名集合 - 前置通知Before advice
- 抛出异常通知
Throwsacvice接口 - 后置通知
- 环绕通知
- 引入通知
- ProxyFactoryBean
- org.springframework.aop.framework.ProxyFactoryBean是Spring AOP创建代理的最基础核心的一个类
- 这可以完全控制切入点和通知,以及他们的顺序
- ................
三、Spring对AspectJ的支持
。。。