什么是Spring
Spring是一个开发源代码的设计层面的框架,他解决的是业务逻辑层和其他各层的松耦合问题,因此它将面向接口的编程思想贯穿整个系统应用。
Spring的特点
-
方便解耦,简化开发
通过Spring提供的IoC容器,我们可以将对象之间的依赖关系交由Spring进行控制,避免硬编码所造成的过度程序耦合。有了Spring,用户不必再为单实例模式类、属性文件解析等这些很底层的需求编写代码,可以更专注于上层的应用。 -
AOP编程的支持
通过Spring提供的AOP功能,方便进行面向切面的编程,
许多不容易用传统OOP实现的功能可以通过AOP轻松应付。 -
声明式事务的支持
在Spring中,我们可以从单调烦闷的事务管理代码中解脱出来,
通过声明式方式灵活地进行事务的管理,提高开发效率和质量。 -
方便集成各种优秀框架
Spring不排斥各种优秀的开源框架,相反,Spring可以降低各种框架的使用难度,Spring提供了对各种优秀框架(如Struts,Hibernate、Hessian、Quartz)等的直接支持。 -
降低Java EE API的使用难度
Spring对很多难用的Java EE API(如JDBC,JavaMail,远程调用等)
提供了一个薄薄的封装层,通过Spring的简易封装,这些Java EE API的使用难度大为降低。 -
Java 源码是经典学习范例
Spring的源码设计精妙、结构清晰、匠心独运,处处体现着大师对Java设计模式灵活运用以及对Java技术的高深造诣。Spring框架源码无疑是Java技术的最佳实践范例。如果想在短时间内迅速提高自己的Java技术水平和应用开发水平,学习和研究Spring源码将会使你收到意想不到的效果。 -
方便程序的测试
可以用非容器依赖的编程方式进行几乎所有的测试工作,在Spring里,测试不再是昂贵的操作,而是随手可做的事情。例如:Spring对Junit4支持,可以通过注解方便的测试Spring程序。
下载
我所用到的jar包
什么是IOC
IOC: Inversion of Control(控制反转),将对象的创建权反转给(交给)Spring。
为什么要IOC
传统开发模式的弊端
① 假如有MySQL和Oracle两个数据库操作需求,所以就应该由这两个数据库操作的分别的实现类,在使用的时候new出所需要的实现类,然后进行操作
上图是都对Oracle数据库的操作,但是如果现在我的需求改变,数据库变成了MySQL,那我就要修改源码,即new出MySQL的实现类
这样业务与实现类过于紧密,业务改变要到底层取需改3次源码
② 在不引入Spring的时可以通过工厂来进行改进,实现接口和实现业务的分离,也就是说有一个可以生产所需类的工厂,再使用实现类的时候去工程拿取
当数据库改变的时候只需要去修改BeanFactory的代码,但是还是修改了源码,我们希望能在不修改源码的基础上,对程序进行扩展
③ 在工程内部使用配置文件(spring-ioc)
这样就能在需求更改的时候只修改配置文件而不修改源码
怎么使用Spring-IOC
① 导入Spring相应的jar包
② 创建Spring的配置文件
③ 添加配置文件,把类交给Spring管理
④ 测试使用
什么是DI
DI和IOC一起作为Spring的核心
DI:依赖注入,给spring管理类当中依赖的属性,通过配置文件进行赋值的过程(前提要有IOC的环境),拿到的对象以及就被注入好相关的属性值,直接使用即可
传统设置属性值的方法
使用依赖注入的方法
① 要被注入的属性要在实现类中提供set方法
② 在配置文件中进行注入
Spring的工厂类
spring创建的对象都是通过内部的工厂来通过反射创建对象,在老版本中是使用BeanFactory,当调用getBean的时候才会去创建实例对象;
现在使用ApplicationContext,加载了配置文件后就会创建实例对象(加载类目录下的applicationContext配置文件)
applicationContext中Bean的相关配置
- 设置对象的生命周期方法
init-method:在Bean被初始化的时候执行的方法,新版本Bean在配置文件加载就会初始化
destroy-method:Bean被销毁的时候执行的方法,对于单例模式,Bean在工厂关闭的时候销毁(applicationContext,close()),但是对于多例还是使用垃圾回收机制 - Bean的作用范围(scope)
默认是singleton,单例的,也就是说每次new出来的对象是同一个对象,地址相同 - 工厂实例化的方法
① 默认是调用类的无参构造方法进行对象的实例化
② 可以使用静态工厂实例化,使用类里面指定的静态方法进行实例化,该静态方法的返回值类型为该类
③ 实例工厂实例化(没事用)
一般只有默认的无参构造方法实例化
Spring属性注入的不同方法
-
使用属性set方法
使用set方法创建对象的时候实际上使用了该对象的无参构造方法,所以当这个对象写了有参构造方法的时候,一定提供无参构造方法,不然会报错 -
使用构造方法的属性注入
对于有参构造方法,需要明确配置,如果构造方法重载,则会使用同参的最后一个构造方法
public class User {
private String name;
private int age;
public User(String name, int age){
this.name = name;
this.age = age;
System.out.println("调用了User(String name, int age)");
}
public User(int age){
this.age = age;
System.out.println("调用了User(int age)");
}
public String save(){
System.out.println("name="+name);
System.out.println("age="+age);
System.out.println("save------");
return null;
}
}
<bean id="User" class="HibernateTest.User">
<constructor-arg name="name" value="abc"></constructor-arg>
<constructor-arg name="age" value="1"></constructor-arg>
</bean>
Spring注解开发
- 在Spring4之后,想要使用注解形式,必须引入aop的包
- 在配置文件中要新增一个context约束
<?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:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
-
配置组件扫描,确定哪个包里面的注解需要被扫描
-
要在设置中配置注解生效
-
在类上添加注解@Component
修改一个类,将这个类交给Spring管理 相当于在配置文件当中配置
component里面的内容就是里面的id
他还有三个衍生注解,是为了更好的分层,目前使用哪一个功能都一样, 后期可能会添加一些属于各自的属性
web层:@Controller
service层:@Service
dao层:@Repository
- 属性注入
① 使用@Value完成普通属性的注入
② 使用@Autowired设置对象类型的属性值,直接使用是按照类型完全属性注入,也就是说根据类型自动找到类,没有用到ID
如果想要使用ID可以使用第三种方法@Resource
③ @Resource
④ 初始化方法,销毁方法和作用范围的注解实现
@PostConstruct:初始化方法
@PreDestroy:销毁方法
@scope:作用范围
XML和注解方法对比
XML可以适用任何场景 ,结构清晰,维护方便但是写的多
注解开发简单方便但是不是自己提供的类实现不了,也就是说别人提供的工具类我们无法去源码里面添加注解使用
可以使用XML与注解整合开发,是两者优点最大化
使用XML管理Bean,而是要注解完成属性的注入,这个时候就不用去扫描包了,因为扫描包是为了扫描类上的注解,可以直接使用context:annotation-config/完成在没有扫描的情况下, 对属性注解@Resource @Value @Autowired @Qulifier的使用
Spring的JDBC模板
Spring是EE开发的一站式的框架,有EE开发的每层的解决方案。Spring对持久层也提供了解决方案:ORM模块和JDBC的模板。
Spring提供了很多的模板用于简化开发,如果不使用Hibernate的话,可以使用Spring的JDBC模板来简化操作,如果使用了Hibernate,也可以使用Spring提供的Hibernate模板
使用方法
- 导入相应的jar包
- 使用
数据库信息可以在配置文件单独配置
配置文件
① 方法1:的方式
② 方法2:使用context
要先加入需要的约束
Spring事务
Spring的事务管理的API
事务的传播行为
传播行为指的是业务B的方法当中,调用另一个业务A的方法,而业务A方法中已经有了事务,怎么去出来业务A的事务
怎么使用spring的事务(使用声明式事务中的@Transactional)
加载applicationContext配置文件的方法
存在问题
不能每次请求都创建一个Spring工厂,这样浪费服务器的资源,应该一个项目只有一个Spring的工厂,在服务器启动的时候,创建一个Spring的工厂,创建完工厂,将这个工厂类保存到ServletContext中,每次使用的时候都从ServletContext中获取。
解决方案
① 引入jar包 spring-web.jar
② 在wen.xml中配置监听器,监听到服务器启动就去加载配置文件
③ 直接在Action中获取工厂
AOP
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。
利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
在传统的开发中存在一些问题:
假设有两个类都有相应的保存功能
但是现在需求变了,在保存前都要进行一次权限校验,所以要去添加权限校验的方法
但是这样每个类都去改很麻烦,所以使用纵向继承的方式,把要加入的方法写的一个父类,让另外两个类去继承
但是这样还是要去修改源码,我们想要的是不去修改源码的基础上进行添加,那么就可以使用AOP,AOP会自动给我们生成代理类,在原来类的基础上进行增强,随时可以添加删除操作
内部原理JDK动态代理
(jdk动态代理要使用接口)
cglib动态代理(jdk动态代理必须要有接口才能使用,而cglib不需要)
Cglig是一个第三方开源代码 生成类库,动态添加类的属性和方法。在spring的核心包当中已经引入了cglib
使用的是继承的方式产生代理对象,产生并返回的就是子类
springAOP的相关术语
Joinpoint:连接点
可以被拦截到的方法,能够被增强的方法,这些方法就可以称为是连接点
Pointcut:切入点
真正被拦截的方法,真正被增加的方法
Advice:通知
增加的内容,通常都是封装成一个方法, 这个方法我们就称为通知
Introduction:引介
类层面的增加,给原有的类添加一些新的属性方法,在开发中通常都是给方法进行增加
Target:被增加的对象
Weaving:织入
将通知应用到目标对象的过程
Proxy:代理对象
Aspect:切面
多个通知和多个切入点的集合
springAOP的使用
- 引入spring的基本jar包
- 引入aop的基本jar包
- 配置文件中加入aop约束
<?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:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop.xsd">
</beans>
- 编写类和切面类并且 交给spring管理,切面类就是把要新加入的方法写到一个类里
- 配置AOP完成对目标产生代理
这样在源代码没有改的情况下值改了配置文件就加入了新功能
AOP通知类型
前置通知:
在目标方法执行之前进行操作
后置通知:
在目标方法执行之后 进行操作
并且这个后置通知还可以获取到之前执行的方法的返回值,使用returning
环绕通知:
在目标方法执行之前 和之后进行操作
异常抛出通知:
在程序出现异常时进行操作
最终通知:
无论代码是否有异常,都会执行
切入点表达式
注解的形式
- 编写切面类并且注入
- 在配置文件开启注解
- 在切面类上添加注解
@Before前置通知
@AfterReturning后置通知
@Around环绕通知
@AfterThrowing异常抛出通知
@After最终通知
来源:CSDN
作者:今天又学java了
链接:https://blog.csdn.net/weixin_43907800/article/details/103746912