下面代码的实现十分简单,但是业务层需要调用数据层的方法,就要在业务层new数据层的对象,如果数据层的实现类发生变化,业务层的代码也需要跟着改变,意味着要编译打包和重新部署
// 数据层实现
public class FoodDaoImpl implements FoodDao{public void save(){...}
}
// 业务层实现
public class FoodServiceImpl implements FoodService{private FoodDao fd = new FoodDaoImpl();public void save(){fd.save();}
}
针对上述问题,Spring提出了一个解决方案:使用对象时,在程序中不要主动使用new产生对象,转换为由外部提供对象(Spring的核心概念)
IOC?使用对象时,由主动new产生对象转换为由外部提供对象,此过程中对象创建控制权由程序转移到外部Spring和IOC之间的关系是什么? Spring技术对IOC思想进行了实现IOC容器),用来充当IOC思想中的外部IOC容器的作用以及内部存放的是什么? IOC容器负责对象的创建、初始化等一系列工作,其中包含了数据层和业务层的类对象IOC容器中统称为BeanIOC容器中创建好service和dao对象后,程序能正确执行么?不行!service运行需要依赖dao对象,IOC容器中虽然有service和dao对象,但service对象和dao对象没有任何关系,需要将二者进行绑定上述提到需要绑定对象间的关系,使用的就是DI
什么是依赖注入DI?在容器中建立bean与bean之间的依赖关系的整个过程称为依赖注入
IOC容器中哪些bean之间要建立依赖关系?如业务层需要依赖数据层,service就要和dao建立依赖关系
充分解耦:
- 使用
IOC容器管理bean- 在
IOC容器内将有依赖关系的bean进行关系绑定- 使用对象时不仅可以直接从
IOC容器中获取,并且获取到的bean已经绑定了所有的依赖关系
Spring是使用容器来管理bean对象的,管什么?主要管理项目中所使用到的类对象,比如Service和DaoIOC容器?使用配置文件IOC容器,要想从容器中获取对象先要获取IOC容器,如何获取?Spring框架提供相应的接口IOC容器得到后,如何从容器中获取bean?调用Spring框架提供对应接口中的方法参考Spring_01_quickstart
分为思路和代码
IOC管理beanService中使用new形式创建的Dao对象是否保留?删除,因为要使用IOC容器中的bean对象Service中需要的Dao对象如何进入到Service中?在Service中提供方法(set方法),让IOC容器可以通过该方法传入bean对象Service与Dao间的关系如何描述?使用配置文件参考Spring_01_quickstart
主要掌握:
bean标签的id和class属性的使用- 对于是否设置单例的思考
代码参考Spring_02_base_config
id:bean的id,在容器中唯一
class:bean的类型(即bean的全路径类名),注意不能使用接口(因为接口无法创建对象)
name:定义bean的别名,存在多个就使用,;或者空格分隔,之后在ref和getBean方法中中也可以使用别名
scope:定义bean的作用范围,singleton表示单例(默认),prototype表示非单例
为什么bean默认为单例?避免了对象的频繁创建与销毁,性能高
bean在容器中是单例的,会不会产生线程安全问题?
哪些bean对象适合交给容器进行管理?
哪些bean对象不适合交给容器进行管理?
主要掌握:
bean是如何创建的?- 实例化
bean的三种方式代码参考Spring_03_bean_instance
bean如何创建?使用反射,因为把构造方法设置为私有也可以使用bean,所以使用的是反射
实例化bean的三种方式:
实例工厂实例化(了解即可):和静态工厂的区别在于工厂中的方法一个是静态一个不是,并且配置也不同
FactoryBean的使用:上述配置过于复杂,因为factory-method名称不固定每次都要配置,并且还需要特意创建id=userFactory的bean配合使用// FactoryBean创建对象
public class UserDaoFactoryBean implements FactoryBean {// 代替原始实例工厂中创建对象的方法(相当于统一了方法名为getObject)public UserDao getObject() throws Exception {return new UserDaoImpl();}public Class> getObjectType() {return UserDao.class;}// 如果要设置为单例/非单例,还可以实现isSingleton方法(不实现就取默认值-单例)
}
bean生命周期指bean对象从创建到销毁的整体过程;bean生命周期控制指在bean创建后到销毁前做的事主要掌握:
- 生命周期设置
bean的生命周期代码参考Spring_04_bean_lifecycle
生命周期设置:
BooDaoImpl类中分别添加两个方法,方法名任意,BookServiceImpl类中实现两个接口InitializingBean和DisposableBean,并实现接口中的方法afterPropertiesSet和destroyinit-method和destroy-method关闭容器(了解即可,因为交给Tomcat容器管理):不关闭容器无法执行消耗方法,关闭方式分为直接使用close方法和先注册钩子再使用close方法
bean的生命周期:
bean初始化方法主要掌握:
setter注入- 构造器注入
- 两个方式的使用选择
代码参考Spring_05_di_set和Spring_06_di_constructor
setter注入:
引用类型:详情见代码BookServiceImpl.java和applicationContext.xml
基本数据类型:和引用类型的区别在于applicationContext.xml中将ref改为value
构造器注入:在实体类中添加有参构造器,主要修改在于applicationContext.xml
引用类型:详情见代码中的applicationContext.xml,对于构造方法中形参名称和类型重复的问题也有说明
基本数据类型:和引用类型的区别在于applicationContext.xml中将ref改为value
使用选择:
setter注入有概率不进行注入导致null对象出现setter注入进行,灵活性强Spring框架倡导使用构造器,第三方框架内部大多数采用构造器注入的形式进行数据初始化,相对严谨
IOC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配主要掌握:
- 自动装配的方式
- 注意事项
代码参考Spring_07_di_autoware
自动装配方式:
autowire="byType"autowire="byName",需要保证被依赖的bean的id名和类中setter方法中把set删除并将首字母大写后的名称一致注意事项:
setter注入与构造器注入,同时出现时自动装配配置失效setter方法前面完成的是引用类型和基本数据类型的注入,还有集合类型(既可装基本数据类型也可装引用数据类型)未说明
主要掌握:
- 不同集合类型的注入
代码参考Spring_08_di_collection
不同集合类型的注入:详情见applicationContext.xml
property标签表示setter方式注入,构造方式注入constructor-arg标签内部也可以写、、、
标签List的底层也是通过数组实现的,所以
和标签可混用标签改成标签即可
https://www.bilibili.com/video/BV1Fi4y1S7ix?p=1-16
下一篇:行走在路上