1、Spring基础讲解
Spring是一种松耦合的对象创建和对象关系管理的框架。 业务层框架
持久层框架:Mybatis、Hibernate
非侵入式:系统中原来已经写好了很多类,现在引入一种新技术框架可以使用。在使用新框架的同时,原来的类不需要改动(不需要继承、实现新框架中的接口)。框架:Spring、Hibernate、Mybatis
入侵式:系统中原来已经写好了很多类,现在引入了一种新技术框架可以使用。在使用新框架的同时,原来的类需要改动。如:Struts,Servlet
IoC与DI:
IoC:(inversion of Control)控制反转,主要解决对象创建问题
DI:(Eependlecy Injection)依赖注入,主要解决对象关系(对象的依赖关系)的问题
AOP:(Aspect - Oriendted Programming)面向切面编程
OOP:(Objiect -Oriented Programming)面向对象编程
切面:简单理解为一个类(具有拦截功能),不影响正常的业务逻辑处理,只是在正常的逻辑处理前或者后做一些额外的操作。
用途:用于账户权限的设置,拦截
Spring的下载
下载:Spring官网(https://spring.io/) - github (Maven、传统)
开源中国:oschina
Version:5.0.2.RELEASE
Spring2 - Spring 3(支持@Annotation)
Spring 4.0的一些新特性:
A)全面支持Java 8
B)Web支持已经升级为支持Servlet 3.0以及更高版本的规范
C)支持Groovy DSL进行Bean配置
D)新增了一个spring-websock模块
Servlet 3.0开始,支持注解方式,如:@WebServlet
Servlet 3.0以下版本,不支持注解,必须写在web.xml中。
2、使用Spring编写一个HelloWordl入门程序
1、导入Spring包
用IDEA创建Maven项目,在prom.xml中添加Spring依赖,代码如下:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/3bc297cbda39407f02944361359b35b8.png)
2、创建Spring配置文件,在src/main/resoure目录下新建applicatonContext.xml文件
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/50081d0cefe105f86a25979c150510ed.png)
代码
<?xml version="1.0" encoding="utf-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:util="http://www.springframework.org/schema/util"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/util
http://www.springframework.org/schema/util/spring-util-5.0.xsd">
<bean id="per" class="org.jabari.spring.core.beans.Teacher"/>
</beans>
如果写入后报错
说明依赖库没有导入到环境当中,我们需要在prom.xml中新加代码
3、bean构造注入,方式一
在applicationContext.xml文件中,插入一条代码
<bean id = "per" class="org.jabari.spring.core.beans.Teacher"/>
bean可以帮助我们管理对象和创建文件
创建bean所认识的目录org.jabari.spring.core.beans
构造器的作用:详细代码讲解请看当日的另外一篇博客
这句代码就是构建对象的意思
ApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
从上下文当中get一个bean,bean的名字叫per,我们在applicationContext.xml中已经定义过了,
<bean id="per" class="org.jabari.spring.core.beans.Teacher"/>
拿到了Teacher,Person.class的意思是Teacher是Person的一个子类
Person pSpring = ctx.getBean("per",Person.class);
pSpring.biz();
注意,在bean构造注入过程中
<bean id="per" class="org.jabari.spring.core.beans.Teacher"/>
会调用无参的构造器所以我们需要留意在新建的类中创建有参构造器的同时,无参构造器是否存在
思考:那么我们如何不写无参构造器而能调用有参的构造器?
答案:
方式一:使用来注入Bean,这里的constructor-arg中的值就是你构建有参构造器参数的值
<bean id="teacher" class="org.jabari.spring.core.beans.Teacher">
<constructor-arg index="0" value="430421111111111"/>
<constructor-arg index="1" value="26"/>
<constructor-arg index="2" value="张三"/>
</bean>
index="0、1、2、3"index中的值代表有参构造器的第几个参数
方式二:使用c:命名空间来简化配置
开发过程:
步骤1:在xml文件的beans头加入:
xmlns:c=“http://www.springframework.org/schema/c”
步骤2:在xml中使用c来配置,如下:
<bean id="teacher2" class="org.jabari.spring.core.beans.Teacher"
c:_2="LiSi" c:_0="12345" c:_1="28">
底层反射机制原理:
String classStr = "org.jabari.spring.core.beans.Person";
Class clz1 = Class.forName(classStr);
Constructor cons = clz1.getConstructor(new Class[]{
String.class,int.class,String.class
});
Person pe = (Person)cons.newInstance(new Object[]{"1111132",32,"有参构造器"});
System.out.println("name="+pe.getName());
System.out.println("age="+pe.getAge());
System.out.println("identity="+pe.getIdentity());
4、bean设置注入
先创建一个空对象,再在里面set和get。
步骤1:在xml文件的beans头加入:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/7d118c3d0d36d1137e027f90a9d9d2d3.png)
xmlns:p="http://www.springframework.org/schema/p"
步骤2:
为什么在倒数第二行的addr,需要使用ref=”addr1“?
因为数据类型不一致。当数据类型为int或者数字之类的时候,可以用value,但是当数据类型复杂的时候,就需要使用ref来引用
5、Bean对象的scope范围
对象创建:单例/多例
scope=“singleton”, 默认值, 即: 默认是单例 【service/dao/工具类】scope=“prototype”, 多例; 【Action对象】
输出结果
可以看到,虽然我们代码中写了输出addr1三次,但是他只执行了一次,说明默认是单例。
我们如果要设置为多例,那么我们可以在
<bean id="addr1" class="org.jabari.spring.core.beans.Address" scope="prototype">
<constructor-arg index="0" value="湖南省"/>
<constructor-arg index="1" value="长沙市"/>
<constructor-arg index="2" value="开服区"/>
</bean>
这时候再次运行的结果:
这里就调用了三次,虽然我们代码
Address addr1 = ctx.getBean("addr1", Address.class);
只写了两次,但是
AbstractApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
也会在加载配置的时候默认执行一次,所以就有三次
5、Bean的懒加载
是否延迟创建
<beans default-lazy-init=”false” />
lazy-init=“false” 默认为false, 不延迟创建,即在启动时候就创建对象
lazy-init=“true” 延迟初始化, 在用到对象的时候才创建对象(只对单例有效)懒加载、延迟加载,使用到的时候,再加载,不要再在启动的时候加载。
6、Bean的初始化和销毁
创建对象之后,初始化/销毁
init-method=“init”
【对应对象的init方法,在对象创建之后执行 】
destroy-method=“destroy”
【在调用容器对象的destroy方法时候执行,(容器用实现类)】
销毁:
如果销毁方法执行成功,就会输出-Address对象销毁—
需要改变加载上下文bean的
将ApplicationContext变成AbstractApplicationContext
因为这里面有一个销毁容器,所以需要进行改变
public class TestBean03 {
public static void main(String[] args) {
AbstractApplicationContext ctx = new
ClassPathXmlApplicationContext("applicationContext.xml");
System.out.println("------------1------------");
Address addr1 = ctx.getBean("addr1", Address.class);
System.out.println("------------2------------");
Address addr2 = ctx.getBean("addr1", Address.class);
System.out.println("------------3------------");
// 销毁容器对象
// ctx.close();
ctx.registerShutdownHook();
}
同时如果需要进行销毁,那么在bean的配置文件中就不能配置多例,应该使用默认的单例。
这里说明多例的具有自动启动的类似功能,无法完全的关闭掉,当你需要使用的时候,即使是用close()也不能关闭。
BEAN的初始化和销毁的4种方式
参考网址:https://www.freesion.com/article/58011376370/
方式一: 自行指定bean的初始化方法和bean的销毁方法
方式二: 通过 InitializingBean和DisposableBean 接口实现bean的初始化以及销毁方法
方式三: 通过JSR250规范 提供的注解@PostConstruct 和@ProDestory标注的方法
方式四:通过Spring的BeanPostProcessor的 bean的后置处理器会拦截所有bean创建过程