Spring学习总结

你确定真的了解 Java 四种引用(强引用、弱引用、软引用、虚引用)了吗?
SpringBoot四种读取properties文件的方式
@PropertySource
springboot读取自定义properties配置文件方法
spring-boot-configuration-processor 是干啥用的

IOC反转控制

ioc 反转控制 就是将我们创建对象的方式反转了 以前对象的创建时由开发人员自己维护 包括依赖关系也是自己注入 学习spring之后 对象的创建以及依赖关系可以由spring完成创建和注入 反转控制也就是反转了对象的创建方式 从人们自己到由spring自己进行

Spring学习总结_第1张图片

Spring学习总结_第2张图片

Spring学习总结_第3张图片

//获得容器
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//从容器中获取对象
IService service = (IService) ac.getBean("service");

Bean可以获取实例化对象
Spring学习总结_第4张图片

Spring学习总结_第5张图片

DI依赖注入

di 比IOC概念要小一些 Dependency Injection 依赖注入
实现IOC思想 DI做支持。

Spring学习总结_第6张图片

设置注入

Spring学习总结_第7张图片

<bean id="hello" class="com.neu.service.HelloSpring">
        <property name="who">
            <value>Springvalue>
        property>
bean>

构造注入

Spring学习总结_第8张图片

<bean id="mySchool" class="com.neu.service.School">
        <constructor-arg name="name" value="肇庆学院"/>
bean>

注意:要保证赋值顺序要与构造器中的参数顺序一致。

集合属性注入

Spring学习总结_第9张图片

Spring学习总结_第10张图片

Spring学习总结_第11张图片

Spring学习总结_第12张图片

对于域属性的自动注入

Spring学习总结_第13张图片

Spring学习总结_第14张图片

为多个应用指定 Spring 配置文件

在实际应用里,随着应用规模的增加,系统 Bean 数量也大量增加,导致配置文件变得
非常庞大、臃肿。为了避免这种情况的产生,提高配置文件的可读性与可维护性,可
以将 Spring 配置文件分解成多个配置文件。
1)平等关系的配置文件

Spring学习总结_第15张图片

2)包含关系的配置文件
各配置文件中有一个总文件,总配置文件将各其它子文件通过引入,在 java 代
码中只需要使用总配置文件对容器进行初始化即可。

Spring学习总结_第16张图片

基于注解的依赖注入

Spring学习总结_第17张图片

以下注解作用是,对应以前xml编写bean时的id(类名首字母小写)和class(类的全限定名):

  1. @Component("") 用在哪个类都可以
  2. @Repository("") 用于对DAO实现类进行注解
  3. @Service("") 用于对Service实现类进行注解
  4. @Controller("") 用于对Controller实现类进行注解

注:2,3,4与1等效是为了以后对其精心功能上的扩展使它们不再等效。

使用内置服务器启动springboot项目时,会从@SpringBootApplication修饰类所在的包开始,加载当前包和所有子包下的类,将由
@Component 、@Repository、@Service、@Controller修饰的类交由spring进行管理。
Spring学习总结_第18张图片

bean的作用域@Scope(“prototype”)

①、singleton:单例模式,在整个 Spring 容器中,使用 singleton 定义的 Bean 将是单例的,只有一个实例,默认为单例。
②、prototype:原型模式,即每次使用 getBean 方法获取的同一个的实例都一个新的实例。
③、request:对于每次 Http 请求,都会产生一个不同的 Bean 实例,表示在一次http请求内有效(只适用于web应用)。
④、session:对于每个不同的 http session,都会产生一个不同的 bean 的实例,表示在一个用户会话内有效(只适用于web应用)。
⑤、globalSession表示在全局会话内有效(只适用于web应用)。
注意:
1)对于 scope 的值 request、session 与globalSession,只有在 web 应用中使用Spring 时,才起作用。
2)对于 singleton,该 bean 是在容器被创建时即被装配好了。
3)对于prototype,bean 实例是在代码中使用该 bean 实例时才进行装配,也就是懒加载。
Spring学习总结_第19张图片

基本类型属性注入@Value("")

需要在属性上使用注解@Value,该注解的 value 属性用于指定要注入的值。
**使用该注解完成属性注入时,类中无需 setter()方法。
Spring学习总结_第20张图片

域属性注入@Autowired和@Resource

@Autowired与@Resource都可以用来装配bean. 都可以写在字段上,或写在setter()方法上。

Spring中@Resource与@Autowired、@Qualifier的用法与区别

域属性注入@Autowired

