Spring入门学习

文章目录

  • IOC本质
  • IOC创建对象方式
    • 构造器参数实现
  • Spring配置
    • 别名
    • bean的配置【重点】
    • import
  • 依赖注入
    • 构造器注入
    • 通过set方式注入【重点】
    • 扩展方式
      • p命名空间注入
      • c命名空间注入
  • bean的作用域
  • bean自动装配
    • 使用注解实现自动装配
  • 使用注解开发
    • xml与注解的关系
  • 使用Java的方式配置Spring
  • 代理模式
    • 静态代理
    • 动态代理
      • 好处
  • Spring实现AOP
  • 整合mybatis
  • 事务

bilibili狂神说笔记

IOC本质

  • 控制反转loC(Inversion of Control),是一种设计思想,Dl(依赖注入)是实现loC的一种方法,也有人认为DI只是loC的另一种说法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
  • 采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
  • 控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是loC容器,其实现方法是依赖注入(Dependency Injection,Dl)。

IOC创建对象方式

无参构造创建对象,默认!
如果有有参构造,则不能用默认的无参,只能用有参的方法:

构造器参数实现

  • 下标赋值
  • 通过类型创建(不建议使用)
  • 直接通过参数名设置
    在这里插入图片描述
    在配置文件加载的时候,容器中的对象就已经初始化了,不必等到getBean才会初始。且容器中的对象唯一实例

Spring配置

别名

alias

<!--添加了别名,我们可以通过别名来取到这个对象-->
<alias name="user" alias="userNew"/>

bean的配置【重点】

<!--
id:bean的唯一标识符,相当于对象名
class:bean对象所对应的全限定名:包名+类型
name:也是别名,而且name可以同时取多个别名
-->
<bean id="user" class="com.spring.User" name="user2 u2,u3;u4"><property name="name" value="aaa"/>
</bean>

import

