一、(1.IoC/DI思想 2.IoC容器 3.Bean)
IOC控制反转是一种思想:使用对象的时候,由主动new对象转化为由外部提供对象,此过程中对象创建控制权由程序转移到外部叫做控制反转
Spring技术对IoC思想进行了实现
内部提供了一个容器(Core Container)称为IoC容器,用来思想中的“外部”
IoC容器负责对象的创建,初始化等一系列工作,被创建或被管理的对象在IoC容器中统称为Bean
DI依赖注入
在容器中建立bean与bean之间的依赖关系的整个过程,称为依赖注入(例如Sevice需要依赖Dao对象在IOC容器中)
目标:充分解耦
使用IOC容器管理bean(IOC)
在IOC容器内将有依赖关系的bean进行关系绑定(DI)
二、(bean的基础配置, bean的别名配置,bean的作用范围)
1.bean别名设置(name) 定义bean的别名,可定义多个,使用逗号,分号,空格分隔
示例:
<bean id="bookDao" name="dao bookDaoImpl" class="com.lsheng.dao.impl.BookDaoimpl"/>
无论是通过id还是name获取,如果无法获取到,将抛出异常NoSuchBeanDefinitionException
2.scope也就是bean的作用范围设置,spring默认是单例的,只好在配置文件中的bean标签中设置
singleton(单例默认) prototype:非单例
例子:
<bean id="bookService" name="service service4" class="com.lsheng.Service.impl.BookServiceimpl">
3.为什么bean默认单例
这有点原因控制我们bean创建实例的对象,也可以防止无穷无尽创建对象,避免重
适合交给容器进行管理的bean
1.表现层对象,业务层对象,数据层对象,工具对象
不适合的
1.封装实体类域对象
三、实例化bean的三种方式
Spring的异常看法是直接拉到最下面,从下到上看,一层套一层
1.构造方法(常用)
需要无参构造方法,私有的也行,但是如果无参构造方法不存在,将抛出异常BeanCreationException,
2.静态工厂(了解)早期
public class OrderFactory{
public static OrderFactory(){
//为什么不直接new因为这里面可能还要加东西
return new OrderDaoImpl();
}}
配置
<bean
id = "orderDao"
factory-method="getOrderDao" //这个要弄出来,具体的方法名
class="com.ls.factory.OrderFactory"
/>
3.实例工厂(了解)早期
public class UserOrderFactory{
public UserOrderFactory getUserDao(){
return new OrderDaoImpl();
}}
因为是实例在测试类中先new一个工场对象
所以在配置中也是先给工厂来个bean
<bean id = "userDaoFactory" class="com....">
<bean
id="userDao"
factory-method="getUseDao"
factory-bean="userDaoFactory"
/>
第四种、是第三种的变种(实用)
配置文件
<bean id="userDao" class="com.lsheng.com.lsheng.factory.UserDaoFactoryBeann" />
FactoryBean
//里边泛型,你想造什么对象写谁的,这是实现一个接口
public class UserDaoFactoryBeann implements FactoryBean<UserDao> {
@Override
//这个一般默认,就是用来那个是不是单例的判断
public boolean isSingleton() {
// return FactoryBean.super.isSingleton();
return false;
}
//要实现接口中的抽象方法
@Override
//
public UserDao getObject() throws Exception {
// return null;,返回那个要创的对象
return new UserDaoImpl();
}
@Override
//你这个对象是什么类型,UserDao类型
public Class<?> getObjectType() {
// return null;
return UserDao.class;
}
}
四、bean的生命周期
①初始化容器
1.创建对象(内存分配) 2.执行构造方法 3.执行属性注入(set操作)4.执行bean的初始化方法
②.使用bean
1.执行业务操作
③.关闭/销毁容器
1.执行bean销毁方法
bean生命周期控制方法的两种格式(两种格式,第一次是配置的格式,第二种是按照spring接口的形式提供了解)
方法一: public class BookDaoImpl implements BookDao{
public void save(){sout省略}
public void init(){sout}
public void destory(){sout} }
配置生命周期的控制方法
<bean id="bookDao" class="com.ls.dao.impl.BookDaoImpl" init-method="init" destory-method="destory"/>
//告诉虚拟机容器关完再退,在虚拟机退出之前把容器关掉,才可以进行销毁操作,用到Ctx.close();但是在 ApplicationContext的子接口中有所以直接用实现类就可以
public class APP {
public static void main(String[] args) {
// ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ctx.getBean("bookDao");
bookDao.save();
//也可以使用关闭钩子,放在哪里都可以,但是close不行,放在前面直接都关了,二选一
//ctx.registerShutsownHook();
ctx.close(); //关闭容器,现在是比较暴力的方式
}
}
方法二:实现InitializingBean,DisposableBean接口
public class BookServiceImpl implements BookService,InitializingBean,DisposableBean{
public void save(){}
下面是两个重写方法
public void afterPropertiesSet() throws Exception(){}
public void destroy() throws Exception(){}
}
按照spring的要求写配置文件那两个就省了,因为感觉有点乱
五.容器的注入(Setter注入)
1.Setter注入,就是例如建立联系Service和Dao层建立联系,之前一直是一个,也可以多个dao层,就是多写几个就行
配置文件也是
①.这个算是比如引用类型
<bean id="bookService"name="serviceservice4"class="com.lsheng.Service.impl.BookServiceimpl">
<property name="bookDao" ref="bookDao"/>
<property name="userDao" ref="userDao"/>
</bean>
还有Dao层没有写出来也是两个
②.说说简单类型(比如int String)(property标签中value属性注入简单类型数据)
首先在实现类中加上private int connectionNum,private String databaseName,然后还有Set入口方法
还有配置文件中的操作
<bean id="bookService"name="serviceservice4"
class="com.lsh.Service.impl.BookServiceimpl">
//注意ref是引用bean的,要想给值就value
<property name="databaseName" value="mysql"/>
<property name="connectionNum" value="10"/>
</bean>
第二种注入方式(构造器注入)
构造器注入和Setter注入几乎差不多,
区别一: 在于标签中的<property name="bookDao" ref="bookDao"/>换做<constructor-arg name="bookDao" ref="bookDao"/>
配置中使用constructor-arg标签ref属性注入引用类型对象
<bean id="bookService" class="com.lsheng.service.impl.BookServiceimpl"> <constructor-arg name="bookDao" ref="bookDao"/> </bean>
区别二: 标签中的name不是指向实现类中的属性,而是构造器中的参数
区别三:就是实现类中去掉Set注入的方法而是加上构造器参数的构造方法;
其余大都一样,
然后构造器注入有一个小问题就是参数问题,和实现类的耦合度高,参数影响直接
对此有两种方法
六.依赖自动装配
这里要说的是实现类中的Set方法还要写,区别就在于那个标签中不用手动写注入了
之前:<bean id="bookService" class="com.lsheng.service.impl.BookServiceimpl"> <constructor-arg name="bookDao" ref="bookDao"/> </bean>
现在:<bean id="bookService" class="com.lsheng.service.impl.BookServiceimpl" autowire="byType"/> 还有可能就是byName
七.集合注入(数组,List, Set, Map, Properties)
这里面要是引用类型的数据就使用ref标签