SpringIOC
Spring简介
Spring是一个开源框架,它由[Rod Johnson]创建。它是为了解决企业应用开发的复杂性而创建的。
目前是JavaEE开发的灵魂框架。他可以简化JavaEE开发,可以非常方便整合其他框架,无侵入的进行功能增强。
Spring的核心就是 控制反转(IoC)和面向切面(AOP) 。
IOC控制反转
控制反转,之前对象的控制权在类手上,现在反转后到了Spring手上。
具体步骤
导入依赖
编写配置文件
创建容器对象获取实现类对象完成测试
Bean的属性
scope
单例模式下
执行第一句话创建容器的时候就会创建实现类对象
之后执行getBean方法不会创建
多例模式下
执行第一句话不会创建实现类对象
之后每执行一次getBean方法,创建一次对象
spring源码分析
测试方法中创建了ioc容器的对象,传入了beans.xml的path参数
调用getBean方法传入接口名,获得接口实现类对象,来调用实现类接口
classPathXmlApplicationContext容器源码
创建了一个HashMap集合来存放对象
load方法
document内容
获取标签中的calss和id值
通过反射机制创建对象
把id作为key,创建出来的对象作为value存进最开始的beanMap集合中
到这里第一句创建对象就结束了
第二句getBean传入id参数
就是从beanMap中根据id获取对象
这里就完成了对象创建的解耦合
可以直接修改xml文件里的impl名
这里就可以直接newIOC容器传入beans.xml文件和id就可以获取到实现类对象了
DI依赖注入
一些实现类比如service的实现类里面一般有dao的属性值好来调用crud
比如这里service的实现类里面有dao的属性值
但是我们通过ioc创建对象的时候,没有给这些属性值赋值,默认为null
当需要用到userDao来调用方法的时候
会报空指针异常错误,就需要通过DI依赖注入的方式来给这些属性值初始化
Set方法注入
我们平时给属性值赋值的时候一般有两种方法
- 空参创建出对象,来调用set方法赋值
- 直接有参构造创建对象
可以在bean标签内用property标签来给属性值赋值
这里其实就是调用了实现类的set方法,如果实现类没有set方法,则报错
ref引用数据类型赋值
假设我们在student里面创建一个dog类型的属性
可以在ref标签中写上spring容器中bean的id来注入
有参方法注入
复杂类型注入
实体类如下
配置如下
Phone注入
List集合注入
List集合注入
Set注入
Map<String,Phone>注入
数组int[]注入
properties类型注入
小技巧:
先写标签,空格看有没有可以写的属性,没有就结束标签,继续空格看有没有,有的话就写在标签内,没有就写在标签外
SPEL表达式
可以进行简单的计算value=“#{10+10}”
ref=“car” 等价于value=“#{car}”
Lombok插件
引入依赖
安装插件
使用方法
在JavaBean中使用
@Data就是编译时自动生成get,set,toString,Hashcode,equals等方法
@NoArgsConstructor 空参构造
@AllArgsConstructor 带参构造
bean读取配置文件注入
举例
DruidDataSource数据库连接池对象
引入依赖
正常连接步骤,new连接池对象,set设置连接参数
可以丢给xml文件的bean来帮我们new对象并且注入值
JDBC配置文件
因为我们编译的时候,resource文件下的配置文件都会自动放到target目录的classes目录下
完整步骤
引入其他xml配置文件
当我们项目比较大的时候,会有很多个xml文件
所以需要有一个主的xml文件来引入其他的xml文件
比如上文的数据库连接的xml文件就可以单独放到一个jdbc.xml文件中
然后在主配置文件中引入这个jdbc.xml文件
低频知识点
bean的配置
name属性
也可以通过name来给bean取名字,name可以有多个
lazy-init
当我们是默认是单例模式的情况下,创建容器的时候就会创建实现类对象,之后执行getBean方法不会创建
使用lazy-init="true"的时候,创建容器的时候不会创建实现类对象,之后执行getBean方法创建
init-method
创建实现类对象的时候,spring会帮我们自动调用某一个方法,但是必须是空参的!
destroy-method
当对象销毁前的时候,自动调用方法,也必须是空参的
什么时候对象会销毁呢**,单例模式下**,只有容器销毁的时候,对象才会销毁
我们也可以调用.close()来关闭容器
工厂类
这是一个car的类,里面有三个引用类型的属性,每个属性都有一个测试方法来调试
当我们需要得到一辆车的时候,需要new Car,然后set属性,最后还要调试
我们可以把这段代码封装到一个工厂类的getCar方法中
在主方法中就可以直接创建这个工厂类,来调用getCar方法,获得一辆车
这属于实例工厂,因为方法不是静态的,需要创建对象,才能getCar
我们可以把getCar方法设置成静态方法,就可以直接用类名来调用,这属于静态工厂
spring使用工厂类
实例工厂创建对象
我们可以让spring来执行上面这些代码
配置文件中先设置工厂类
再设置一个bean,但是这个bean没有class
factory-bean:指定使用哪个工厂对象
factory-method:指定使用哪个工厂方法
测试类中
这里getBean使用的id是car
静态工厂创建对象
不需要创建工厂对象了
配置文件中class指定工厂类的全类名,然后factory-method指定使用哪个工厂方法,要有一个id属性
测试类中
注解开发
@component
等价于<bean…id=“student”>
前提在配置文件中添加component-scan
DI注解
简单属性注入**@value(“”)**
支持SPEL写法#{}
@Autowired
引用数据类型注入(就是从spring容器中找满足这个类型的注入)
前提: 本类和引用类都要被注解修饰(放到spring容器里面才能被找到)
required属性代表这个属性是否是必须的,默认值为true。
如果是true的话Spring容器中如果找不到相同类型的对象完成属性注入就会出现异常。
如果改为false,就是找不到也无所谓,不报错,但是不会赋值,就是null
@Qualifier
当一个包下面有多个同类型的对象时候,@Autowired找不到,就需要@Qualifier来指定某一个对象的具体id
需要和@Autowired连用
替换xml文件
自定义创建一个ApplicationConfig配置类
@Configuration
标注在类上,表示当前类是一个配置类。我们可以用注解类来完全替换掉xml配置文件。
注意:如果使用配置类替换了xml配置,spring容器要使用:AnnotationConfigApplicationContext
测试类
@ComponentScan
可以用来代替context:component-scan标签来配置组件扫描。
basePackages属性来指定要扫描的包。
Bean注解
和@component@Service@Repository一样
都是代替标签放到spring容器中的,但是@Bean主要是用来导入第三方类的
比如DruidDataSource类
xml文件中
ApplicationConfig配置类导入
使用:定义一个方法,在方法中创建对应的对象并且作为返回值返回。然后在方法上加上@Bean注解,注解的value属性来设置bean的名称。
如何选择?