用于团队开发, 在application.xml文件中通过import导入多个bean.xml(不同人可能创建不同的bean)。最后使用的时候,直接使用总的xml文件(application.xml

<import resource="bean.xml" />
<import resource="bean2.xml" />
<import resource="bean3.xml" />

依赖注入

构造器注入

通过set方式注入【重点】

  • 依赖:bean对象的创建依赖于容器
  • 注入:bean对象中的所有属性,由容器来注入
<!--引用注入-->
<bean id="address" class="com.spring.Address"/>
<bean id="student" class="com.spring.Student"><!--第一种,普通值注入,value--><property name="name" value="xxx"/><!--第二种,bean注入,ref--><property name="address" ref="address"/><!--第三种,数组注入><property name="books"><array><value>abc</value><value>abc2</value><value>abc3</value></array></property><!--第四种,list注入><property name="hobbys"><list><value>abc</value><value>abc2</value><value>abc3</value></list></property><!--第五种map注入><property name="card"><map><entry key="aa" value="11111"/><entry key="aa" value="11111"/><entry key="aa" value="11111"/></map></property><!--第六种set注入><property name="games"><set><value>abc</value><value>abc2</value><value>abc3</value></set></property><!--第七种null注入><property name="wife"><null/></property><!--第八种properties注入><property name="info"><props><prop key="driver">11111</prop><prop key="url">11111</prop><prop key="username">11111</prop><prop key="password">11111</prop></props></property>
</bean>

扩展方式

p命名空间注入

<!--p命名空间注入,可以直接注入属性的值:property,但是依赖于第三方的配置
xmlns:p="http://www.springframework.org/schema/p"-->
<bean id="user" class="" p:name="xxx" p:age="18>

c命名空间注入

<!--c命名空间注入,通过构造器注入:construct-args,但是依赖于第三方的配置
xmlns:c="http://www.springframework.org/schema/c"-->
<bean id="user" class="" c:name="xxx" c:age="18>

p命名和c命名不能直接使用,需要导入约束

<!--
xmlns:c="http://www.springframework.org/schema/c"
xmlns:p="http://www.springframework.org/schema/p"
-->

bean的作用域

  • 单例模式(spring默认机制)
<bean id="user" class="" scope="singleton"/>
  • 原型模式:每次从容器中get的时候,都会产生一个新的对象
<bean id="user" class="" scope="prototype"/>
  • 其余的request、session、application这些只能在web开发中使用到

bean自动装配

  • 自动装配是Spring满足bean依赖一种方式!
  • Spring会在上下文中自动寻找,并自动给bean装配属性!

原本:

<bean id="address" class="com.spring.Address"/>
<bean id="teacher" class="com.spring.Teacher"/>
<bean id="student" class="com.spring.Student"><property name="name" ref="teacher"/><property name="address" ref="address"/>
</bean>

自动注入后:

<bean id="address" class="com.spring.Address"/>
<bean id="teacher" class="com.spring.Teacher"/>
<bean id="student" class="com.spring.Student" autowire="byName">
</bean>
autowire="byName/byType"
byName:会自动在让其上下文查找,和自己对象set方法后面的值对应的bean id。
byType:会自动在让其上下文查找,和自己对象属性类型相同的bean。(必须保证类型全局唯一)
  • byName:需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法一致。
  • byType:需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致。

在Spring中有三种装配的方式

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配bean【重要】

使用注解实现自动装配

  • 导入约束:context约束
  • 开启注解的支持 <context:annotation-config/>
<context:annotation-config/>
<bean id="address" class="com.spring.Address"/>
<bean id="teacher" class="com.spring.Teacher"/>
<bean id="student" class="com.spring.Student"/>
<!--在address和teacher,student属性上面添加@Autowired注解-->

@Autowired

  • 直接在属性上使用即可,也可在set方式上使用
  • 使用Autowired我们可以不用set方法了,前提是这个自动装配的属性在IOC容器中存在,且符合名字byName(通过byType方式实现,且必须这个对象存在)。
  • @Nullable 属性:字段标记了这个注解,说明该字段可以为null
  • required :默认为true,如果为false,说明这个对象可以为null
  • @Qualifier:可以使用@Qualifier(value=“xxx”)配合@Autowired使用,指定一个唯一的bean对象注入

@Resource注解

  • 放在属性字段上,默认通过byName的方式实现,如果找不到名字,则通过byType方式实现,如果两个都找不到就报错。

两者区别

@Autowired和@Resource的区别

使用注解开发

  • 要使用注解开发,必须保证aop的包导入了
  • 要开启注解支持
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.spring.dao">
<context:annotation-config/>

@Component:组件,说明该类被Spring管理了
衍生注解:dao 【@Repository】、service【@Service】、controller【@Controller】 都是代表将某个类注册到Spring中,装备Bean

xml与注解的关系

  • xml更加万能,适用于任何场合,维护简单方便
  • 注解不是自己的类使用不了,维护相对复杂
  • xml用来管理bean
  • 注解只负责完成属性的注入
  • 我们在使用过程中要注意,必须让注解生效,要开启注解支持

使用Java的方式配置Spring

不使用Spring的xml配置。
@Configuration:也会被Spring容器托管,注册到容器中,因为她本来就是一个@Component,@Configuration代表这是一个配置类
@Bean:相当于我们之前写的一个bean标签,该方法的名字相当于bean标签中的id,返回值相当于bean标签中的class属性

代理模式

  • 静态代理
  • 动态代理

静态代理

  • 抽象角色:一般会使用接口或抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人

代理模式的好处:

  • 可以是真实角色的操作更加纯粹,不用去关注一些公共的业务
  • 公共业务就交给代理角色,实现了业务的分工
  • 公共业务发生扩展的时候,方便集中管理

缺点:

  • 一个真实角色就会产生一个代理角色,代码量会翻倍,开发效率会变低

为什么添加代理类而不是在原有的类上改变:

  • 改动原有的业务代码,是公司的大忌

动态代理

  • 动态代理和静态代理角色一样
  • 动态代理的代理类是动态生成的,不是我们直接写好的
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口的代理:JDK动态代理
    • 基于类:cglib
    • java字节码实现:javasist
  • 一个动态代理类代理的是一个接口,就是一类业务
    动态代理的本质都是使用反射机制实现
    就是自己不写那个方法,
    了解ProxyInvocationHandler
    在这里插入图片描述

好处

动态代理的好处:

  • 可以使真实角色的操作更加纯粹!
  • 不用去关注一些公共的业务·公共也就就交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务。
  • 一个动态代理类可以代理多个类,只要是实现了同一个接口即可!

Spring实现AOP

方法一:使用Spring的API接口
spring里面有aop的包,里面有对应的方法,然后注册bean,配置aop
在这里插入图片描述
方法二:使用自定义来实现AOP【切面定义】
在这里插入图片描述
方法三:注解
用注解@Aspect标注这是一个切面
在这里插入图片描述

整合mybatis

在这里插入图片描述

事务

在这里插入图片描述

在这里插入图片描述