Spring的核心 IOC、DI和AOP

我们都知道Spring的两大核心技术:依赖注入(DI)和面向切面编程(AOP)

控制反转(IOC)是一种思想,不是技术,它是由DI技术实现的。

在了解这两技术之前我们先来了解一下什么是容器

Spring容器

  • 在基于Spring的应用中,你的应用对象就生存在Spring容器(container)中。
  • Spring容器负责创建对象,装配、配置它们并管理它们的整个生命周期,从创建到销毁。
  • 容器是Spring框架的核心。Spring容器通过依赖注入(DI)管理管理构成应用的组件,它会创建相互协作的组件之间的联系。
  • 从代码层面理解:Spring容器就是一个实现了ApplicationContext接口的对象。
  • 从功能上理解:Spring容器是用来管理对象的。

Spring结构图
在这里插入图片描述

IOC与DI

IOC控制反转——思想

控制反转是一种思想,它的实现主要靠依赖注入(DI)。

在传统应用程序中,我们在类的内部创建对象,这样使类与类之间关系紧密,耦合度较高。
IOC思想则是把对象的创建、装配和管理都交给容器来控制。目的就是松散耦合,使程序结构更灵活。

例如,Servlet技术也是控制反转(IOC)思想的一种体现。
在Servlet技术中:
1、你要创建一个类继承HttpServlet类;
2、在配置文件web.xml中注册servlet

<servlet-name>myServlet</servlet-name>
<servlet-class>com.bjpowernode.controller.myServlet</servlet-class>

在这个过程中没有创建过Servlet对象,我们只是在配置文件中注册Servlet,实际上是Tomcat容器帮我们创建的。

总结: 在使用Spring之前,当一个类A要调用另一个类B的方法时,就会在自己的类中new B(),需要哪个对象就创建哪个对象,A会对B产生依赖,导致程序之间的耦合度较高,而且不灵活。在Spring之后,A不需要在自己创建B对象了,把这个工作交给一个第三方Spring容器控制,Spring容器会创建好B,在A需要时,从Spring容器中取出B交给A,也实现了A对B的依赖,至于什么时候创建B什么时候取出,都是容器的工作,也就是把以前A自己掌握的控制权现在移交给Spring容器了。这也就是控制反转的思想。

DI依赖注入——IOC思想的技术实现

DI是如何实现的呢?或者叫容器是如何创建对象的

主要有两种方式:主要通过配置文件注解

配置文件

1、配置文件的方式:set注入
一个bean标签的声明就对应一个对象,下图的方式是通过在配置文件中使用set方法注入property标签实际是调用了Sutdent中的set方法实现的赋值。这是比较常用的一种赋值方式
在这里插入图片描述
所有的通过bean标签声明的对象都具有单例性,id唯一,实际是拿到了bean中的class属性,通过反射创建对象,property给对象的属性赋值,Spring会把通过bean创建的对象都保存到一个map容器中,key保存的就是bean的id(对象名),value保存的是对象的实例,当需要用哪个对象时通过getBean(“id”)方法就可以获取对象。

2、还有一种是配置文件的构造注入:
在这里插入图片描述
通过< constructor-arg >标签的个数来找对应的构造方法,并且对应好参数列表,通过构造器的方式实现给对象赋值。

如果是引用类型的参数那么标签中的value换成ref即可。

配置文件实现注入的这种方法也有弊端,代码量增多,不方便阅读,需要结合代码和xml文件一起看,优点是,对于需要频繁修改的可以放在配置文件中,减少修改源代码的次数。

注解

步骤
1、使用注解首先要添加依赖,spring-context这个包中包含了spring-aop这个依赖,有spring-aop才可以使用注解。
2、添加注解
3、在配置文件中加入组件扫描器,扫描注解的位置。

@Component(value=“student”)
括号里的可省略,默认为类名的首字母小写,这个注解用在类上相当于声明bean,用于创建对象
@Value(value=“张三”):定义在属性上的,通过这个注解就不需要set方法了,原理也是通过反射实现的。

@Repository:放在dao层的实现类上面,表示创建dao对象,dao对象是进行数据库访问的,又叫持久层注解。
@Service:放在业务层的实现类上面,创建Service对象,业务层是处理业务逻辑的。
@Controller:放在控制层上面,创建Controller对象的,控制层用来提交用户信息或者接受返回数据的。
这三个注解即创建对象,同时也把程序进行了分层处理。

@Autowired(required=true)是Spring框架提供的注解,用于引用类型的自动注入(也是创建对象),以byType的方式;
括号里的可以省略,默认是true,表示对象创建失败,程序报错并停止,false表示如果对象创建失败,不提醒报错,但是可能会出现空指针异常。
这个可以搭配使用@Qualifier(“studentDao”)用来表示实例化的对象名

@Resource注解与上面的有些不同,他是JDK中提供的,而不是Spring,但是Spring支持他的使用,@Resource也是用来给引用类型自动注入的,它优先使用byName的方式,如果没有找到名字再使用byType的方式。

注解的优点:代码简洁易读,但是需要频繁修改对象属性时,还是推荐使用配置文件的方式

AOP面向切面编程

AOP 全拼:Aspect Object Programming

AOP编程技术不是Spring独有的,Spring框架是支持AOP编程的框架之一,关系不要搞混。

AOP的目的是在不修改源代码的基础上实现功能的拓展。

AOP编程往往被定义为促使软件系统实现关注点分离的一项技术
这个关注点就是指一个业务模块中实现核心业务逻辑的代码,这个核心才是程序应该关注的。同时还会有日志、事务管理、安全等具有辅助功能的重复代码,每个业务模块中都会有这样的重复代码,我们把这种具有辅助功能的重复代码核心业务代码分开就是AOP编程要解决的问题。
我们把这种具有辅助功能的重复代码抽取并封装为一个可重用的模块,这个模块被命名为“切面”(Aspect)。
在这里插入图片描述
如果我们把核心代码与具有辅助功能的代码分离开,可以实现横切关注点与它们所影响的对象之间的解耦,使服务模块更简洁,因为它们只包含核心代码,而把日志,事务管理等代码转移到切面中。

DI有助于应用对象之间的解耦,而AOP可以实现横切关注点与它们所影响的对象之间的解耦。

AOP常用术语

  • 目标对象 要给哪个类的方法增加功能,这个类就是目标对象。
  • 通知(Advice) 表示这个切面执行的时间,比如日志在目标对象之前输出还是之后输出。
  • 连接点(joinpoint) 连接切面和业务方法的位置,其实就是业务方法
  • 切点(pointcut) 多个连接点的集合
动态代理

AOP变成就是动态代理实现的。
两种方式:JDK动态代理和CGLIB动态代理。

更详细的可以查看这篇文章《Java设计思想——反射机制》中的invoke方法
1、JDK动态代理只提供接口的代理,不支持类的代理。核心InvocationHandler接口和Proxy类,InvocationHandler 通过invoke()方法反射来调用目标类中的代码,动态地将横切逻辑和业务编织在一起;接着,Proxy利用 InvocationHandler动态创建一个符合某一接口的的实例, 生成目标类的代理对象。

2、如果代理类没有实现 InvocationHandler 接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。CGLIB(Code Generation Library),是一个代码生成的类库(或者说是一个工具类),可以在运行时动态的生成指定类的一个子类对象,并覆盖其中特定方法并添加增强代码,从而实现AOP。CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值