手写IOC及AOP
Posted 怀瑾Hello World
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写IOC及AOP相关的知识,希望对你有一定的参考价值。
手写ioc&aop
1.概念
IOC:Inversion of control 控制反转
- 控制:指的是对象创建(实例化、管理)的权利
- 反转:控制权交给外部环境了(spring框架、IoC容器)
- 传统开发⽅式:⽐如类A依赖于类B,往往会在类A中new⼀个B的对象
- IoC思想下开发方式:我们不⽤⾃⼰去new对象了,⽽是由IoC容器(Spring框架)去帮助我们实例化对象并且管理它,我们需要使⽤哪个对象,去问IoC容器要即可。
- 解决的问题:解决对象之间的耦合问题,避免new关键字
- Ioc和DI区别:IOC和DI是从不同角度描述同一件事情(对象实例化及依赖关系维护这件事情)。IOC是站在对象的角度,对象实例化及其管理的权力交给了(反转)容器。DI:Dependancy Injection(依赖注⼊),是站在容器的角度,容器会把对象依赖的其他对象注入(送进去),比如A对象实例化过程中因为声明了一个B类型的属性,那么就需要容器把B对象注入给A
AOP:Aspect oriented Programming 面向切面编程
- 起源:aop是oop的延续,oop三大特征:封装、继承、多态。是一种垂直纵向的继承体系。OOP编程思想可以解决⼤多数的代码重复问题,但是有⼀些情况是处理不了的,⽐如在顶级⽗类中的多个⽅法中相同位置出现了重复代码,OOP就解决不了
- 横切逻辑代码问题:1.横切代码重复问题。2.横切逻辑代码和业务代码混杂在⼀起,代码臃肿,维护不⽅便
- AOP解决的问题:在不改变原有业务逻辑情况下,增强横切逻辑代码,根本上解耦合,避免横切逻辑代码重复
- 面向切面编程理解:「切」:指的是横切逻辑,原有业务逻辑代码我们不能动,只能操作横切逻辑代码,所以⾯向横切逻辑。「⾯」:横切逻辑代码往往要影响的是很多个⽅法,每⼀个⽅法都如同⼀个点,多个点构成⾯,有⼀个⾯的概念在⾥⾯
2.通过银行转账案例手写IOC和AOP
2.1.表结构
CREATE TABLE `account` (
`name` varchar(255) DEFAULT NULL COMMENT '用户名',
`money` varchar(255) DEFAULT NULL COMMENT '账户金额',
`cardNo` varchar(255) NOT NULL COMMENT '银行卡号'
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
2.2.银行转账调用关系
2.3.分析存在的问题
- (1)问题⼀:在上述案例实现中,service 层实现类在使⽤ dao 层对象时,直接在TransferServiceImpl 中通过 AccountDao accountDao = new JdbcAccountDaoImpl() 获得了 dao层对象,然⽽⼀个 new 关键字却将 TransferServiceImpl 和 dao 层具体的⼀个实现类JdbcAccountDaoImpl 耦合在了⼀起,如果说技术架构发⽣⼀些变动,dao 层的实现要使⽤其它技术,⽐如 Mybatis,思考切换起来的成本?每⼀个 new 的地⽅都需要修改源代码,重新编译,⾯向接⼝开发的意义将⼤打折扣?
- (2)问题⼆:service 层代码没有竟然还没有进⾏事务控制 ?!如果转账过程中出现异常,将可能导致数据库数据错乱,后果可能会很严重,尤其在⾦融业务
2.4.解决问题思路
- 实例化对象的⽅式除了 new 之外,还有什么技术?反射 (需要把类的全限定类名配置在xml中)
- 考虑使⽤设计模式中的⼯⼚模式解耦合,另外项⽬中往往有很多对象需要实例化,那就在⼯⼚中使⽤反 射技术实例化对象,⼯⼚模式很合适
- service 层没有添加事务控制,怎么办?没有事务就添加上事务控制,⼿动控制 JDBC 的Connection 事务,但要注意将Connection和当前线程绑定(即保证⼀个线程只有⼀个Connection,这样操作才针对的是同⼀个 Connection,进⽽控制的是同⼀个事务)。分析:数据库的事务归根结底是Connection的事务connection.commit();提交事务 connection.rollback();回滚事务
2.5.通过IOC及AOP进行改造
2.5.0.pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.lagou.edu</groupId>
<artifactId>lagou-transfer</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>lagou-transfer Maven Webapp</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<dependencies>
<!-- 单元测试Junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<!-- mysql数据库驱动包 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.35</version>
</dependency>
<!--druid连接池-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.21</version>
</dependency>
<!-- servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
<!-- jackson依赖 -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<!--dom4j依赖-->
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<!--xpath表达式依赖-->
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.1.6</version>
</dependency>
<!--引入cglib依赖包-->
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>2.1_2</version>
</dependency>
</dependencies>
<build>
<plugins>
<!-- 配置Maven的JDK编译级别 -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<source>11</source>
<target>11</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<!-- tomcat7插件 -->
<!-- 注意:目前来说,maven中央仓库还没有tomcat8的插件 -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.2</version>
<configuration>
<port>8080</port>
<path>/</path>
</configuration>
</plugin>
</plugins>
</build>
</project>
2.5.1.index.xml
<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>转账汇款</title>
<script type="text/javascript" src="js/jquery-3.4.1.min.js"></script>
<style type="text/css">
body {
background-color:#00b38a;
text-align:center;
}
.lp-login {
position:absolute;
width:500px;
height:300px;
top:50%;
left:50%;
margin-top:-250px;
margin-left:-250px;
background: #ffffff;
border-radius: 4px;
box-shadow: 0 0 10px #12a591;
padding: 57px 50px 35px;
box-sizing: border-box
}
.lp-login .submitBtn {
display:block;
text-decoration:none;
height: 48px;
width: 150px;
line-height: 48px;
font-size: 16px;
color: #fff;
text-align: center;
background-image: -webkit-gradient(linear, left top, right top, from(#09cb9d), to(#02b389));
background-image: linear-gradient(90deg, #09cb9d, #02b389);
border-radius: 3px
}
input[type='text'] {
height:30px;
width:250px;
}
span {
font-style: normal;
font-variant-ligatures: normal;
font-variant-caps: normal;
font-variant-numeric: normal;以上是关于手写IOC及AOP的主要内容,如果未能解决你的问题,请参考以下文章
手写实现自定义简易版Spring (实现IoC 和 AOP)