目录
二.springframework-core(bean容器)
DI的底层实现原理是依赖反射和ASM字节码框架实现(字节码框架操作字节码更为高效,功能更强大)
@Autowired和@Resource有什么区别呢?(M)
一.框架的概念:
1.什么是框架?
在java开发中,框架是指不需要我们自己去设计开发,而通过引入不同的依赖包,而实现不同功能的类和接口,我们后续的开发是在框架的基础基础上进行的,在狭义上来说,我们在开发项目时引入的每一个包都可以称为框架(比如实现网络传输过程中jackson字符串和java对之间的jackson包),在广义上说,框架是实现相对丰富且强大的功能的依赖包,每一个依赖包我们可以称为一个模块。我们在进行java企业级开发时通常使用的框架是ssm,即spring/springboot(基本的脚手架), springMvc(web开发的框架) 和mybatis(数据库开发)。
2.框架的作用?
使用框架进行开发,能极大的提高我们开发的效率,也方便于我们后期项目的维护工作的展开。
二.springframework-core(bean容器)
几乎所有的spring框架都是基于springframework的核心库的基础上来运行的,而其核心库就是有关bean的知识,bean我们可以先简单理解为一个普通的java对象
1.什么是bean容器?
bean容器与数据结构中的集合框架类似,是对bean对象进行存储取出和操作的容器,我们可以将容器理解为一个键值对(类似于hashmap)与集合框架有所不同的是,其对bean对象的操作并不完全是对外提供方法接口,而是部分采用注解的方式来实现对元素的操作。
对bean容器的理解(M)
上面对bean容器的介绍相对而言比较粗俗,正常的表述应该是这样的:bean容器是对IOC设计模式的一种实现,是使用容器来统一管理bean对象及对象之间的依赖关系的,其作用主要有两点(1)使用bean容器管理对象的生命周期(2)使用bean容器管理对象之间的依赖关系。创建bean容器的API主bean容器管理对象的生命周期(2)使用bean容器管理对象之间的依赖关系。创建bean容器的API主要有两种:BeanFactory和ApplicationContext(两个顶级实现接口)。其中BeanFactory只提供基本的容器功能:实例化bean对象和bean对象的依赖注入,BeanFactory采取的bean加载方式是懒加载方式,也就是说只有我们调用getBean()方法时,才会对bean对象进行实例化操作。
ApplicationContext是BeanFactory的子接口,其加在bean对象的方式是预加载,是在bean容器被创建就对bean对象进行加载,ApplicationContext除了实现基本的容器功能之外,还实现了更强大的一些功能:①整合bean对象的生命周期(管理整个bean对象的生命周期)②实现了I18的国际功能(可以理解为在不同的地区显示不同的语言)③载入多个(有继承关系的)上下文,使每个上下文都专注于自己的层次(各个上下文之间既可以是相互独立的,也可以是有关系的(继承关系和引用关系等等))
对IOC和DI的理解(M)
IOC即控制反转,主要是通过第三方IOC容器对bean对象进行统一管理以及组织对象之间的依赖关系。获得依赖对象由程序自己控制转化为由IOC容器主动注入,所以称为控制反转。IOC又被称为DI,IOC和DI是对同一个概念从两个侧重点进行描述,两者具有以下的关系:
①IOC强调的是使用bean容器管理对象和对象之间的依赖关系,获取依赖对象由程序自己控制转化为了由IOC容器主动注入,DI(依赖注入)强调的是bean对象之间所建立的依赖关系,
②IOC定义的是一种规范和思想,并没有具体实现,而DI是对IOC思想的一种具体实现
③IOC和DI的共同作用是实现解耦
DI的实现方式一般有两种,属性依赖和构造依赖:使用@Autowired修饰的属性是属性依赖,使用@Autowired修饰的构造方法是构造依赖:其中构造依赖的实现逻辑如下:将方法的形参按照对象名的方式在容器中获取bean对象,然后将形参赋值给类中的属性。
DI的底层实现原理是依赖反射和ASM字节码框架实现(字节码框架操作字节码更为高效,功能更强大)
spring中bean的作用域有哪些?(M)
①singleton:在同一个作用域下获取的bean对象都是一个bean对象,通过getbean()获取bean和@Autowired注入bean都是同一个bean对象
②prototype(原型):在同一个作用域获取的bean对象都是新建的bean对象,通过getbean()获取bean对象和@Autowired注入bean都是新的bean对象
③request:一次请求和响应共享同一个bean对象(只在这一次请求和响应中有效)
④session:一个用户的多次请求和响应共享同一个bean对象(只在一个用户的请求和响应中有效)
⑤application:在一个应用的servlet上下文声明周期中,产生一个新的bean对象
⑥websocket:在一个websocket生命周期内,产生一个新的bean对象
bean对象的生命周期(M)
①实例化bean
为bean对象在内存中开辟空间
②设置属性
为bean对象的属性进行注入和装配
③bean初始化
1)实现Aware各种通知方法 :BeanNameAware 、BeanFactoryAware、ApplicationContextAware的接口方法
2)执行BeanPostProcessor初始化前置方法
3)执行@PostConstruct初始化方法,依赖注入操作之后执行
4)执行自己指定的init-method方法(如果有的话)
5)执行BeanPostProcessor初始化后置方法
④bean的使用
⑤销毁bean
bean容器中所储存的bean对象通常是无状态的bean对象
有状态对象(Stateful Bean) :就是有实例变量的对象,可以保存数据,是非线程安全的。每个用户有自己特有的一个实例,在用户的生存期内,bean保持了用户的信息,即“有状态”;一旦用户灭亡(调用结束或实例结束),bean的生命期也告结束。即每个用户最初都会得到一个初始的bean。
无状态对象(Stateless Bean):就是没有实例变量的对象,不能保存数据,是不变类,是线程安全的。bean一旦实例化就被加进会话池中,各个用户都可以共用。即使用户已经消亡,bean 的生命期也不一定结束,它可能依然存在于会话池中,供其他用户调用。由于没有特定的用户,那么也就不能保持某一用户的状态,所以叫无状态bean。但无状态会话bean 并非没有状态,如果它有自己的属性(变量),那么这些变量就会受到所有调用它的用户的影响,这是在实际应用中必须注意的。
我们可以对其进行简单理解:无状态的对象就是bean对象的属性不随场景而变化,有状态的对象是其属性随场景而变化(如根据id来获取不同的对象)
2.bean对象的注入和注册
注册是指将bean对象存入spring容器中,而注入是指将容器中的bean对象取出到另一个地方(可能是方法的参数,也可能是某个实例对象的属性)
对于spring容器而言,bean对象的注册和注入都是通过注释来完成的:
①注册:
1.对于类的注册:我们通常使用的是@component注解
使用@component注解,容器将被注解修饰的类以首字母小写作为容器该bean对象的键,值为该bean对象,使用@component注解存储的对象,通常为单例对象(在不使用其他注解的情况下)
而在企业级项目开发中我们通常为了降低项目各个模块之间的耦合度,通常将整个项目分为不同的模块:对应不同的模块,单例bean对象的注册也对应着不同的注解:
@Controller:控制器存储,进行web开发使用的,对web请求和响应进行处理
@Service:服务存储,进行业务逻辑的对象注册:为整个项目提供服务。
@repository:仓库存储,进行数据访问操作,一般是指操作数据库
@component: 一般的组件,除了以上三种功能之外的其他功能
@configuration:指企业级/大型项目启动时需要加载的资源文件
2.对于方法的注册,我们通常使用的是@Bean注解
使用@Bean注解,容器将被注解修饰的方法作为容器对象的键,值为该容器的对象,如果是不同的方法返回同一类型的对象,那么bean容器中可以存储多个bean对象
②注入
3.对于bean对象的注入,通常使用的是@Autowired注解:(注入之后,两者存在依赖关系,person依赖于mobile)
使用autowired将容器中的Mobile对象注入到Person类中(根据对象名和对象类型进行注入,如果对象名不匹配则去匹配容器中的对象类型,如果发现spring容器中存在多个这样的类对象,直接报错)。
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'person': Unsatisfied dependency expressed through field 'mobile3'; nested exception is
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'org.ljl.Mobile' available: expected single matching bean but found 2: mobile,mobile2
另外,使引入lombok依赖包并使用@Data注解能实现setter、getter、tostring、equals和hashcode等方法的重写,提高代码开发的效率,也有利于后期代码的维护
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.24</version>
</dependency>
除了实现@Autowired能实现属性的注入之外,使用@Resource同样可以实现属性的注入
@Autowired和@Resource有什么区别呢?(M)
1.@Autowired是spring框架提供的注解,@Resource是JDK提供的注解
2.@Autowired必须在框架中使用,否则会报错@Resource不需要一定在框架中使用,但是具注解具体的功能JDK不负责实现。
3.显示指定某个bean的实现方式不同:@Resource(name=“ ”)实现,而@Autowired要结合@Qualifer实现
同一个类型的bean,如何正确注入到某个属性呢?(M)
三.基于spring容器的项目开发
项目开发的步骤如下:
①创建maven工程
②引入spring依赖包
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.3.22</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.22</version>
</dependency>
③创建容器并扫描包
ApplicationContext context=new AnnotationConfigApplicationContext("org.ljl");④根据注解注册依赖
⑤注入依赖