今天聊一聊我自己对Spring的学习总结分析,Spring说白了就两个点:IOC 和 AOP
这两个点也是面试官最爱问的两个点,那么今天我就主要讲一下我对这两个点的理解
IOC实现原理
再说IOC之前,我先给大家看幅图:
在没了解IOC之前,我们的程序都是这样的,用户需要去查看数据,找到业务层,业务层对应去帮用户找到用户想要查看的数据,而我们程序员则是控制着业务层。
那么作为一个程序员,当用户需求和我们的功能越来越多的时候,用户每次去查询不同的功能,我们对应就要修改代码,如果代码量过于庞大,修改一次的成本代价是很昂贵的!
而我们把主动权交给了用户以后,用户自己需要什么功能,由用户自己去调用
这样系统的耦合性大大降低,程序员可以更加专注的在业务的实现上!这就是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的概述:
大家看这幅图,如果我们一个已经完整的项目,突然想去加一些新功能,比如实现日志,那我们需要去重新破坏掉原有的结构嘛?如果是那样,我们的损失会很大!
但是如果我们采用面切切面,在需要加的地方,横切进去,这样不就最大化的解决了问题,这也就是我们要说的AOP面向切面编程
2.AOP的原理:
AOP的实现原理也就是我们熟知的动态代理
在说动态代理之前,我先说一下代理模式,为什么要有代理模式?
就要我们最常见的例子来说,比如用户要租房,但是工作很忙没时间去看房子,这时就找到了我们的房屋中介,房屋中介和房东有一种关系,房屋中介和房东都可以向外出租房子,这也就是我们的说的代理模式,这种也是我们最初的静态代理
静态代理有什么问题呢?
静态代理帮我们把功能直接写死在代码中,一个真实角色就会产生一个代理角色;代码量翻倍,开发效率变低
如果用户向实现多种功能,就要多个代理,代码量会冗余
那接下来就引出我们的动态代理模式:
如果我们变成这样,用户需要实现什么功能,而我们的代理则动态的生成
- 可以使真实角色的操作更加纯粹!
- 公共业务就交给了代理角色!实现了业务的分工
- 公共业务发生扩展的时候,方便集中管理!
- 一个动态代理类代理的是一个接口,一般就是对应的一类业务
- 一个动态代理类可以代理多个类
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/>