默认是按照类型装配注入的,如果想按照名称来装配注入,则需要结合@Qualifier一起使用;
注意:
按照类型装配注入有一种出错的情况,如果这个类有多个实现类,那么spring就不知道找那个类了。
上述的情况就必须结合@Qualifier一起用了。
如果@Autowired和@Qualifier同时用了,那么会先按类型装配,找不到才按名称装配
这个注解是属于spring的,
默认情况下必须要求依赖对象必须存在,不然直接报错,如果要允许null 值,可以设置它的required属性为false,
如:@Autowired(required=false)

按类型注入域属性(ByType)

Spring学习总结_第21张图片
Spring学习总结_第22张图片

按名称注入域属性(ByName)用这个灵活

Spring学习总结_第23张图片

域属性注解@Resource(name="")

@Resource默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来装配注入,
名称可以通过name属性进行指定。
这个注解属于J2EE的,Sping 只是提供了 JSR-250 规范中定义@Resource 标准注解的支持。
如果没有指定name属性,当注解写在字段上时,默认取字段名进行按照名称查找,如果注解写在setter方法上默认取属性名进行装配。
当找不到与名称匹配的bean时才按照类型进行装配。
但是需要注意的是,name属性一旦指定,就只会按照名称进行装配。

1)按类型注入域属性

Spring学习总结_第24张图片

2)按名称注入域属性

Spring学习总结_第25张图片

其他Spring注解,这是在单元测试时用的

  • ssm项目
    • @RunWith(SpringJUnit4ClassRunner.class):用于指定运行环境
    • @ContextConfiguration(locations = “classpath:ApplicationContext.xml”):用于指定配置文件位置
  • springboot项目
    • @RunWith(SpringRunner.class)
    • @SpringBootTest

面向切面编程AOP

Spring AOP动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

spring-aop原理讲解 JDK动态代理和CGLIB动态代理
摘抄:
Spring AOP动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

  1. JDK动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK动态代理的核心是InvocationHandler接口和
    Proxy 类。
  2. 如果目标类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码
    生成的类库,可以在运行时动态的生成某个类的子类(通过修改字节码来实现代理)。
    注意,CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
    jdk和cglib动态代理是共同用来实现我们的aop面向切面的功能。

AOP 就是纵向的编程,如业务 1 和业务 2 都需要一个共同的操作,与其往每个业务中
都添加同样的代码,不如写一遍代码,让两个业务共同使用这段代码。在日常有订单管
理、商品管理、资金管理、库存管理等业务,都会需要到类似日志记录、事务控制、权限
控制、性能统计、异常处理及事务处理等。AOP 把所有共有代码全部抽取出来,放置到某
个地方集中管理,然后在具体运行时,再由容器动态织入这些共有代码。

AOP实现的底层原理

只有发生在运行期,则可直接通过 Java 语言的反射机制与动态代理机制来动态实现。

AOP 涉及名称:

  • **切面(Aspect):**其实就是共有功能的实现。如日志切面、权限切面、事务切面等。在
    实际应用中通常是一个存放共有功能实现的普通 Java 类,之所以能被 AOP 容器识别成切
    面,是在配置中指定的。
  • 通知(Advice):是切面的具体实现。以目标方法为参照点,根据放置的地方不同,可
    分为前置通知(Before)、后置通知(AfterReturning)、异常通知(AfterThrowing)、最终通知(After)与环绕通知(Around)5 种。在实际应用中通常是切面类中的一个方法,具体属于哪类通知,同样是在配置中指定的。
  • 顾问(Advisor):顾问是切面的另一种实现,能够将通知以更为复杂的方式织入到目标对象中,是将通知包装为更复杂切面的装配器。
  • 连接点(Joinpoint):就是程序在运行过程中能够插入切面的地点。例如,方法调用、异常抛出或字段修改等,但 Spring 只支持方法级的连接点。(环绕通知有这个参数)
  • 切入点(Pointcut):用于定义通知应该切入到哪些连接点上。不同的通知通常需要切入到不同的连接点上,这种精准的匹配是由切入点的正则表达式来定义的。
  • 目标对象(Target):就是那些即将切入切面的对象,也就是那些被通知的对象。这些
    对象中已经只剩下干干净净的核心业务逻辑代码了,所有的共有功能代码等待 AOP 容器
    的切入。
  • 代理对象(Proxy):将通知应用到目标对象之后被动态创建的对象。可以简单地理解
    为,代理对象的功能等于目标对象的核心业务逻辑功能加上共有功能。代理对象对于使用
    者而言是透明的,是程序运行过程中的产物。
  • **织入(Weaving):**将切面应用到目标对象从而创建一个新的代理对象的过程。这个过
    程可以发生在编译期、类装载期及运行期,当然不同的发生点有着不同的前提条件。譬如
    发生在编译期的话,就要求有一个支持这种 AOP 实现的特殊编译器;发生在类装载期,
    就要求有一个支持 AOP 实现的特殊类装载器;只有发生在运行期,则可直接通过 Java 语言
    的反射机制与动态代理机制来动态实现。

