《拉勾Java高薪课程》阶段一输出 之 IoC容器设计实现及Spring源码分析 - 学习笔记 --菜鸟小回

阶段一模块二学习笔记-Spring高级框架


专栏地址:拉勾专栏(持续更新…)


一、自定义Ioc&AOP框架

1. spring概述

  • Spring 简介:Spring 是分层的 full-stack(全栈) 轻量级开源框架,以 IoC 和 AOP 为内核,提供了展现层 SpringMVC 和业务层事务管理等众多的企业级应⽤技术,还能整合开源世界众多著名的第三⽅框架和类库,已经成为使⽤最多的 Java EE 企业应⽤开源框架。
  • Spring 的优势
    • ⽅便解耦,简化开发
    • AOP编程的⽀持
    • 声明式事务的⽀持
    • ⽅便程序的测试
    • ⽅便集成各种优秀框架
    • 降低JavaEE API的使⽤难度
    • 源码是经典的 Java 学习范例

2. 核心思想

2.1 Ioc

  • 什么是IOC: IoC Inversion of Control (控制反转/反转控制),注意它是⼀个技术思想,不是⼀个技术实现
    描述的事情:Java开发领域对象的创建,管理的问题
    传统开发⽅式:⽐如类A依赖于类B,往往会在类A中new⼀个B的对象
    IoC思想下开发⽅式:我们不⽤⾃⼰去new对象了,⽽是由IoC容器(Spring框架)去帮助我们实例化对
    象并且管理它,我们需要使⽤哪个对象,去问IoC容器要即可
    enter description here
  • IOC的作用
    IoC解决对象之间的耦合问题
    enter description here
  • IOC和DI的区别
    IOC和DI描述的是同一件事情(对象实例化及依赖关系维护这件事情),只不过角度不同罢了
    IOC是站在对象的角度:对象实例化及其管理的权利交给了(反转)给了容器
    DI是站在容器的角度:容器会把对象依赖的其他对象注入(送进去),比如A对象实例化过程中因为声明了一个B类型的属性,那么就需要容器把B对象注入给A

2.2 AOP

  • 先了解OOP
    OOP三⼤特征:封装、继承和多态
    oop是⼀种垂直继承体系
    enter description here
  • OOP问题:
    OOP编程思想可以解决⼤多数的代码重复问题,但是有⼀些情况是处理不了的,⽐如下⾯的在顶级⽗类
    Animal中的多个⽅法中相同位置出现了重复代码,OOP就解决不了,如图的横切逻辑
    enter description here
    enter description here
    • 横切代码重复问题
    • 横切逻辑代码和业务代码混杂在⼀起,代码臃肿,维护不⽅便

3.手写IOC和AOP

  • 提到工厂模式和单例模式
  • 工厂模式:从自己手动创建对象,到自己只传递想要的参数给工厂,由工厂创建对象。
  • 单例模式,应用在全局只有一个实例对象时,将自身实例化并赋值给一个属性,加载到此类时直接调用其静态实例。分为懒汉和饿汉式
    • 饿汉:enter description here
    • 懒汉:enter description here
  • 代理模式:实现对方法的前后增强,相当于委托给代理实现想要的功能,代理可以在实现功能的前后实现自己的需求。
    • jdk动态代理(需要委托对象实现接口):enter description here
    • 使用:enter description here

3.1银行转账的工厂模式实现

工厂模式生产,在xml中获取实现的全路径进行反射

  • 工厂:读取解析xml,通过反射技术实例化对象并且存储待用(map集合);对外提供获取实例对象的接口(根据id获取)
    enter description here
  • 存放需要实例化的对象全路径
    enter description here
  • 使用工厂中的方法并传入相应参数
    enter description here
  • 源码:git clone -b master1 https://gitee.com/idse666666/my_spring.git
  • 存在问题:仍需要从工厂获取bean
  • 解决:enter description here
    enter description here
  • 源码:git clone -b master2 https://gitee.com/idse666666/my_spring.git

3.2事务控制

  • 如图:如果不对service层进行事务控制,将会存在前者转账,后者接收不到的问题。
    enter description here
  • 而现有的事务控制是对于每一个数据库连接,我们需要将数据库连接存放到线程中,单个线程只有一个数据库连接,也就是单例模式。
    enter description here
  • 经过以上事务控制的拦截,我们捕获存在异常则回滚事务。保证了数据正确。
    enter description here
  • 源码:git clone -b master3 https://gitee.com/idse666666/my_spring.git
  • 仍存在问题:我们的每个方法都需要添加开启事务,提交事务,回滚以及try…catch…代码块。应使用代理模式在方法的前后进行增强,将固定的try…catch…代码块提取至jdk动态代理里。
    enter description here
    enter description here
    • 源码:git clone -b master4 https://gitee.com/idse666666/my_spring.git

