【Spring】IoC,DI,两种代理方式,AOP定义和使用
文章目录
- 前言
- 一、Spring框架中的核心思想?
- 1.1依赖注入(DI)
- 【总结】IOC DI
- 二、Spring-面向切面编程(AOP)
- 2.1代理模式举例
- 2.2如何开发一个代理对象?
- 2.2.1 静态代理对象
- 2.2.2动态代理对象
- 2.3面向切面编程
- 2.3.1Spring aop 编程的编程步骤
- 2.3.2aop编程举例
- 2.4总结
- 三、如何用Spring创建复杂对象?
- 3.1Spring工厂获取对象的原理(回顾)
前言
一、Spring框架中的核心思想?
两个思想:控制反转(IoC, Inversion of Control) 、 面向切面编程(AOP, )
IoC
定义:控制反转:控制权力的反转。
解释:将原来手动通过new关键字创建对象的权力交给了Spring,通过在配置文件中配置bean标签的形式创建对象,交给Spring 由Spring创建对象的过程。
可是,像Tomcat容器,也能够做到不需要new关键字,就可以使用Servlet,(其实背后就是控制反转)。那么控制反转并不是Spring所特有的特性。
因此,Spring在基于IOC基础上,提出了“依赖注入”(DI,Dependency Injection)。
我们可以发现Service层经常需要调用DAO层,即需要DAO组件对象, 这种 “需要” 可以称为 “依赖”,即 依赖DAO组件。
因为DAO组件对象已经在Spring中生成了,那么下次Service层在调用时,只需要在Spring容器中取就好了。
像此时,deptDAO只是有声明,如果需要时在12行直接调用save(),会报空指针异常。
那么 第一步 需要谁。就先声明谁为成员变量,
第二步:为成员变量赋值,为成员变量赋值的过程 ,就称为依赖注入。
1.1依赖注入(DI)
定义:为组件中成员变量完成赋值过程 ,这个过程就称之为 依赖注入。
语法:
1.组件对象中需要哪个组件, 就将谁声明为成员变量 并提供公开的SET方法。(示例如下:)
(提供get方法,会出现代码冗余)
只有上面操作还不够,还要经过第二步
2.在Spring的配置文件中对应的 组件标签内 完成属性的赋值操作。
下面就是依赖注入的示例:
以上就是依赖注入的过程。
并且可以总结得知:通过IOC可以创建组件对象, 通过DI 维护了组件与组件之间的调用关系
此时
IOC的全部定义概述为:
即控制反转, 将原来手动通过new关键字创建对象的权力交给Spring,由Spring工厂创建对象的过程。
当然,Spring不仅创建对象还要再创建对象的同时,通过DI的方式维护组件与组件的调用关系。
DI(set方式注入)基本语法:
DAO层:
Service层:
配置文件的赋值:
启动工厂测试:
其实在Spring中注入方式主要有三种:
(重点)a.SET注入 : 使用成员变量SET方法形式进行赋值
(了解)b.构造注入 : 使用构造方法形式 进行属性的赋值
(了解)c.自动注入 : 通过在配置文件中 完成类中属性自动赋值
Spring中SET方法的注入语法:
上面已经讲过的,注入时,把组件对象声明,然后生成SET方法,
但如果需要注入的不是对象, 而是一个String属性值、Date类型的还和上面的语法一样吗?
可以通过在xml文件中选用value对 八种基本数据类型 + String类型 + Date 类型 统一使用 value属性进行注入
Spring中对日期类型的值注入,只能使用格式为value=“yyyy/MM/dd HH:mm:ss”
总结:
对于Map类型,其键值对,根据具体情况具体写,总体原则是,对象类型就要用ref, String等类型用value。例如:key-ref,value-ref等
对于properties配置文件,里面也是key-value:,里面都是放String,所以没有什么key-ref:
【总结】IOC DI
二、Spring-面向切面编程(AOP)
面向切面的编程,:(AOP,Aspect Oriented Programing )
底层原理:java 代理设计模式 动态代理
好处:在保证 原始业务功能不变的情况下, 通过代理对象完成 业务中附加操作,将业务中核心操作 放在目标对象中执行,实现了附加操作和核心操作的解耦
在说AOP之前,需要先明白代理设计模式
java: (Proxy)代理设计模式
2.1代理模式举例
小张和小丽网恋,小张(业务逻辑调用者,Main())给小丽的账号名(如花)(接口Interface)发消息,本来小丽要给闺蜜做饭,所以就让小丽闺蜜(代理对象Proxy)帮自己打字,并转述聊天内容。在这个过程中小张是不知道手机对面是谁在和自己聊天(接口屏蔽了底层的具体实现逻辑)。
小丽闺蜜的存在,减轻了小丽的负担,保证了原始业务逻辑不变,同时还能使小丽完成一些附加事情。
2.2如何开发一个代理对象?
2.2.1 静态代理对象
a) 代理对象和 业务逻辑对象 (真正的业务逻辑对象) 实现相同的接口
b) 代理对象中 依赖 真正业务逻辑对象
先看看原始业务逻辑对象的代码:存在大量冗余(忙)
以上代码可以看到,每个方法都出现了大量的代码冗余,(开启事务,提交事务…)
有代理的存在和无代理的存在,能完成的原始功能是一致的,但是有代理的话,可以让原始业务逻辑对象更加专注去处理原来的核心业务(处理DAO)。
(静态)代理对象的代码:
spring.xml中:
因此有了代理存在,就 不能再调用原始的业务逻辑对象,而是 应该调用代理对象,才能保证原始大的功能不变。
上面讲的,为每一个业务层 通过手动开发一个代理对象的过程 称之为 “静态代理对象”
存在问题:很明显,静态代理开发,比原先更加复杂了,(需要多写一个类),如果为每一个业务层开发一个静态代理类,不仅没有减轻工作量,
甚至让工作量多了一倍。
解决方案:为业务层在运行过程中动态创建代理类,通过动态代理类去解决现有业务层中业务代码冗余问题。
2.2.2动态代理对象
代理对象:保证原始功能不变的情况下,完成业务逻辑中附加操作
原始业务逻辑对象:也叫Target,目标对象| 被代理对象称之为目标对象, 原始业务逻辑对象
什么是动态代理:
在程序运行过程中,通过代码底层的方式,为指定的类创建动态代理对象,(不是手工开发的,是根据接口创建的)
proxy 用来生成动态对象的类
参数1:classLoader 类加载器
参数2:Class[] 目标对象的接口的类型的数组 (一个类可以实现多个接口,所以是数组)
参数3: InvocationHandler 接口类型 invoke 方法用来书写额外功能(附加操作)
UserService userService = new UserServiceImpl(); //目标类
//类加载器,
ClassLoader classLoader = Thread.currentThread().getContextClassLoader()
//Class[] 目标对象的接口 的类型 的数组
Class[] classes = {UserService.class};
//返回值:创建好的动态代理对象:
//(为目标类创建代理对象,方式是,通过底层的classLoader类加载器,
//读到UserServiceImpl的类信息,把信息加载到内存中,然后才能对应生成动态代理)
Uservice userServiceDynamicProxy = (UserService)Proxy.newProxyInstancce(classLoader, classes,new InvocationHandler(){//通过动态代理对象调用自己里面代理方法时 会优先指定InvocationHandler类中invoke方法@Override
//参数1:当前创建好的代理对象; 参数2:当前代理对象执行的方法对象, 参数3:当前代理对象执行方法的参数public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{System.outprintln("当前执行的方法:"+method.getName());System.outprintln("当前执行的方法的参数:"+args[0]);try{System.outprintln("开启事务");//调用目标类中业务方法,通过反射机制,调用目标类中当前方法Object invoke = method.invoke(new UserServiceImpl(), args)System.outprintln("提交事务");return invoke;}catch(Exception e){e.printStackTrace();System.out.println("回滚事务");}return null;}});
String name =proxy.findAll("小明"); //通过动态代理对象调用代理中的方法,执行这里时,会跳到上面执行@Override的方法
第一个参数是类加载器,为什么呢?
读接口的信息,底层操作字节码,读字节码 动态生成对象,classLoader就是用来读class文件,读类信息的
classes,告诉基于哪个目标类的接口,去生成代理对象
2.3面向切面编程
下图方框中标记的代码,我们称为附加操作,附加操作在AOP中被称为通知(Advice)
通知(Advice):除了目标方法以外的操作都称之为通知 附加功能 事务通知 日志通知 性能通知…
切入点(Pointcut): 指定开发好的 通知 应用于项目中 哪些组件中 哪些方法,通常通知多用于业务层
切面(Aspect):通知(Advice) + 切入点 (pointcut)
环绕通知:围绕目标方法执行的通知
AOP 面向切面编程:
1.开发通知类(附加功能)
2.配置切面点
3.组装切面(Aspect)
2.3.1Spring aop 编程的编程步骤
1.引入aop编程相关依赖
spring-aop、 spring-expression 、spring-aspect
2.项目开发额外功能通知
环绕通知 MethodIntercept
前置通知 MethodforAdvice
后置通知 AfterReturningAdvice
异常通知 ThrowsAdvice
3.配置切面 (在spring.xml中完成)
a).注册通知类
<bean id ="" class="xxxAdvice">
b).组装切面 aspect = advice + pointcut
<aop:config><aop:pointcut id="" expression="execution()"/><aop:advisor advice-ref="" pointcut-ref=""/>
</aop:config>
2.3.2aop编程举例
上面程序中第8、14行,只是方法名称不同,存在冗余,因此可通过切面编程优化。
解决: 自己写一个前置通知,这个要实现框架中提供的接口 (implements MethodBeforeAdvice)
上述代码中,expression="execution(* aop.EmpServiceImpl.*(..))"
第一个*
代表 可 任意类型的返回值
第二个 参数 aop.EmpServiceImpl.*(..)
这个包名 表示 切入点在 aop.EmpServiceImpl类下的所有方法。如果写成aop.*ServiceImpl.*.(..)
则表示,切入点在aop包下的所有以ServiceImpl
结尾的类,都会切入切面。
上述在spring.xml中配置的代码,只要发现了有<aop.advisor>
,那么就会根据该句中的pointcut-ref=""/>
生成动态代理对象,
2.4总结
说明:
在implements MethodBeforeAdvice之后,重写的这个before()已经把InvokHandler中的invoke方法做了提取,提取成了 各种各样的通知,
这才使得,当只要切入成功,这里通过getBean得到的empService
对象变成了代理对象, 它会优先执行代理对象的方法。然后再调用dao执行业务逻辑方法
三、如何用Spring创建复杂对象?
3.1Spring工厂获取对象的原理(回顾)
为什么经过上面的a)b)c)三步,工厂可以获取到组件对象?
因为是反射机制
通过Class.forName("全限定名")
,读取类的信息,然后又调用 newInstance()
调用类的构造方法进行对象的创建
3.通过工厂创建简单对象
简单对象:可以直接通过new关键字 创建的对象 ,统一称为 简单对象
工厂创建简单对象时直接通过<bean id="xxx" class="xxx">
完成
4.通过工厂创建复杂对象
复杂对象: 不能直接通过new关键字进行创建对象,例如:接口类型 | Collection | 抽象类类型 Calender(日历)/ MessageDigest(加密)…
对象名FactoryBean implements FactoryBean<Calender|Connection|复杂对象>{}
例如:创建Calender复杂对象,1) implements+ 2) @override
public class CalenderFactoryBean implements FactoryBean<Calender> {//用来书写复杂对象的创建方式@Overridepublic Calender getObject() throws Exception{return Calender.getInstance();}//指定创建的复杂对象的类型@Overridepublic Class<?> getObjectType(){return Calender.class;}//用来指定创建的对象模式,单例或多例@Overridepublic boolean isSingleton(){return false;}
}
工厂创建日历(复杂)对象:
工厂创建连接对象:
在工厂中获取复杂对象的方式也是用<bean>
代码如下(示例):
【Spring】IoC,DI,两种代理方式,AOP定义和使用相关推荐
- Spring的两种代理方式:JDK动态代理和CGLIB动态代理
代理模式 代理模式的英文叫做Proxy或Surrogate,中文都可译为"代理",所谓代理,就是一个人或者一个机构代表另一个人或者另一个机构采取行动.在一些情况下,一个客户不想或者 ...
- Spring与Hibernate两种组合方式
Spring与Hibernate大致有两种组合方式,主要区别是一种是在Hibernate中的hibernate.cfg.xml中配置数据源,一种是借助Spring的jdbc方式在Spring的appl ...
- Spring中AOP的两种代理方式(Java动态代理和CGLIB代理)
第一种代理即Java的动态代理方式上一篇已经分析,在这里不再介绍,现在我们先来了解下GCLIB代理是什么?它又是怎样实现的?和Java动态代理有什么区别? cglib(Code Generation ...
- 【Spring AOP(2)篇】原理及两种实现方式(cglibjdk动态代理)
简介: Spring AOP(Aspect-Oriented Programming,面向切面编程)是 Spring 框架的一个重要特性,用于解耦和切割业务逻辑,是实现面向切面编程的重要手段之一.本文 ...
- Spring AOP两种使用方式以及如何使用解析
AOP是一种面向切面编程思想,也是面向对象设计(OOP)的一种延伸. 在Spring实现AOP有两种实现方式,一种是采用JDK动态代理实现,另外一种就是采用CGLIB代理实现,Spring是如何实现的 ...
- Java框架篇---spring aop两种配置方式
Java框架篇---spring aop两种配置方式 第一种:注解配置AOP 注解配置AOP(使用 AspectJ 类库实现的),大致分为三步: 1. 使用注解@Aspect来定义一个切面,在切面中 ...
- java动态代理两种实现方式
代理顾名思义就是代理别人完成某件任务,比如张三代理李四去交物业费.张三就是代理人,李四就是被代理人. Java代理实现,有静态代理和动态代理,静态代理就是代码在编译成class文件后,就已经有代理类的 ...
- 【IOC 控制反转】IOC 简介 ( 依赖注入的两种实现方式 | 编译期注入 | 运行期注入 )
文章目录 一.IOC 简介 二.依赖注入的两种实现方式 一.IOC 简介 IOC 是 Inversion Of Control 的缩写 , 控制反转 ; 其最主要的作用是 降低代码的耦合度 , 最常见 ...
- AOP 详解 、AOP 中通知类型 、AOP 两种实现方式(Schema-base 和 AspectJ)
一.AOP AOP:中文名称面向切面编程 英文名称:(Aspect Oriented Programming) 正常程序执行流程都是纵向执行流程 3.1 又叫面向切面编程,在原有纵向执行流程中添加横切 ...
- spring入门之Spring 常用的三种注入方式
Spring 常用的三种注入方式 Spring 通过 DI(依赖注入)实现 IOC(控制反转),常用的注入方式主要有三种:构造方法注入,set 方法注入,基于注解的注入. 一.通过构造方法注入 先简单 ...
最新文章
- C++中typedef和define的区别
- 一文带你了解卷积神经网络基础,建议收藏
- UIBezierPath 绘制正五边形
- Linux df -h查看磁盘使用情况
- MongoDB查询性能分析—— explain 操作返回结果详解
- linux c计算两个int相除求百分比的实现
- 命令行运行Jmeter实例
- java html转word!
- NYOJ 412 Same binary weight题解
- 网名接龙--之追求完美
- 【洛谷】洛谷深基学习记录 第二章 顺序结构程序设计
- 如何扩大计算机的硬盘空间,Win7系统怎么扩大C盘空间 Win7电脑扩大硬盘C盘空间方法介绍...
- 用Canvas画一个七巧板
- Qter 开发资源大集合
- 2021 || You Cannot Easily Catch Me: A Low-Detectable Adversarial Patch for Object Detectors
- 分时系统和实时系统(操作系统)
- SSL/TLS类安全漏洞及SLB安全漏洞问题
- cnn卷积神经网络手写体识别keras和tensorflow
- (附源码)Springboot小程序交通违法举报系统 毕业设计 242045
- Windows Media Player控件属性及方法(c#)以duration为什么总是“0”解决方法
热门文章
- linux关闭云锁服务器,安全软件之linux系统下云锁简单的安装方法
- 虚幻4引擎源码学习笔记(二):主循环LaunchEngineLoop
- 【转】腾讯云PCDN:从P2P到万物互联服务框架
- 从零开始 CMake 学习笔记 (G)compile-flags
- ORACLE数据库字段类型说明
- 亲手制作:超级DOS工具+Vista+加强版WindowsXP Lite5.8集成
- layui爬坑之路——input value属性绑定函数返回值
- 【opencv】颜色空间总结
- 2020幻影围棋 第三天围棋规则模块(一)
- web安全主要包括哪些方面的安全