Spring学习总结_第26张图片

通知详解(实现原理)

Spring学习总结_第27张图片

Spring学习总结_第28张图片

前置通知MethodBeforeAdvice

定义前置通知,需要实现 MethodBeforeAdvice 接口,访接口中有一个方法 before(),在目
标方法执行之前执行,前置通知的特点:
(1)在目标方法执行之前先执行
(2)不改变目标方法的执行流程,前置通知代码不能阻止目标方法执行
(3)不改变目标方法执行的结果

后置通知AfterReturningAdvice

定义后置通知,需要实现接口 AfterReturningAdvice,该接口中有一个方法 afterReturning()
会在目标方法执行之后执行。后置通知的特点:
(1)在目标方法执行后执行
(2)不改变目标方法的执行流程,后置通知代码不能阻止目标方法执行
(3)不改变目标方法执行的结果

环绕通知 MethodInterceptor

定义环绕通知,需要实现接口 MethodInterceptor,环绕通知,也叫方法拦截器,可以在目
标方法调用之前及之后做处处理,可以改变目标方法的返回值,也可以改变程序执行流
程。
注意:org.aopalliance.intercept.MethodInterceptor 才是需要的包。

异常通知 ThrowsAdvice

Spring学习总结_第29张图片

最终通知

其中最终通知是指无论程序执行是否正常,该通知都会执行。

AspectJ 对 AOP 的实现(可以用注解实现AOP了)

对于 AOP 这种编程思想,很多框架都进行了实现。Spring 就是其中之一。AspectJ 也实现了
AOP 的功能,且实现方式更为简捷,使用更为方便,而且还支持注解式开发。在 Spring 中
使用 AOP 开发时,一般使用 AspectJ 的实现方式。
1、AspectJ 简介
AspectJ 是一个面向切面的框架,它扩展了 Java 语言。AspectJ 定义了 AOP 语法,所以它有
一个专门的编译器用来生成遵守 Java 字节编码规范的 Class 文件。
2、AsectJ 的通知类型
常用的有五种类型:
1)前置通知
2)后置通知
3)环绕通知
4)异常通知
5)最终通知
其中最终通知是指无论程序执行是否正常,该通知都会执行。
3、AspectJ 的切入点表达式

Spring学习总结_第30张图片
4. AspectJ 基于注解的 AOP 实现
1)实现步骤
Step1:定义业务接口与实现类
Step2:定义切面 POJO 类
Step3:在切面类上添加**@Aspect** 注解,指定当前 POJO 类将作为切面
Step4:在 POJO 类的普通方法上添加通知注解
Step5:注册目标对象与 POJO 切面类
Step6:注册 AspectJ 的自动代理
Step7:测试类中使用目标对象的 id
2)@Before 前置通知-方法有 JoinPoint 参数
3)@AfterReturning 后置通知-注解有 retruning 属性
4)@Around 环绕通知-增加方法有 ProceeDingJoinPoint 参数
5)@AfterThrowing 异常通知-注解中有 throwing 属性
6)@After 最终通知
7)@Pointcut 定义切入点

execution()是最常用的切点函数,其语法如下所示:

整个表达式可以分为五个部分:
1、execution(): 表达式主体。
2、第一个*号:表示返回类型, 号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,
com.sample.service.impl 包、子孙包下所有类的方法。
4、第二个
号:表示类名,号表示所有的类。
5、
(…):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,
两个句点表示任何参数

Aop 标签是 AspectJ 框架使用的,而非 Spring 框架本身在实现 AOP 时使用。

AspectJ 对 AOP 的实现有两种方式
1)注解方式
号:表示返回类型, 号表示所有的类型。
3、包名:表示需要拦截的包名,后面的两个句点表示当前包和当前包的所有子包,
com.sample.service.impl 包、子孙包下所有类的方法。
4、第二个
号:表示类名,号表示所有的类。
5、
(…):最后这个星号表示方法名,*号表示所有的方法,后面括弧里面表示方法的参数,
两个句点表示任何参数

Aop 标签是 AspectJ 框架使用的,而非 Spring 框架本身在实现 AOP 时使用。

AspectJ 对 AOP 的实现有两种方式
1)注解方式
2)XML 方式

顺便讲一下JPA

这里顺便说一下JPA,以下的图是springDataJPA、JPA、hibernate的关系

Spring学习总结_第31张图片

以下是spring-data-jpa的运行原理