3.3将所有用到的工具类等以bean形式封装到xml中。

enter description here

  • 源码:git clone -b master5 https://gitee.com/idse666666/my_spring.git

3.4 手写IOC与AOP示意图

enter description here

二、 spring IOC应用

enter description here

1. BeanFactory与ApplicationContext区别

  • BeanFactory是Spring框架中IoC容器的顶层接⼝,它只是⽤来定义⼀些基础功能,定义⼀些基础规范,⽽ApplicationContext是它的⼀个⼦接⼝,所以ApplicationContext是具备BeanFactory提供的全部功能的。我们称BeanFactory为SpringIOC的基础容器,ApplicationContext是容器的⾼级接⼝,比BeanFactory要拥有更多的功能

2. 启动IOC的方式

2.1 Java环境下
  • ClassPathXmlApplicationContext 从类的根路径下加载配置⽂件(推荐使⽤)
  • AnnotationConfigApplicationContext 纯注解模式下启动Spring容器
2.2 Web环境下启动IoC容器
  • Web环境下启动IoC容器
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
 <display-name>Archetype Created Web Application</display-name>
 <!--配置Spring ioc容器的配置文件-->
 <context-param>
   <param-name>contextConfigLocation</param-name>
   <param-value>classpath:applicationContext.xml</param-value>
 </context-param>
 <!--使用监听器启动Spring的IOC容器-->
 <listener>
   <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>
</web-app>

3. 使用spring ioc xml形式注入Bean改造手写的ioc和aop

3.1 常见的bean标签:
  • id属性: ⽤于给bean提供⼀个唯⼀标识。在⼀个标签内部,标识必须唯⼀。
  • class属性:⽤于指定创建Bean对象的全限定类名。
  • name属性:⽤于给bean提供⼀个或多个名称。多个名称⽤空格分隔。
  • factory-bean属性:⽤于指定创建当前bean对象的⼯⼚bean的唯⼀标识。当指定了此属性之后,class属性失效。
  • factory-method属性:⽤于指定创建当前bean对象的⼯⼚⽅法,如配合factory-bean属性使⽤,则class属性失效。如配合class属性使⽤,则⽅法必须是static的。
  • scope属性:⽤于指定bean对象的作⽤范围。通常情况下就是singleton。当要⽤到多例模式时,可以配置为prototype。
  • init-method属性:⽤于指定bean对象的初始化⽅法,此⽅法会在bean对象装配后调⽤。必须是⼀个⽆参⽅法。
  • destory-method属性:⽤于指定bean对象的销毁⽅法,此⽅法会在bean对象销毁前执⾏。它只能为scope是singleton时起作⽤。
3.2 实例化bean的几种方式
<!--Spring ioc 实例化Bean的三种方式-->
<!--方式一:使用无参构造器(推荐)-->
<bean id="connectionUtils" class="com.lagou.edu.utils.ConnectionUtils"></bean>
<!--另外两种方式是为了我们自己new的对象加入到SpringIOC容器管理-->
<!--方式二:静态方法-->
<bean id="connectionUtils" class="com.lagou.edu.factory.CreateBeanFactory" factory-method="getInstanceStatic"/>
<!--方式三:实例化方法-->
<bean id="createBeanFactory" class="com.lagou.edu.factory.CreateBeanFactory"></bean>
<bean id="connectionUtils" factory-bean="createBeanFactory" factory-method="getInstance"/>
3.3 DI依赖注入
<property name="ConnectionUtils" ref="connectionUtils"/>
<property name="name" value="zhangsan"/>
<property name="sex" value="1"/>
<property name="money" value="100.3"/>--> 
  • 源码:git clone -b master6 https://gitee.com/idse666666/my_spring.git

4. xml与注解相结合模式

4.1注意事项
  • 实际企业开发中,纯xml模式使⽤已经很少了
  • 引⼊注解功能,不需要引⼊额外的jar
  • xml+注解结合模式,xml⽂件依然存在,所以,spring IOC容器的启动仍然从加载xml开始
4.2xml中标签与注解的对应(IoC)

enter description here
DI 依赖注⼊的注解实现⽅式:@Autowired(推荐使⽤)
enter description here

  • 源码:git clone -b master7 https://gitee.com/idse666666/my_spring.git

5.全注解形式

5.1常用注解

