* 【开闭原则】 * (1)非常重要的原则(OCP open closed principle) * (2)扩展开放的,修改封闭的 * 如何实现 * (1)最基础的就是面向抽象编程 * 利用abstruct、interface * * new 一个对象的目的使用里边的方法,编写业务逻辑,使用interface就不需要new * 直接重写里边的方法即可 - 面向抽象编程 * * 面向抽象编程 -> 实现开闭原则 -> 可维护代码 * * 【重点理论】 * interface * (1)多年的总结,单纯的interface可以统一方法的调用,但是它不能 * 统一对象的实例化。 * (2)面向对象主要做两件事:实例化对象 调用方法(完成业务逻辑) * (3)只有一点代码中没有new 的出现,才会保持代码的相对稳定,才能实现ocp * (4)上边的这句话只是表象,实质上一段代码如果要保持稳定,就不应该对象的实例化。 * (5)对象实例化是不可消除的。 * (6)把对象实例化过程 转移到其他代码块里边 * (7)代码中总是存在不稳定的额地方,只是要需要隔离这些不稳定,保证其他代码是稳定的。
2021年10月3日 - 反射强大之处
1、通过一个类的全路径,可以直接操作这个类的所有方法,类变量、实例变量等等。
spring 的ioc也是使用的反射 + 工厂模式
2、改动配置文件是不是符合OCP呢?
配置文件不应该属于系统,属于系统外部的,不属于代码本身。
3、常规长长操作,当我们想要一个对象时,需要new一个对象,或者自己封装一个工厂,然后调用工厂去创建一个对象,每一次都是自己主动去要;而 ioc 容器是主动给我们对象,不需要调用方法或者new 去获取一个对象了,而是直接定义这个对象。
4、为什么引入容器的概念之后,代码、系统会变的稳定了? 之前的强耦合,现在变为松耦合了呢?
强耦合,类与类之间有强联系:
松耦合,类与类之间不会有联系了:
5、IOC、DI、DIP
IOC 控制反转(我的理解:把控制对象的权利交给容器,我们只负责使用,当我们需要用对象时,去容易拿就行了,它会给我们对象,具体怎么创建的不需要管),它跟DI的关系:
ID是ioc的 实现 或者 描述 或者 应用。
DI 依赖注入
// spring会自动把obj给注入到A类中来
public class A {
private Obj obj;
public void getOb() {
obj.getName();
}
}
注入的方式:
(1)属性注入(上边代码就是属性注入)
(2)构造函数注入,
public class Obj {
// 通过构造函数参数进行注入
public Obj(A a) {
}
}
DIP 依赖倒置
6、容器再理解
容器实际上是在装配
2021年10月4日
【springboot理论课】
@Component @Service 把类加入容器中
1、spring、springMVC、springboot 关系:
(1)spring 就是spring framework 而,springMVC是spring framework 专门开发web的模块。
(2)springboot 对象于 spring framework的优势:
2021年10月5日
1、IOC 具体意义:
把类、对象加入到容器中,使用时,把对象注入进来。
2、抽象意义,也是目的:
控制权交给用户。
3、注解:
(1)@Component、@Autowired
在一个类中,打上@Component,springboot 会自动加到容器中去了并且实例化类;@Autowired 注入bean -> 使用bean。
(2)@Component
是一个最基础注解, - 把组件、类、bean(这三个名词都一样只是叫法不一样) 加入到IOC容器中去且实例化它。
(3)@Service @Controller @Repository
内部都是@Component,功能没有任何区别!都是把组件加入到容器且实例化的作用。只是标明一个类的不同作用。
@Service 标明这个类是一种服务的意思。
@Controller 标明这个类还有控制器的意思。
@Repository 标明这个类还有仓储的作用。
总结:以上所记录的都是围绕着类的实例化去展开的,上边4个注解,只要是放在类上,spring都会扫描到,且会把类加入到容器中实例化。
4、@Configuration
更灵活,在一个类中,可以把一组bean加入到容器中。
@Configuration 必须配合@Bean 使用,方法上加上@Bean,方法中必须返回一个bean!,此时Obj 会被加入到ioc容器中去。
@Configuration 标注一个类是一个配置类,对一个类进行相关的配置,spring3.0新增的注解,对应之前的 xml文件,下边的xml文件中的 <bean> 标签和里边的<property> 属性标签,对应的就是 @Configration注解 和 @Bean注解。
它相对于 @Component 的优势:
1> @Configuration 修饰的类中,可以自己new 一个bean,然后加入到容器中,而且可以在加入到ioc容器之前 对bean进行赋值操作。
通过有参构造进行赋值:
2> 最重要的就是,把一个bean加入到 IOC容器前,可以做一系列的处理,但是使用@Component 注解就不能这样处理 !!!
5、细节问题:
(1)@Autowired
默认注入的对象必须在容器中,如果不在容器中,会报错!,也可以配置 @Autowired(required=false) 取消报错,但是这样,如果用到注入进来的对象时,执行时会报错!
(2)ioc容器在什么时候,实例化和注入对象的时机?
在应用启动时实例化且会同时把对象注入到我们的代码片段里边去了。也是spring的默认机制!立即提前实例化对象。但是我们也可以配置让它延迟实例化,在springboot更改延迟bean、对象的实例化,需要使用 @Lazy注解。
但是,如果在控制层中用到了 Obj 这个类,如下:
Obj这个类不会被延迟初始化,因为,在应用启动时,控制层中的BannerController这个类 必须要立即初始化完成,而它所依赖的别的类也要必须立即初始化完成,不可能控制器类初始化完成了,但是它里边所依赖的来还没初始化完成,这是不允许的。
那么如何让Obj 这个类延迟初始化呢?
也很简单,在BannerController上也加上 @Lazy 注解即可,只有访问这个控制器的时候,BannerController类和 Obj类才会被实例化!
(3)任何类被注入的时候,在应用启动的时候,都会去加载 被注入类的无参构造函数。
(4)通常不会开启延迟实例化,因为要尽早发现问题,尽早解决问题。
(5)常见的注入方式:
1> @Autowired 属性注入
2> 构造函数的注入(推荐)
注意:构造函数的注入方式也要加 @Autowired
3> settter 方法注入(推荐)
注意:settter方法的注入必须要在上班加上@Autowired。
(6) @Autowired 注入方式
1> by type 是@Autowired 默认的注入方式,
2> by name
spring会去容器中找实现该接口的bean,大致分三种情况:
1> 找不到bean,直接报错;
2> 找到一个bean,直接注入;
3> 找到多个bean 并不一定报错,它还是会去看变量的名字,去推断要注入的bean,如果匹配不到,会报错,下边有案例 !
再来看下一个案例:
同一个Person接口,有2个实现类ImplA和ImplB,且在两个实现类都被加入到了容器中去了,在控制层使用,来看下效果。
Person接口:
ImplA 实现类:
ImplB实现类:
在控制层,注入 Person接口,如果我们如下写法:
idea会给我们报错!因为在容器中有2个类同时实现了 Person接口,且 @Autowired 默认的注入方式是 通过类型注入,在容器中,是Person类型的有2个ImplA和ImplB,所以通过类型找它也不知道,你想注入的是哪一个类!所以它还会通过名字(这个名字是首字母小写的类名) 来找注入的是哪一个bean,但是呢,容器中又没有person这个名字的类,所以,idea就会报错啦!在这里可以看出idea 非常强大,它会把问题给你推断出来!
所以,如果通过类型推断不出来的话,就必须通过名字注入,要注入的名字必须是类的首字母小写的名字,ImplA 类才会被注入进来!
c
(7)主动指定要注入哪一个bean的方式
@Qualifier("bean的名字")
这种方式是指定注入哪一个bean,此时的变量可以随便写啦,下边我们注入的是 implA这个bean, 所以下边打印的是 ImplA类中的信息。
(8)应对变化的方式
1> 指定一个interface接口,然后用多个类实现同一个interface - 策略模式。
2> 放到配置文件中去,或者添加变量。
(9)一个类加载顺序
无参构造函数 -> 注入属性(@Autowired、@Value)-> @PostConstruct