为什么它可以生成dao接口对应实现类?
就是因为它使用的设计模式中的代理模式,其中的动态代理。
它通过你的映射关系对DAO接口进行增强,自动生成了其实现类。
其实mybatis用的也是这个原理,不过它对代码操作的自由度高,也就是有一半映射你得自己写,写好关系mapper文件,再匹配你指定的dao接口,它才帮你做动态代理,这就是半ORM。

吐槽:其实感觉jpa还是挺厉害的,你说自由度嘛,其实也没比mybatis差多少,国外用的最多的就是JPA了,感觉国内太迷信mybatis了。
具体可看这个链接:设计模式—代理模式
spring-data-jpa的@Repository扫描原理
JDK动态代理实现原理
Java两种动态代理JDK动态代理和CGLIB动态代理
Spring学习总结_第32张图片
Spring学习总结_第33张图片
还有就是spring-data-jpa的代理类,已经写了@Repository注解了,所以jpa在给相应的dao做增强(也就是生成实现类)的时候,因为有@Repository的原因,所以就直接纳入spring管理了,就像普通的实现类一样。
Spring学习总结_第34张图片

Java class、Object、Class 的区别

Class的toString()方法。
Spring学习总结_第35张图片
Object在Class类之前,那是在编译期;Class能表示Object类,那是在JVM中。
Class只是一个用于描述Java类与接口的、用于支持反射操作的类型。

Java高级篇(四)——反射

Java基础之—反射(非常重要)
spring 中使用反射
Spring注入的反射解释

其他比较重要的注解:

  1. **@Deprecated:**若某接口、某类(抽象类也是)或某方法加上该注解之后,表示此接口、类(包括抽象类)、方法不再建议使用,调用时
    也会出现删除线,但并不代表不能用,只是说,不推荐使用,因为还有更好的方法可以调用。
  2. **@Transactional:**开启事务,推荐放service层,这才符合事务的逻辑。
  3. **@Configuration:**该注解是可以用来替代XML文件。以前我们配置bean时,都是写在applicationContext.xml(对spring的配置)
    文件中的。有了这个注解后,我们就可以编写一个类在其上面加上该注解。即配置类。
    在配置类中可以在方法上加@Bean注解定义其中的Bean。
    回忆如下两图:
    以前:
    Spring学习总结_第36张图片
    现在:Spring学习总结_第37张图片
    好吧,我知道你忘记了,下面让你再回忆一下,不用springboot时,以前你是怎么配置web应用的spring的。

tips:其实spring的配置文件和springMVC的配置文件起什么名字都可以的,因为,spring的web应用是基于servlet技术进行开发的,
而servlet技术又有核心配置文件web.xml(servlet是用它来方便web工程的开发的),
所以,这两个文件最终都是要写到web.xml去注册的,然后spring才开始运作起来的。

  • 首先,你会去编写spring容器的配置文件,一般名字叫applicationContext.xml,在里面你除了不对controller进行组件扫描
    (context:component-scan,context:exclude-filter),对dao和service都会进行组件扫描。
    【注意,以前配置jpa/hibernate和配置mybatis在dao和service的扫描时配置写法有点不一样的,因为前者是ORM框架、而后者是半
    ORM框架,但是配置上原理一样意思也一样】
  • 然后,你会去编写springMVC的配置文件,一般名字叫spring-mvc.xml,在里面你只对controller进行组件扫描
    (context:component-scan,context:include-filter,context:exclude-filter)
  • 最后,你得在web.xml注册这两个配置文件。
  1. **@Configurable :**现在假设,我们想在非Spring管理的类中使用依赖注入;
    比如:手动new出来的对象,正常情况下,Spring是无法依赖注入的,这个时候就可以使用@Configurable注解;

Spring注解中@Configuration和@Configurable的区别

  1. **@Lazy:**默认情况下,Spring会在应用程序上下文的启动时创建所有单例bean,也就是立即加载。
    这背后的原因很简单:立即避免和检测 所有可能的错误,而不是在运行时。
    但是,有些情况下我们需要创建一个bean,不是在应用程序上下文启动时,而是在我们请求时,
    这时就可以使用该注解,它默认是ture。

Spring系列——@lazy注解

  1. **@ComponentScan :**创建一个配置类,在配置类上添加 @ComponentScan 注解。该注解默认会扫描该类所在的包下所有的配置
    类,相当于之前的 context:component-scan。

Spring注解——使用@ComponentScan自动扫描组件

  1. @Primary: 优先方案,被注解的实现,优先被注入。

@Primary 和 @Qualifier

  1. @Import(xx.class): Spring中@Import注解的作用和使用

你可能感兴趣的:(spring)