@Configuration 注解,表名当前类是⼀个配置类
@ComponentScan 注解,替代 context:component-scan
@PropertySource,引⼊外部属性配置⽂件
@Import 引⼊其他配置类
@Value 对变量赋值,可以直接赋值,也可以使⽤ ${} 读取资源配置⽂件中的信息
@Bean 将⽅法返回对象加⼊ SpringIOC 容器

5.2 具体迁移所对应形式

enter description here

  • 源码:git clone -b master8 https://gitee.com/idse666666/my_spring.git

6. 延迟加载

6.1概念

ApplicationContext 容器的默认⾏为是在启动服务器时将所有 singleton bean 提前进⾏实例化。提前
实例化意味着作为初始化过程的⼀部分,ApplicationContext 实例会创建并配置所有的singleton
bean。

6.2使用
//xml
//单个
<bean id="testBean" calss="cn.lagou.LazyBean" lazy-init="true" />
//全部
<beans default-lazy-init="true"></beans>
6.3 使用场景
  • 开启延迟加载⼀定程度提⾼容器启动和运转性能
  • 对于不常使⽤的 Bean 设置延迟加载,这样偶尔使⽤的时候再加载,不必要从⼀开始该 Bean 就占⽤资源

7. FactoryBean 和 BeanFactory

7.1概念
  • BeanFactory接⼝是容器的顶级接⼝,定义了容器的⼀些基础⾏为,负责⽣产和管理Bean的⼀个⼯⼚,具体使⽤它下⾯的⼦接⼝类型,⽐如ApplicationContext;此处我们重点分析FactoryBean
  • Spring中Bean有两种,⼀种是普通Bean,⼀种是⼯⼚Bean(FactoryBean),FactoryBean可以⽣成某⼀个类型的Bean实例(返回给我们),也就是说我们可以借助于它⾃定义Bean的创建过程。
  • Bean创建的三种⽅式中的静态⽅法和实例化⽅法和FactoryBean作⽤类似,FactoryBean使⽤较多,尤其在Spring框架⼀些组件中会使⽤,还有其他框架和Spring框架整合时使⽤
7.2 使用

enter description here
enter description here

二、 spring AOP应用

  • AOP的本质:在不改变原有业务逻辑的情况下增强横切逻辑,横切逻辑代码往往是权限校验代码、⽇志代码、事务控制代码、性能监控代码。
  • 1

1. AOP相关术语

  • 连接点:⽅法开始时、结束时、正常运⾏完毕时、⽅法异常时等这些特殊的时机点,我们称之为连接 点,项⽬中每个⽅法都有连接点,连接点是⼀种候选点
  • 切⼊点:指定AOP思想想要影响的具体⽅法是哪些,描述感兴趣的⽅法 Advice增强:
    • 第⼀个层次:指的是横切逻辑
    • 第⼆个层次:⽅位点(在某⼀些连接点上加⼊横切逻辑,那么这些连接点就叫做⽅位点,描述的是具体 的特殊时机)
  • Aspect切⾯:切⾯概念是对上述概念的⼀个综合 Aspect切⾯= 切⼊点+增强= 切⼊点(锁定⽅法) + ⽅位点(锁定⽅法中的特殊时机)+ 横切逻辑 众多的概念,⽬的就是为了锁定要在哪个地⽅插⼊什么横切逻辑代码

2.Spring中AOP的代理选择

  • Spring 实现AOP思想使⽤的是动态代理技术
  • 默认情况下,Spring会根据被代理对象是否实现接⼝来选择使⽤JDK还是CGLIB。当被代理对象没有实现任何接⼝时,Spring会选择CGLIB。当被代理对象实现了接⼝,Spring会选择JDK官⽅的代理技术,不过我们可以通过配置的⽅式,让Spring强制使⽤CGLIB。

3. AOP的xml实现

    <!--aop注解模式-->
    <!--aspect   =    切入点(锁定方法) + 方位点(锁定方法中的特殊时机)+ 横切逻辑-->
    <aop:config>
        <!--横切逻辑类名-->
        <aop:aspect id="lagAspect" ref="logUtils">
            <!--切入点:切入我们感兴趣的方法,使用aspectj表达式-->
            <aop:pointcut id="pt1" expression="execution(public void com.lagou.edu.service.impl.TransferServiceImpl.transfer(java.lang.String , java.lang.String , int ))"/>

            <!--aop:before方位点-->
			<!--method具体横切逻辑-->
            <!--aop:before前置通知/增强-->
            <!--<aop:before method="beforeMethod" pointcut-ref="pt1"/>-->
            <!--aop:after,最终通知,无论如何都执行-->
            <!--aop:after-returnning,正常执行通知-->
            <!--<aop:after-returning method="successMethod" returning="retValue"/>-->
            <!--aop:after-throwing,异常通知-->
            <aop:around method="arroundMethod" pointcut-ref="pt1"/>
        </aop:aspect>
    </aop:config>

