一、IoC & DI
(一)IoC
IoC——控制反转,是一种设计思想,我们要用一个对象时,不需要自己去创建,只需要告诉Spring的容器,由容器为我们创建。
IoC的好处是,对象与对象之间是松散耦合的,方便测试,利于功能复用,更重要的是把程序的整体结构变得十分灵活。
IoC 思想是通过反射机制实现的。
反射作用总结就是:
- 从现有的对象中获取类型。
- 应用程序需要在运行时从某个特定的程序集中载入一个特定的类。
(二)DI
DI:依赖注入,即IoC容器可以动态的将一个对象注入到另一个对象中.
依赖注入的方法有三种:接口注入(侵入性,不推荐)、构造注入、setter注入
那么我们就有一个疑问:容器是如何来管理对象之间的依赖关系的呢?它怎么知道程序中的A对象要依赖一个B对象?
Spring中有三种方法来告诉容器:
- 直接编码
- 配置文件
- 注解
二、AOP
(一)介绍
AOP是Spring框架面向切面的编程思想,AOP采用一种称为“横切”的技术,将涉及多业务流程的通用功能抽取并单独封装,形成独立的切面,在合适的时机将这些切面横向切入到业务流程指定的位置中。
(二)实现方式
AOP常用的实现方式有两种,一种是采用声明的方式来实现(基于XML),一种是采用注解的方式来实现(基于AspectJ)。
(三)概念汇总
| 切面 | 切入业务流程的一个独立模块 |
| 切入点 | 用于定义通知应该切入到哪些连接点上,不同的通知通常需要切入到不同的连接点上 |
| 连接点 | 也就是业务流程在运行过程中需要插入切面的具体位置 |
| 通知 | 切面的具体实现方法。可分为前置通知、后置通知、异常通知、最终通知、环绕通知 |
| 目标对象 | 切面所通知的对象 |
| 代理对象 | 目标对象的业务逻辑功能加上被切入的切面所形成的对象 |
| 切入 | 将切面应用到目标对象从而创建一个新的代理对象的过程。 |
(四)分类
(1)动态代理技术
利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行。
(2)静态织入
引入特定的语法创建“面”,从而使得编译器可以在编译期间织入有关“面”的代码。
三、代理
(一)概念介绍
代理是一种常用的设计模式,其目的就是为其他对象提供一个代理以控制对某个对象的访问。代理类负责为委托类预处理消息,过滤消息并转发消息,以及进行消息被委托类执行后的后续处理。
(二)分类
根据代理类的生成时间不同可以将代理分为静态代理和动态代理两种。
静态代理与动态代理的区别
-
静态代理在编译时就已经实现,编译完成后代理类是一个实际的class文件
-
动态代理是在运行时动态生成的,即编译完成后没有实际的class文件,而是在运行时动态生成类字节码,并加载到JVM中
-
静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。
(三)静态代理
-
目标类和代理类都实现相同的业务接口;
-
代理类的构造方法中传入目标类的实例;
-
在代理类的接口实现中调用目标类实例的接口方法;
(1)优点
业务类只需要关注业务逻辑本身,保证了业务类的重用性。这是代理的共有优点。
(2)缺点
- 静态代理的缺点是不同的业务,需要实现多个目标实现类,代码冗余高
- 如果接口增加一个方法,除了所有实现类需要实现这个方法外,所有代理类也需要实现此方法。增加了代码维护的复杂度。
另外,如果要按照上述的方法使用代理模式,那么真实角色(委托类)必须是事先已经存在的,并将其作为代理对象的内部属性。但是实际使用时,一个真实角色必须对应一个代理角色,如果大量使用会导致类的急剧膨胀;此外,如果事先并不知道真实角色(委托类),该如何使用代理呢?这个问题可以通过Java的动态代理类来解决。
(四)动态代理
动态代理,就是根据对象在内存中加载的Class类创建运行时类对象,从而调用代理类方法和属性。
JDK动态代理是基于Java的反射机制实现的
(1)动态代理步骤
-
创建目标业务接口和实现类实例;
-
通过Proxy类的newProxyInstance()方法获取代理类实例;
-
创建InvocationHandler方法委托类实例,实现代理类到目标类的方法分派,并支持在目标类业务前后增改操作
(2)优缺点
优点
- 动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。
- 动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java 反射机制可以生成任意类型的动态代理类。
缺点
JDK的动态代理机制只能代理实现了接口的类,而不能实现接口的类就不能实现JDK的动态代理,cglib是针对类来实现代理的,他的原理是对指定的目标类生成一个子类,并覆盖其中方法实现增强,但因为采用的是继承,所以不能对final修饰的类进行代理。
(五)JDK动态代理、Cglib
而cglib动态代理是利用asm开源包,对代理对象类的class文件加载进来,通过修改其字节码生成子类来处理。
- 如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
- 如果目标对象实现了接口,可以强制使用CGLIB实现AOP
- 如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换
如何强制使用CGLIB实现AOP?
(1)添加CGLIB库,SPRING_HOME/cglib/*.jar
(2)在spring配置文件中加入<aop:aspectj-autoproxy proxy-target-class="true"/>
JDK动态代理和CGLIB字节码生成的区别?
(1)JDK动态代理只能对实现了接口的类生成代理
(2)CGLIB是针对类实现代理,主要是对指定的类生成一个子类,覆盖其中的方法
因为是继承,所以该类或方法最好不要声明成final

本文深入解析了Spring框架中的IoC(控制反转)和DI(依赖注入)原理,介绍了如何通过编码、配置文件和注解告诉Spring容器管理对象依赖。同时涵盖了AOP(面向切面编程)的概念、动态代理和静态织入的区别,以及JDK动态代理和CGLIB在实现AOP中的应用。
843

被折叠的 条评论
为什么被折叠?



