Spring

  • IOC实现原理
  • 1.IOC概述:
  • 2.IOC的创建对象的方法
  • AOP实现原理
  • 1.AOP的概述:
  • 2.AOP的原理:
  • 3.AOP的实现:
  • 方式一:
  • 方式二:
  • 方式三:



今天聊一聊我自己对Spring的学习总结分析,Spring说白了就两个点:IOC 和 AOP


这两个点也是面试官最爱问的两个点,那么今天我就主要讲一下我对这两个点的理解

IOC实现原理

再说IOC之前,我先给大家看幅图:

spring从零开始学 spring应该怎么学_spring从零开始学


在没了解IOC之前,我们的程序都是这样的,用户需要去查看数据,找到业务层,业务层对应去帮用户找到用户想要查看的数据,而我们程序员则是控制着业务层。

那么作为一个程序员,当用户需求和我们的功能越来越多的时候,用户每次去查询不同的功能,我们对应就要修改代码,如果代码量过于庞大,修改一次的成本代价是很昂贵的!

spring从零开始学 spring应该怎么学_实现原理_02


而我们把主动权交给了用户以后,用户自己需要什么功能,由用户自己去调用

这样系统的耦合性大大降低,程序员可以更加专注的在业务的实现上!这就是IOC的原型!

1.IOC概述:

控制反转loC(Inversion ofControl),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是loC的另一种说法。没有loC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。

2.IOC的创建对象的方法

1.使用无参构造创建对象,默认!

2.假设我们要使用有参构造创建对象

  • 1.下标注入:
<bean id="user" class="com.zjd.pojo.User">
    <constructor-arg index="0" value="乔治"/>
</bean>
  • 2.类型赋值:
<!--    第二种:有参构造,类型赋值-->
<bean id="user" class="com.zjd.pojo.User">
   <constructor-arg type="java.lang.String" value="哈登"/>
</bean>
  • 3.直接通过参数名赋值
<bean id="user" class="com.zjd.pojo.User">
    <constructor-arg name="name" value="欧文"/>
</bean>

总结:

在配置文件加载的时候,容器中的管理对象就已经初始化了!

AOP实现原理

1.AOP的概述:

spring从零开始学 spring应该怎么学_spring从零开始学_03


大家看这幅图,如果我们一个已经完整的项目,突然想去加一些新功能,比如实现日志,那我们需要去重新破坏掉原有的结构嘛?如果是那样,我们的损失会很大!

但是如果我们采用面切切面,在需要加的地方,横切进去,这样不就最大化的解决了问题,这也就是我们要说的AOP面向切面编程

2.AOP的原理:

AOP的实现原理也就是我们熟知的动态代理

在说动态代理之前,我先说一下代理模式,为什么要有代理模式?

spring从零开始学 spring应该怎么学_spring从零开始学_04


就要我们最常见的例子来说,比如用户要租房,但是工作很忙没时间去看房子,这时就找到了我们的房屋中介,房屋中介和房东有一种关系,房屋中介和房东都可以向外出租房子,这也就是我们的说的代理模式,这种也是我们最初的静态代理

静态代理有什么问题呢?

静态代理帮我们把功能直接写死在代码中,一个真实角色就会产生一个代理角色;代码量翻倍,开发效率变低

如果用户向实现多种功能,就要多个代理,代码量会冗余

spring从零开始学 spring应该怎么学_spring_05


那接下来就引出我们的动态代理模式:

spring从零开始学 spring应该怎么学_实现原理_06


如果我们变成这样,用户需要实现什么功能,而我们的代理则动态的生成

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

3.AOP的实现:

方式一:

使用Spring的API接口 【 主要是Spring接口】

方式一:原生Spring API接口
    配置aop 导入约束
    <aop:config>
        <!-- 切入点  expression=execution(要执行的位置)-->
        <aop:pointcut id="pointcut" expression="execution(* com.zjd.service.UserServiceImpl.*(..))"/>
        <!--执行环绕增加-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>
        <aop:advisor advice-ref="afterLog" pointcut-ref="pointcut"/>
    </aop:config>
方式二:

使用自定义类来实现【主要是切面】

方式二:自定义类实现
<bean id="diy" class="com.wdit.diy.diyPointCut"/>
<aop:config>
    <!--自定义切面,ref 要引用的类-->
    <aop:aspect ref="diy">
        <!--切入点-->
        <aop:pointcut id="pointcut" expression="execution(* com.zjd.service.UserServiceImpl.*(..))"/>
        <!--通知-->
        <aop:before method="before" pointcut-ref="pointcut"/>
        <aop:after method="after" pointcut-ref="pointcut"/>
    </aop:aspect>
</aop:config>
方式三:

使用注解实现

<!--方式三:注解-->
<bean id="annopointcut" class="com.zjd.diy.AnnotationPointCut"/>
    <!--注解支持-->
<aop:aspectj-autoproxy/>