enter description here

  • 源码:git clone -b master9 https://gitee.com/idse666666/my_spring.git

4.AOP的xml+anno形式实现

enter description here

  • 源码:git clone -b master10 https://gitee.com/idse666666/my_spring.git

5. AOP的anno模式实现

enter description here

  • 源码:git clone -b master11 https://gitee.com/idse666666/my_spring.git

6. 声明式事务的⽀持

6.1概念

事务指逻辑上的⼀组操作,组成这组操作的各个单元,要么全部成功,要么全部不成功。从⽽确保了数据的准确与安全。又分为

  • 编程式事务:在业务代码中添加事务控制代码,这样的事务控制机制就叫做编程式事务
  • 声明式事务:通过xml或者注解配置的⽅式达到事务控制的⽬的,叫做声明式事务
6.2事务的四大特性
  • 原⼦性(Atomicity) 原⼦性是指事务是⼀个不可分割的⼯作单位,事务中的操作要么都发⽣,要么都不发⽣。从操作的⻆度来描述,事务中的各个操作要么都成功要么都失败
  • ⼀致性(Consistency) 事务必须使数据库从⼀个⼀致性状态变换到另外⼀个⼀致性状态。⼀致性是从数据的⻆度来说的,
  • 隔离性(Isolation) 事务的隔离性是多个⽤户并发访问数据库时,数据库为每⼀个⽤户开启的事务,每个事务不能被其他事务的操作数据所⼲扰,多个并发事务之间要相互隔离。
  • 持久性(Durability) 持久性是指⼀个事务⼀旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发⽣故障也不应该对其有任何影响。

三、 事务

1 事务的隔离级别

不考虑隔离级别会出现:

  • 脏读:⼀个线程中的事务读到了另外⼀个线程中未提交的数据。
  • 不可重复读:⼀个线程中的事务读到了另外⼀个线程中已经提交的update的数据(前后内容不⼀样)
  • 虚读(幻读):⼀个线程中的事务读到了另外⼀个线程中已经提交的insert或者delete的数据(前后条数不⼀样)
    四种隔离级别
  • Serializable(串⾏化):可避免脏读、不可重复读、虚读情况的发⽣。(串⾏化)
  • Repeatable read(可重复读):可避免脏读、不可重复读情况的发⽣。(幻读有可能发⽣) 该机制下会对要update的⾏进⾏加锁
  • Read committed(读已提交):可避免脏读情况发⽣。不可重复读和幻读⼀定会发⽣。
  • Read uncommitted(读未提交):最低级别,以上情况均⽆法保证。(读未提交)
    注意:级别依次升⾼,效率依次降低

2.事务的传播性

  • 事务往往在service层进⾏控制,如果出现service层⽅法A调⽤了另外⼀个service层⽅法B,A和B⽅法本身都已经被添加了事务控制,那么A调⽤B的时候,就需要进⾏事务的⼀些协商,这就叫做事务的传播⾏为。A调⽤B,我们站在B的⻆度来观察来定义事务的传播⾏为
    enter description here

3. spring xml实现事务

<!--spring声明式事务配置,声明式事务无非就是配置一个aop,只不过有些标签不一样罢了-->
<!--横切逻辑-->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<constructor-arg name="dataSource" ref="dataSource"></constructor-arg>
</bean>

<tx:advice id="txAdvice" transaction-manager="transactionManager">
	<!--定制事务细节,传播行为、隔离级别等-->
	<tx:attributes>
		<!--一般性配置-->
		<tx:method name="*" read-only="false" propagation="REQUIRED" isolation="DEFAULT" timeout="-1"/>
		<!--针对查询的覆盖性配置-->
		<tx:method name="query*" read-only="true" propagation="SUPPORTS"/>
	</tx:attributes>
</tx:advice>
<aop:config>
	<!--advice-ref指向增强=横切逻辑+方位&-->
	<aop:advisor advice-ref="txAdvice" pointcut="execution(* com.lagou.edu.service.impl.TransferServiceImpl.*(..))"/>
</aop:config>

4. spring xml+anno实现事务

//xml
<!--声明式事务的注解驱动-->
<tx:annotation-driven transaction-manager="transactionManager"/>
//anno
@Transactional

5. 纯注解

@EnableTransactionManagement
@Transactional
  • 源码:git clone -b master12 https://gitee.com/idse666666/my_spring.git
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值