说明:学习出了xml以外spring还支持的注解与java Config两种配置ioc容器的方式
作为xml注解或者java config这三种只是配置方式上的不同,底层原理都是一样的
了解下注解的优势
按功能划分
分别进行讲解
作为这四种注解如果要被springioc所识别的话还需要条件
如何基于注解完成ioc 容器的对象实例化
创建工程
创建依赖
创建xml文件
注解不是为了摆脱xml文件吗?为什么这里还要创建?
最基础的配置还是要写在xml文件中,引入基于注解的
增加了一个名为context的命名空间,来设置基准的包名只要类符合前缀要求都可以被扫描
创建包
新建用于用户表增删改查的UserDao类
增加注解,用于说明当前这个类对象是用于数据持久化,增删改查
作为bean来说总要有一个id这个id是什么呢?也可以手动书写
创建应用程序入口,初始化ioc容器
将容器内对象打印出来,获取所有有效beanid,进行遍历
测试一下
正好验证了我们的设置
将其去掉再来看一下
因为没有明确的beanid所以就默认使用了类名首字母小写来作为beanId使用,平时工作时都是用类名首字母小写来命名。
看一下其他的注解,创建用户逻辑类
只用这一个注解便可以完成ioc容器对象创建与管理的工作
在找到控制器
最后作为utils工具类中可能也包含了很多需要被ioc管理的对象,但是utils这些工具,作为spring并没有给她明确的一个分类到底是什么
对于这种不好分类的直接增加
就好了
无论是哪一种注解都可以通过括号内设置beanid来自定义
运行一下
在ioc容器初始化的过程中 ,为我们创建了四个对象
思考一个问题,作为这些bean在容器中是单例的还是多例的呢?
答案肯定是单例因为只有单例才会在ioc容器初始化的过程中进行创建,如果是多例模式则会延迟到getBean或者是进行对象注入的时候才会创建。
如何基于注解完成对象的注入?
运行的过程中自动的为某个属性注入数据,自动装配注解就是为了依赖注入所存在的
看一下这两类是什么
在之前的项目中
我们对bookService这个服务类动态注入了bookDao。对bookDao属性注入的过程中采用的是利用ref属性引用另一个bean的id,对这种使用bean的名称来完成依赖注入的过程我们称为按名称注入,在绝大多数的场景下我们都是使用bean的名称来动态注入到其他属性中的,在注解情况下又提供了另外的选择
按类型装配是指我并不关心这个容器内bean的名称叫什么,我只需要在运行过程中为属性进行注入时把与属性相同类型的对象完成自动注入。不推荐使用
进入代码演示
在属性上增加动态装配的注解
按类型注解,生成getset ,默认构造方法
运行
应该还有setUdao的方法调用,但没有出现。
将userService提取出来进行打印,看一下具体的输出
发现udao是有数据的 ,而且和放在容器中的数据是同一个,但为什么没有调用set方法完成注入呢?
做个实验把@autowired放在setUdao上运行
此时出现了
在set方法上增加注解和在属性名上增加注解都可以完成对象的注入,但是一个执行了set方法一个没哟执行,他们根本有什么不同呢?
正是因为这个过程是在运行时动态完成,而且基于这种使用办法并不需要是依赖于set办法所以在日常开发中如果基于注解去完成对象依赖注入的话。我们通常是不会生成set方法的,多数情况下会直接在属性上增加对应的装配注解。
为什么在工作中不推荐进行类型装配呢?
演示一下创建接口
实现接口
因为有了接口了,作为userService中按照面向对象编程的理念,属性的类就从具体的类型变成接口了
这里没有问题可是随着技术的发展,我们原有的UserDao是基于mysql数据库进行的开发,但是随着公司技术转型要把数据迁移到其他的数据库上,这时候开发者想到的是基于接口在创建一个全新的实现类
这里程序运行时就会出问题了
作为用@Autowired描述的属性类型是IUserDao这个接口,那么在注入的过程中,自然ioc容器会在。当前容器中查找有哪些,bean的类型是IUserDao,结果发现有两个都实现了IUserDao
注入过程就出现问题了,springioc容器就不知道要将那个bean注入到当前的udao属性中
如何解决?
去掉注解userdao就不会被管理,就可以正常运行了
第二种方法引入其他的注解
primary是主要的意思默认采用由此注解所描述的对象进行注入
运行后也不会报错
究其根本就是在容器中可能会出现多个相同类型的对象。为了避免这种情况采用按名称注入,因为名称都是唯一的。
Resource注解按名称装配
如何按名称装配注解?
新建service
说明是一个service类
udao并不存在于当前的ioc容器中,这种情况resource就会走按类型匹配的情况,为了解决这个问题增加name属性去指向需要注入的对象
第二种是规范属性的命名
做一下实验
运行
改为userdao时
输出就发生了变化
改为udao
忘记设置primary
就会出现无法确认注入那个对象的错误
错误就消失了
什么是元数据注解?就是为springioc容器管理对象时,提供一些辅助信息
演示
意味着userService在容器中将会以多例的形式出现,同时创建UserService的时机就由ioc容器初始化变成了调用getBean或者将这个对象进行依赖注入时所创建
运行
代表init方法被执行了
@Value的含义是为某个属性设置静态数值
metadata用于描述UserService本身这个类的信息,如何使用@Value在运行时对其注入呢?
直接输入你想诸如的数据就行了
问题来了这个字符串也是在程序中写死的,和直接对其进行赋值好像没什么区别
而且这种比运行时反射注入效率还要高,那存在的意义是什么呢?
并不是在源代码中将其数据写死还可以将这些静态数值剥离到配置文件中来进行说明
演示
新建
代表的是应用程序的配置信息
如果要被spring所识别的话,必须要在xml文件中将其加载
加载后我们便可以在具体的@value注解中进行引用了
引用的方法是
在init方法中把值打印出来
作为配置文件的使用是很广泛的
通过增加前缀来说明配置选项的作用或者范围是什么
实际引用时也要增加完整的字符串