Spring容器创建对象的三种方式
-
构造器方式实例化
默认调用这个类型的无参构造
<bean id="标识" class="包名.类名"></bean>
- 静态工厂方法实例化
本质上调用一个静态方法,获取一个对象
<bean id="标识" class="包名.工厂类名" factory-method="静态方法名"></bean>
- 实例工厂方法实例化
本质上就是利用已存在的对象,调用成员方法,获取另一个类型的对象
<bean id="标识 factory-method=" 实例方法名" factory-bean="工厂对象"></bean>
Spring中对象的作用域
把一个对象是否单例也要看成作用域,默认Spring容器中的对象是单例的;可以通过bean标记的scope属性指定成别的作用域
如:prototype这是非单例 request、session等再web才会涉及
Spring容器中的对象的初始化和销毁
初始化
当容器创建之后可以通过bean标记的default-init-method=“方法名” 这样容器中所有类型对应的对象都会走这个初始化方法,这样影响比较大,所以某个类型中没有对应的初始化方法也很正常,这样容器是不会报错的;也可以通过bean标记的init-method来指定初始化方法,这样影响对象是比较精准的,如果对象中没有对应的初始化方法是会报错的。
销毁
当容器总的对象即将销毁,可以通过bean标记的default-destroy-method=”方法名“,这样容器中所有类型对应的对象,都会走这个方法。这样的影响范围也比较大,所以某个类型对应的对象没有对应的销毁方法也不会报错;也可以通过bean标记的destory-method来指定销毁方法,这样影响的对象是比较精准的,如果这个对象没有对应的销毁方法,则程序会报错
*注意销毁方法只针对单例模式,非单例模式需要手工调用
Spring的DI注入(解决的是组件装配问题)
DI有三种注入方式
- setter注入
基于set方法注入
如果是简单值(八种基本类型和封装类 String 、枚举)的赋值,直接使用value赋值
如果是复杂值,则使用 ref 进行赋值 ref=“对象在容器中的id”
<bean id=" " class=" ">
<property name="属性名" value=" 属性值"/>
//属性名就是set方法去掉set 首字母小写
</bean>
- 构造器注入
参考的是构造方法,构造方法看的是构造方法上的参数
<bean id=" " class=" ">
<contructor-arg name="参数名" value="值"/>
//属性名是set方法去掉set 首字母小写
如果是简单值(八种基本类型 和 封装类 String类 、枚举)的赋值直接用value赋值
如果是复杂值赋值,则使用ref ref=“对象在容器中的id”
//上面的name也可以index 用参数的位置来赋值
和setter注入不同的是,构造器注入必须有对应的构造方法
</bean>
-
自动化注入
可以在bean标记中加一个属性叫autowire 赋值有 byName、byType、constructro、
byName参考的是set方法,如果第一个不匹配 还会继续
byType参考的是成员变量的类型,如果第一个不匹配,则会继续
constructor会按照构造方法去找,如果第一个都找不到;则会终止查找。但不报错;
如果找到了对应的值,先会按照类型匹配,如果如冲突则会启用名字查找 -
参数的注入
简单值的注入
基本数据类型 封装类 String 枚举 直接使用value进行注入 可以使用 < value> 标记取代value属性 这样就不用加双引号了 也可以< null/>进行标记 意为赋值null
复杂之的注入
把上面的value换成ref即可
集合参数的注入(list set map properties)
List<list> <value>值</value> <value>值</value> </list>
set
<set> <value>值</value> <value>值</value> </set>
Map
<map> <entry key=" " value=" " > </entry> </map>
Properties
<props> <prop key =" "> 值</prop> <prop key =" "> 值</prop> <prop key =" "> 值</prop> </props>
集合参数的单独定义
拷贝过来 加 <util: 前缀 并且要加id 只有props 比较特殊需要使用 <util:properties id=" "> 属性集合单独定义时 还可以直接关联一个配置文件
Spring中的el表达式
获取Spring 容器中对象的值或者是对象的属性值 语法是 把之前的$ 换成 #
Spring的组件扫描
什么是组件扫描
Component Scan 组件扫描 他是Spring基于标注(注解)的技术,为了简化Spring中xml的配置编写的
在使用组件扫描时要记得在Spring容器中开启组件扫描
@Component 通用标注层
@Respository 持久层标注 针对DAO层
@Service 服务层标注
@Controller 控制层标注
-
组件扫描相关的其他标注:
控制对象作用域的标注 @Scope(prototype | singleton) 对象初始化的标注 @PostConstruct 对象销毁的标注 @Predestory
-
和DI相关的标注
@value 可以用在成员标量set方法上,它解决的是简单之的装配问题
写法是 @Value(“值”);
如果是复杂值装配,则需要el表达式
写法是 @value("#{对象名}")
@Autowired
可以用在成员变量 set方法 构造方法上
它解决的是复杂值的装配问题,优先以类型进行匹配,如有冲突则启用名字进行匹配
可以配合@Quailfier 来指定名字进行查找 但是这个不能用在构造方法上查找的组件默认是强依赖。可以通过required=false进行改变,当是false时 会尽量去查找,找不到也不会报错
@Resource
可以用在成员变量 set方法上
它解决的是复杂值的装配问题,优先按照名字进行查找,如果找不到则启用类型查找这个标注是jdk中的标注,不能解决强依赖。
Spring DAO
简化了DAO实现类的编写,对JDBC访问数据库做了高度封装,提供了基于aop的特性
对jdbc的异常做了封装。由继承原来的SQLException 变成了 RunTimeException的DAtaAccessException
继承jdbcDaoSupport的方式来使用SpringDao
也可以不继承jdbcDaoSupport的方式使用SpringDao
Spring中的事务管理
Spring中的事务管理形式
- 编程式的事务管理
- 基于AOP声明式的事务管理
声明式事务管理的实现步骤
-
开启声明式事务
<tx:annotation-driven transaction-manager="事务管理器id” proxy-target-class=“true | false” //transaction-manager指定Spring提供事务管理器 //proxy-target-class SUN有一套生成代理的API 目标和代理之间必须实现共同的接口 是兄弟关系 CGLIB写了新的API 目标和代理之间不用实现共同的接口,底层采用继承,目标和代理氏父子关系 //proxy-target-class =“false”时,代表优先使用sun公司的api如果生不成,则启用CGLIB;如果是true,则直接启用CGLIB
-
在容器中创建一个事务管理器
<bean id="事务管理器id“ class=”org.springframework.jdbc.datasource.DataSourceTranSactionManager“> <property name="dataSource ref=" "/> </bean>
-
在类上或者业务方法上加事务管理标注
@Tranactional