Spring的实现有两种方式,一是配置,二是注解
为什么会有IOC和DI?
因为要解决原有代码开发的问题:
IOC:控制反转,什么控制反转?创建对象的权利由程序反转到程序外部,也就是有IOC容器来创建对象。
DI:依赖注入,其实就是绑定,绑定什么呢?绑定两个有依赖关系的对象。
IOC和DI的目标和最终效果
//1.导入spring的坐标spring-context,对应版本是5.2.10.RELEASE
//2.配置bean-->
//bean标签标示配置bean
//id属性标示给bean起名字
//class属性表示给bean定义类型
//3.获取IoC容器
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
//4.获取bean(根据bean配置id获取)
// BookDao bookDao = (BookDao) ctx.getBean("bookDao"); 强转对象
// bookDao.save();
这样一套下来,业务层中的代码就可以不new对象了,改为
//5.删除业务层中使用new的方式创建的dao对象
//6.提供对应的set方法
//7.配置server与dao的关系-->
//property标签表示配置当前bean的属性
//name属性表示配置哪一个具体的属性
//ref属性表示参照哪一个bean
对于bean的基础配置,
IOC容器为我们创建对象默认为单例的,若想创建个多例的,需要在配置文件配置bean的scope属性
使用bean的scope
属性可以控制bean的创建是否为单例:
singleton
默认为单例prototype
为非单例<bean id="bookDao" name="dao" class="com.itheima.dao.impl.BookDaoImpl" scope="prototype"/>
//spring报错信息处理,看最后一个报错信息,这个解决了报错也就差不多可以解决,看不懂再看倒数第二个以此类推。
IOC容器创造bean对象其实是调用了构造方法,并且这个方法不论是公有的还是私有的都可以调得到,因为用到了反射。
因此bean实例化的第一个方法就是使用构造方法。
以前为了解耦,往往不自己new对象,而是交给工厂new,现在呢,静态工厂可以移交给spring来创建对象,需要配置要创造的bean的工厂方法(factory-method):
因此bean实例化的第二个方法就是使用静态工厂。
第三个方法:用FactoryBean创建对象,用UserDaoFactoryBean
实现spring框架的一个FactoryBean接口,这是一个泛型,需要指定对象,并重写接口的方法,接着在配置文件中配置
<bean id="userDao" class="com.itheima.factory.UserDaoFactoryBean"/>
关于是生命周期的核心问题
生命周期的控制主要由两种方是,第一种就是自己写初始化(init)操作和销毁(destory)操作,然后在配置文件中bean标签中添加init-method="初始化方法名" destroy-method="销毁方法名"
而运行后发现销毁方法中的内容并不会执行,why?
因此解决方法就是:
关闭容器的两种方式:
至此就介绍完了,但是这些初始化和销毁实现起来步骤比较多也比较乱,Spring提供了两个接口来完成生命周期的控制,好处是可以不用再进行配置init-method
和destroy-method
,操作:在业务类实现接口时添加两个接口InitializingBean
, DisposableBean
并实现接口中的两个方法afterPropertiesSet
和destroy
,例如:
public class BookServiceImpl implements BookService, InitializingBean, DisposableBean {
private BookDao bookDao;
public void setBookDao(BookDao bookDao) {
this.bookDao = bookDao;
}
public void save() {
System.out.println("book service save ...");
bookDao.save();
}
public void destroy() throws Exception {
System.out.println("service destroy");
}
public void afterPropertiesSet() throws Exception {
System.out.println("service init");
}
}
依赖注入的两类方式
setter引用类型注入,现在类中注入setter方法,然后在配置文件中使用property标签注入
例如:
其中ref的值是bean的id,name的值是引用类的对象名。
setter简单类型注入,先在类中声明对应的简单数据类型的属性,并提供对应的setter方法,然后在配置文件中使用property标签注入
例如:
其中name的值是声明的数据类型的名称,value是它的值。
对于setter注入方式的基本使用就已经介绍完了,
构造器引用数据类型,删除setter方法,添加带有参数的构造方法,然后在配置文件中使用标签
,例如
其中name属性对应的值为构造函数中方法形参的参数名,必须要保持一致。ref属性指向的是spring的IOC容器中其他bean对象。
构造器简单数据类型,删除setter方法,添加带有参数的构造方法,然后在配置文件中使用标签
,例如
其中name属性同上,value是它的值。
其实这俩在配置文件几乎没有差别不过一个property标签,一个是constructor-arg标签
那这两个如何选择呢?自己开发的模板推荐使用setter方法注入。
setter注入
简单数据类型
<bean ...>
<property name="" value=""/>
bean>
引用数据类型
<bean ...>
<property name="" ref=""/>
bean>
构造器注入
简单数据类型
<bean ...>
<constructor-arg name="" index="" type="" value=""/>
bean>
引用数据类型
<bean ...>
<constructor-arg name="" index="" type="" ref=""/>
bean>
依赖注入的方式选择上
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl" autowire="byType"/>
一般采用类型注入(byType),比如bean1依赖bean2,所以我们要在bean1标签的autowire属性中设置为byType,此时bean2甚至都不需要id,IOC就可以帮我们自动注入,当然自动注入只能注入引用类型。
环境:
BookServiceImpl中要调用BookDao的方法,势必要在BookServiceImpl中声明一个BookDao的对象,并且若实现自动注入,则BookServiceImpl中必须有BookDao的setter方法,再进行配置
如:
<bean class="com.itheima.dao.impl.BookDaoImpl"/>
<bean id="bookService" autowire="byType" class="com.itheima.service.impl.BookServiceImpl"/>
注意事项:按照类型在Spring的IOC容器中如果找到多个对象,会报NoUniqueBeanDefinitionException
数组、list、set、map、properties一共有五种
先声明集合,然后设置集合的setter方法,接着在配置中用property标记相应的bean,如:
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl">
<property name="list">
<list>
<value>100value>
<value>200value>
<value>300value>
list>
property>
<property name="array">
<array>
<value>100value>
<value>200value>
<value>300value>
array>
property>
<property name="set">
<set>
<value>itcastvalue>
<value>itheimavalue>
<value>boxueguvalue>
<value>boxueguvalue>
set>
property>
<property name="map">
<map>
<entry key="username" value="陈富源"/>
<entry key="passWord" value="1234"/>
map>
property>
bean>
说明:
、
、
、
、
标签
和
标签是可以混用
标签改成
标签,这种方式用的比较少对象有我们自己创建的,还有第三方提供的,如何管理这些第三方提供的bean呢?
先导入第三方的坐标,然后在配置文件中进行配置,一般使用标签property和value
对于一个陌生的第三方的bean,我们就要探索了,首先就是在mvnresportry搜索并导入所需要的依赖,然后猜测它的对象名是什么,看他是否可以用构造方法注入,如若不行则用setter方法注入,使用setter方法注入则在配置文件中用property和value标签配置就可。
举两个数据连接池的例子