IOC和DI
- IOC(Inversion of Control 控制(权)反转)
啥是Spring,一句简单的话来概括,Spring是一个具有众多工具的IOC容器。众多工具:各种功能模块和类库。
IOC容器:通过一些注释把创建对象这件事交给了Spring,我们自己减少了许多对对象的创建,需要啥对象通过注解去拿就行了。降低了程序间的耦合性。
IOC存对象的注解分为
类注解:@Controller:控制层, 接收请求, 对请求进⾏处理, 并进⾏响应. @Servie:业务逻辑层, 处理具体的业务逻辑. @Repository:数据访问层,也称为持久层. 负责数据访问操作,像是存到数据库里之类的。@Configuration:配置层. 处理项⽬中的⼀些配置信息
方法注解:@Bean,在Spring中把Bean称为对象
这么多的注解是为了方便去定位。就像车牌前的省份缩写
- DI(Dependency Injection依赖注入)
DI是从Spring中取出对象注入到目标变量的一种实现方式。我感觉这可以让很多个对象的属性都使用特地的对象.有点奇妙的感觉,与日常编程习惯有很大的不同.平常都是用一个然后对象里在重新new,DI的话就可以让不同的对象使用同一个属性.
DI注入分为三种
- 属性注入
- 构造方法注入
- Sette方法注入
- 接下来我们实操一下
- 先用五大注解标识这个类,然后就自动把他存到Spring里了。
这里要注意的是三种常用的getBean方法,当使用字符串的时候是对象的名字,默认是类名的小驼峰,当第一个和第二个都是大写字母的时候就不变第一个了。然后aClass是类名.class。
想把这个对象赋值直接赋值给一个变量名也可以,如果没有注入那么poerson就会是null
这个就是注入要用到DI的三种方法下面配合@Bean演示
- 通过@Bean
@Bean可以对方法使用让方法返回的对象交给Spring管理,并通过getBean或者@autoWired来使用.但前提是@Bean对应方法所属的类要被五大注解修饰,也就是说要把类当做对象交给Spring.同时也可能会发生一个重名问题,我们可以用({“变量名”,”变量名”})来进行重命名.名字虽然多但都是对应同一个对象.默认是方法名.
@Controller |
那么如果我们要多个对象是不是要注解多个方法,是的.那么既然都有多个方法了那么重载是不是也可以,重写呢?具有参数的要怎么办.且听我娓娓道来.
重写: 如果父类和子类都使用了@Bean,那么是不行的就算子类返回父类的对象也是不行的(也就是子类方法的返回值是父类被重写方法返回值的父类)解决方法:考虑重命名其中一个bean,或者通过设置spring.main.allow-bean-definition- override =true来启用覆盖,如果只有一个被@Bean修饰那么Spring就可以直接建立对象.
重载:重载肯定涉及到了参数问题,那么我们该如何传参给@Bean修饰的方法呢.如果同时存在无参和有参的那么只有有参数的会被生成对象,如果有多个有参数的重载方法,很神奇,参数数量一样就无法创建,不一样就创建参数多的那个.想解决这个问题也很简单重命名就完事.
这以上我只是试出来的不一定对,请酌情参考.
接下来我们使用DI的三种方法
- 属性注入.
以类型为匹配第一标准,第二标准是名称.且无法修饰final属性的对象.无法在非IOC容器里使用
- 构造方法注入
默认使用无参构造方法,没有的话如果只有一个构造方法就使用这个,有多的就要用到@AutoWired来标准.参数的话要使用其他类创造出来的对象,不能是这个类创造的.
- Setter方法注入
属性注⼊
优点: 简洁,使⽤⽅便;
缺点: 只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指 针异常)不能注⼊进⼀个Final修饰的属性
构造函数注⼊(Spring 4.X推荐)
优点: 可以注⼊final修饰的属性 注⼊的对象不会被修改 依赖对象在使⽤前⼀定会被完全初始化,因为依赖是在类的构造⽅法中执⾏的,⽽构造⽅法是在类加载阶段就会执⾏的⽅法,通⽤性好, 构造⽅法是jdk⽀持的, 所以更换任何框架,他都是适⽤
缺点: 注⼊多个对象时, 代码会⽐较繁琐
Setter注⼊(Spring 3.X推荐)
优点: ⽅便在类实例之后, 重新对该对象进⾏配置或者注⼊
缺点: 不能注⼊⼀个Final修饰的属性注⼊对象可能会被改变, 因为setter⽅法可能会被多次调⽤, 就有被修改的⻛险.(手动调用的时候)
@AutoWired的一些问题
当Spring存在多个对象的时候,注入时先根据类型来匹配其次根据名字.这里有不改名字和改名字几种方法
- @Primary:让注入的时候默认使用这个对象.在产生对象的地方使用
- @Qualifier(“指定注入Bean的名称”): 指定要注入的对象,在被注入的时候也就是@AutoWired的时候配合使用
- @Resource(name = “指定注入Bean的名称”): 也是在被注入的对象处使用.与@AutoWired恰恰相反,@Resource优先匹配名字其次是类型.啥意思呢?具体.@AutoWired是在有多个与被注入对象类型相同时才考虑去选择名字.而@Resrouce是在名称相同的情况下才去考虑类型.而且@Resource是JDK提供的注解而@AutoWired是Spring提供的