一、IOC控制反转
1.1 概念
控制反转(Inversion of Control,缩写为IoC),是面向对象编程中的一种设计原则,可以用来减低计算机代码之间的耦合度。其中最常见的方式叫做**依赖注入(Dependency Injection,简称DI**),还有一种方式叫“依赖查找”(Dependency Lookup)。通过控制反转,对象在被创建的时候,由一个调控系统内所有对象的外界实体将其所依赖的对象的引用传递给它。也可以说,依赖被注入到对象中。
1.2 什么是IOC
- 控制反转,把对象的创建和对象直接的调用的过程,都交给Spring进行管理
- 使用IOC的目的: 为了耦合度降低
1.3 IOC底层
- xml解析,工厂模式,反射
1.4 IOC画图
1.4.1 原始方式调用方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1a5YYgwg-1640579136698)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225105919319.png)]
耦合度很高,如果dao层方法改变了之后service也要跟着改变
1.4.2 工厂模式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-E5OsL5fb-1640579136699)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225110235241.png)]
采用工厂设计模式还是有耦合度
1.4.3 IOC实现
- xml解析
- 工厂设计模式
- 反射创建对象
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PO0LtjhI-1640579136700)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225110739879.png)]
1.5 IOC接口
-
IOC思想基于IOC容器完成,IOC容器底层就是对象工厂
-
Spring提供IOC容器实现两种方式:两个接口
-
BeanFactory : IOC容器基本实现,是spring内部使用的接口,不提供给开发人员使用
加载配置文件的时候不会去创建对象,在获取对象的时候才去创建对象
-
ApplicationContext :是BeanFactory的子接口,提供更多更强大的功能,一般给开发人员使用
加载配置文件的时候就会把配置文件的对象进行创建
-
-
ApplicationContext配置类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9UJru6gl-1640579136701)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225111744393.png)]
二、AOP面向切面编程
2.1 概念
在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
2.2 面向切面登录功能
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oByaWEN9-1640579136701)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225113515106.png)]
2.3 AOP底层原理
-
AOP的底层采用动态代理
-
有两种情况的动态代理
第一种: 有接口的情况 ,JDK动态代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vukrFPVl-1640579136702)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225114228067.png)]
第二种: 没有接口,采用CGLIB动态代理
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zyaYOxY5-1640579136703)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225114515789.png)]
-
2.4 AOP动态代理实现
-
使用JDK动态代理,使用Proxy创建
调用newProxyInstance方法
- 第一个参数,类加载器
- 增强方法所在的类,这个类实现的接口,支持多个接口
- 实现这个接口InvocationHandler,创建代理对象,写增强的方法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vAUTGJ5Z-1640579136703)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225120504464.png)]
-
代码实现JDK动态代理代码
- 创建接口,定义方法
public interface UserDao { int add(int a,int b); String update(String id); }
-
创建接口实现类,实现方法
public class UserDaoImpl implements UserDao{ @Override public int add(int a, int b) { System.out.println("add方法调用了"); return a + b; } @Override public String update(String id) { return id; } }
-
创建代理类
public class JDKProxy { public static void main(String[] args) { // 创建接口实现类代理对象 Class[] interfaces = {UserDao.class}; UserDaoImpl userDao = new UserDaoImpl(); UserDao dao = (UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); int result = dao.add(1, 2); System.out.println(result); } } class UserDaoProxy implements InvocationHandler{ // 1 把创建的是谁的代理对象,把谁闯进来 // 有参数构造函数 private Object object; public UserDaoProxy(Object object) { this.object = object; } // 增强的逻辑 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 方法执行之前 System.out.println("方法执行之前......" + method.getName() + "参数" + Arrays.toString(args)); // 被增强的方法执行 Object invoke = method.invoke(object, args); // 方法之后 System.out.println("方法之后......" + invoke); return invoke; } }
2.5 AOP 术语
- 连接点
- 切入点
- 通知(增强)
- 切面
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J8X58fNV-1640579136704)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225115711424.png)]
2.6 AOP操作(准备)
-
Spring框架宜宾都基于AspectJ实现AOP操作
- 什么是AspectJ
- AspectJ不是spring组成部分,二手独立AOP框架,一般吧AspectJ和Spring框架一起使用,进行AOP操作
- 什么是AspectJ
-
基于AspectJ实现AOP操作
- 基于XML配置文件实现
- 基于注解方式实现
-
在项目工程里引入AOP相关依赖
-
切入点表达式
-
切入点表达式作用:知道对哪个类里边的方法进行增强
-
语法结构
execution([权限修饰符][返回类型][类路径][方法名称]([参数列表]))
-
举例一
对com.mohan.dao.BookDao里边的add进行增强
execution(*com.mohan.dao.BookDao.add(…))
举例二
对com.mohan.dao.BookDao里边的add进行增强
execution(*com.mohan.dao.BookDao. *(…) )
举例三
对com.mohan.dao.里所有的类里边的方法进行增强
execution(*com.mohan.dao. *. *(…) )
2.7 AOP操作 AspectJ
2.7.1 注解方式
-
创建类,在类里边定义方法
public class User { public void add() { System.out.println("add..."); } }
-
创建一个增强类
-
进行通知的配置
-
在spring配置文件中,开启注解扫描
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/context/spring-aop.xsd"> <context:component-scan base-package="com.mohan.spring5.aopanno"></context:component-scan> </beans>
-
使用注解创建User和UserProxy
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vC0BhpxJ-1640579136705)(F:\人生苦短,我用spring\新笔记\Spring5.assets\image-20211225155441737.png)]
-
在增强类添加注解@Aspect
//增强的类 @Component @Aspect //生成代理对象 public class UserProxy {} //被增强的类 @Component public class User {}
-
在spring配置文件中开启生成代理对象
//4、配置不同类型的通知 @Component @Aspect //生成代理对象 public class UserProxy { //相同切入点抽取 @Pointcut(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))") public void pointdemo() { } //前置通知 //@Before注解表示作为前置通知 @Before(value = "pointdemo()")//相同切入点抽取使用! public void before() { System.out.println("before........."); } //后置通知(返回通知) @AfterReturning(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))") public void afterReturning() { System.out.println("afterReturning........."); } //最终通知 @After(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))") public void after() { System.out.println("after........."); } //异常通知 @AfterThrowing(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))") public void afterThrowing() { System.out.println("afterThrowing........."); } //环绕通知 @Around(value = "execution(* com.atguigu.spring5.aopanno.User.add(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("环绕之前........."); //被增强的方法执行 proceedingJoinPoint.proceed(); System.out.println("环绕之后........."); } }
-
三、JdbcTemplate
3.1 概念
Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库的创建
3.2 准备工作
roceedingJoinPoint) throws Throwable {
System.out.println(“环绕之前…”);
//被增强的方法执行
proceedingJoinPoint.proceed();
System.out.println("环绕之后.........");
}
}
```
三、JdbcTemplate
3.1 概念
Spring框架对JDBC进行封装,使用JdbcTemplate方便实现对数据库的创建