框架阶段一些总结

什么是IoC和DI?DI是如何实现的?

IoC叫控制反转,是Inversion of Control的缩写,DI(Dependency Injection)叫依赖注入,是对IoC更简单的诠释。控制反转是把传统上由程序代码直接操控的对象的调用权交给容器,通过容器来实现对象组件的装配和管理。所谓的”控制反转”就是对组件对象控制权的转移,从程序代码本身转移到了外部容器,由容器来创建对象并管理对象之间的依赖关系。
依赖注入是组件之间依赖关系由容器在运行期决定,形象的说,即由容器动态的将某个依赖关系注入到组件之中。依赖注入的目的并非为软件系统带来更多功能,而是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。通过依赖注入机制,我们只需要通过简单的配置,而无需任何代码就可指定目标需要的资源,完成自身的业务逻辑,而不需要关心具体的资源来自何处,由谁实现。

AOP

面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

Spring的IOC实现步骤:

1.编写实体类
2.编写spring的核心配置文件:applicationContext 中bean中添加管理的实体类,id表示bean的唯一标示,class表示实体类所在的路径,包名.类名
3.测试类中,spring容器的创建ApplicationContext context =new ClassPathXmlApplicationContext(“ApplicationContext.xml”)
从spring容器中获取对象 Hello hello =(Hello)context.getBean(“hello”)
调用hello对象的方法 hello.say();

spring的IOC的原理

在这里插入图片描述
说明:

当spring容器启动时,找到了对应的核心配置文件applicationContext.xml
当 加载配置文件时,逐行的读取xml配置,然后遇到bean标签时,进行解析
bean标签的id属性,解析为map中的key,bean标签的class属性,解析时通过java的反射机制,创建了Hello对象,同时,把value值放入了map中的value中
使用 map中的id属性的值,获取了map中的对象

spring中的单例和多例

单例:在内存中,有且只有一份对象
spring中,配置的标签,对应着一个对象。那么,该对象是多例还是单例?答案:默认单例模式。
单例模式的优点:节省内存的开销
单例模式的缺点:在一些项目需求中,比如:用户的订单模块,订单的对象最好是多例的,因为单例情况下,对象的内容会更新。
多例模式如何设计?
在这里插入图片描述

多例模式下:spring不负责对象的生命周期的维护。也就是说,程序员什么时候调用getBean,spring就什么时候生成对象。
单例模式下:spring直接创建出对象,负责对象的生命周期。

代理模式

静态代理模式
目的:实现了事务控制层和业务逻辑层之间的解耦
静态代理模式的方式:

在这里插入图片描述
根据需求,编写 事务控制的模块 tx.TransactionManager
在这里插入图片描述
根据需求,使用静态代理模式,编写 代理类 proxy.Proxy
在这里插入图片描述
在这里插入图片描述
根据 流程图 ,调整 web层 —> proxy代理 --> service层 之间的依赖关系
web层 : 不需要改动代码 UserService userService;
proxy代理:@Component(“userService”) 主要目的是,让web层依赖代理对象,其实对于web层来说,没有任何的区别。
service层 :@Component(“target”) 主要目的是,让代理对象 依赖 真实有效的目标对象 ,然后调用 真实有效的方法。

静态代理模式的优点:
1、实现了 业务层  与  事务控制层  之间的解耦
2、代理类 能够完成本职工作的调用 (目标对象的方法调用)
3、代理类  还能够完成 额外的操作 (对业务逻辑方法添加事务控制)
 
静态代理模式的缺点:
1、一个业务模块,必须要对应着  一个代理类
2、事务控制的代码 依然会有大量的重复

在这里插入图片描述
静态代理模式实现的前提条件:
必须要实现 目标对象的 相同的接口。

动态代理模式的介绍
是 在代码编译期间,不存在代理类。在代码运行期间,才会自动的产生代理类和代理对象。
解决的问题: 代理类 不需要 实现编译好,减少了代码量。
同时,解决了 静态代理模式的缺点。

动态代理的实现技术: java的反射机制 以及 回调函数

动态代理的实现方式: jdk提供的动态代理 、
spring提供的CGlib动态代理

JDK的动态代理实现 : jdkDynamicProxy

使用了 java提供的Proxy类 和 InvocationHandler接口

实现步骤:
创建一个动态代理的解决方案的类:JDKDynamicProxy
在 JDKDynamicProxy类中,添加 两个成员变量: 目标对象(本职的操作) 、事务控制(额外的操作)
在JDKDynamicProxy类中,添加构造方法,完成 成员变量的初始化
在JDKDynamicProxy类中,非静态的自定义方法getProxy():主要使用java.lang.reflect.Proxy类完成 目标对象的代理类和代理对象
在这里插入图片描述
在JDKDynamicProxy类中,添加回调函数,主要完成 :当客户端发起请求时,拦截到该方法,进入invoke()方法中,完成额外操作和本职的方法调用。
在这里插入图片描述
JDK的动态代理:

优点:继承了静态代理的优点
解决的代码重复的问题
动态的生成代理类和代理对象

前提:必须要求 目标对象 和 代理对象 必须要实现相同的接口。

Cglib的动态代理

使用spring提供的类Enhancer类(增加类,操作二进制文件) 和 MethodIntercepter接口

实现步骤:
创建一个动态代理的解决方案的类:CGlibDynamicProxy
在 CGlibDynamicProxy类中,添加 两个成员变量: 目标对象(本职的操作) 、事务控制(额外的操作)
在CGlibDynamicProxy类中,添加构造方法,完成 成员变量的初始化
在CGlibDynamicProxy类中,非静态的自定义方法getProxy():主要使用org.springframework.cglib.proxy.Enhancer类完成 目标对象的代理类和代理对象
在这里插入图片描述
在CGlibDynamicProxy类中,添加回调函数,主要完成 :当客户端发起请求时,拦截到该方法,进入intercept()方法中,完成额外操作和本职的方法调用
在这里插入图片描述

CGlib的特点: 目标对象 是作 为 代理对象的 父 类 ,没有必要实现接口

Spring MVC的工作原理是怎样的?

1:浏览器发起请求到前端控制器
2:前端控制器请求映射器根据xml中的配置和注解进行查找
3:映射器将查找结果返回给前端控制器
4:前端控制器调用处理器适配器去执行Handler
5:处理器适配器去执行Handler
6:Handler执行完成给适配器返回ModelAndView
7:处理器适配器返回ModelAndView给前端控制器
8:前端控制器请求视图解析器去进行视图解析,生成真正的视图页面.
9:视图解析器向前端控制器返回View
10:前端控制器进行视图渲染,将模型数据填充到request域
11:前端控制器将响应结果展示给用户

MVC的各个部分都有哪些技术来实现?如何实现?

MVC是Model-View-Controlller的简写.Model代表的是应用的业务逻辑(通过JavaBean,EJB实现),View是应用的表示面(由JSP页面产生),Controller是提供应用的处理过程控制(一般是一个Servlet),通过这种设计模型把应用逻辑,处理过程个显示逻辑分成不同的组件实现,这些组件可以进行交互和重用.

对Spring的理解

1.spring实现了工厂模式的工厂类,这个类名为BeanFactory,在程序中通常BeanFactory的子类ApplicationContext.spring相当于一个大的工厂类,在其配置文件中通过元素配置用于创建实例对象的类名和实例对象的属性.
2.spring提供了对IOC良好支持,IOC是一种编程思想,是一种架构艺术,利用这种思想可以很好的实现模块之间的解耦.
3.Spring提供了对AOP技术的良好封装,AOP称为面向切面编程,就是系统中有很多不相干的类的方法,在这些众多方法中要加入某种系统功能的代码,例如,加入日志,加入权限判断,加入异常处理,这种应用称为AOP.实现AOP功能采用的是代理技术,客户端程序不再调用目标,而调用代理类,代理类与目标类对外具有相同的方法声明,有两种方式可以实现相同的方法声明,一是实现相同的接口,二是作为目标的子类在JDK中采用Proxy类产生动态代理类的方式为某个接口生成实现类,如果要为某个类生成子类,则可以用CGLIB.在生成的代理类的方法中加入系统功能和调用目标类的相应方法,系统功能的代理以Advice对象进行提供,显然要创建出代理对象,至少需要目标类和Advice类,spring提供了这种支持,只需要在spring配置文件中配置这两个元素即可实现代理和aop功能,例如:

spring的AOP面向切面编程(思想和设计理念)

面向对象编程 : 使用封装 、 继承 、 多态 , 把相应的方法,写在类的内部,而使用者直接进行类的实例化,然后通过实例化对象调用方法。

实现方式: 对象.方法名();

面向接口编程 :使用接口以及接口的实现类,根据需求,完成具体功能的设计,然后程序员根据接口,只需要实现具体的方法逻辑即可。

实现方式: 类名 implements 接口 ; 实现接口中的方法体

1、把与业务逻辑无关的代码抽离出来,写在一个类中。该类就是切面类

2、切面类主要负责 完成额外的操作(事务控制) 以及 本职的方法

3、切面类 是 对 service层的方法进行 额外操作的,那么 就需要定义一个切入点,该切入点就是指向了 service层的 方法。

4、在执行service层的方法时,切面类 先进行事务控制 (事务的开启、事务的提交),那么 该方法就是 通知。

5、在执行完额外通知后,需要进行本职工作的调用。那么,本职方法的调用是通过 连接点完成的(addUser()方法)。

切面:把 与业务逻辑 紧密结合的代码抽离出来,放在一个统一的类中。该类是 切面类,主要作用是:完成 特定的功能模块(事务模块)的方法 。 切面实现的模块主要包括:(这些模块与业务逻辑无关)

数据库中的事务/数据库连接池/权限控制/日志分析/安全性的处理

切入点:

一种匹配规则,比如:在service层的UserServiceImpl类上加入切入点,就表示该切面类中的事务控制,对 UserServiceImpl中的方法生效了。

只有满足了匹配规则的方法,才能执行通知.

通知:

切面中的方法(主要实现额外的操作)

连接点:

客户端通过代理对象调用的方法(完成本职的操作)

主要实现本职方法的操作

目标对象:真实有效的对象方法的执行

spring当中的五大通知

环绕通知(Around Advice):表示 在 目标方法执行的前后添加相应的额外操作。
在这里插入图片描述
前置通知 (Before Advice):表示 在目标方法执行之前进行额外的操作。

前置通知:不执行目标方法,所以不能添加ProceedingJoinPoint类作为形参。
在这里插入图片描述
需求 : 不能使用 ProceedingJoinPoint 的情况下,如何获取目标对象的方法名称?
在这里插入图片描述
后置通知 (AfterRetuning Advice) :是在目标方法执行完毕之后,才执行的。

获取 目标方法执行的 返回值结果。同时,对执行结果做一个日志的监控和分析。

实现步骤:
前提条件:必须让环绕通知执行结束之后,添加方法放回的结果

  1. 在核心配置文件中,添加后置通知的标签
    在这里插入图片描述
    2.在切面类中,添加自定义方法 afterReturning(int number)
    在这里插入图片描述
    3.特别注意:需要修改 环绕通知的返回值类型:
    在这里插入图片描述
    总结:后置通知 一般用于 日志分析 与 日志监控。同时表示,方法执行完毕之后,需要拿到相应的返回值结果做分析。
    异常通知 (AfterThrowing Advice):在目标方法执行过程中,如果发生了异常,对异常信息进行捕获和处理

    异常出现时,环绕通知的方法执行过程中就会报错,然后,直接把异常结果交给了异常通知去处理。环绕通知的 事务提交方法 没有执行,同时 , 后置通知的方法 也没有执行。

    实现步骤:
    1、在配置文件中,编写异常通知的标签
    在这里插入图片描述
    2、在切面类中,编写自定义方法:afterThrowing(Throwable throwable),获取所有的异常类型
    在这里插入图片描述
    3、在业务方法中,添加一个模式异常的操作:int I = 1/0;
    在这里插入图片描述
    总结:异常通知,主要是进行异常的捕获和分析。在方法执行过程中进行捕获。

    最终通知(After (finally) Advice):无论目标方法是否成功执行,都会进行最终通知的执行

    说明:一般情况下,使用以上四种就可以,最终通知可以被后置通知代替。
    在这里插入图片描述
    在这里插入图片描述

面试——Spring事务管理

一、@Transactional
注意事项:如果动态代理使用的是jdk默认的动态代理,那么进行@Resource注入的时候,一定要给接口注入对象,而不是给实现类注入对象。因为aop底层是基于业务层接口通过反射构造实现类对业务方法进行执行的。所以必须注入接口。不然会报BeanNotRequiredException。
二、事务的管理
@Transactional(readonly=true),在业务方法上添加该注解
“只读事务”并不是一个强制选项,它只是一个“暗示”,提示数据库驱动程序和数据库系统,这个事务并不包含更改数据的操作,那么JDBC驱动程序和数据库就有可能根据这种情况对该事务进行一些特定的优化,比方说不安排相应的数据库锁,以减轻事务对数据库的压力,毕竟事务也是要消耗数据库的资源的。
三、事务的传播
事务的传播:业务重构的时候需要业务方法调用业务方法,这就需要一个业务方法的事务传播到另一个业务方法中,整合为一个事务。
举例就是——一个业务方法内调用了其他的业务方法,也就是说一个业务是由多个事务(或者业务)组成并合成一个事务的。这时候我们为了保持事务的原子性与一致性,要在这多个业务方法上增加@Transactional注解。就可以保持事务的原子性与一致性。一旦这个业务中的某个业务发生了异常,那么所有事务都不会commi
四、事务传播(propagation)属性
重点掌握 Propagation.REQUIRED
@Transactional(propagation=Propagation.REQUIRED)
需要事务, 如果没有事务创建新事务, 如果当前有事务参与当前事务
@Transactional(propagation=Propagation.MANDATORY)
必须有事务, 如果当前没有事务就抛异常
@Transactional(propagation=Propagation.NEVER)
绝不, 绝对不能有事务, 如果在事务中调用则抛出异常
在业务方法上打此标签,事务是具有原子性,但是事务不参与传播,一旦在别的业务方法中调用此业务方法,则会抛出异常
@Transactional(propagation=Propagation.NESTED)
嵌套, 必须被嵌套到其他事务中
@Transactional(propagation=Propagation.NOT_SUPPORTED)
不支持事务
@Transactional(propagation=Propagation.SUPPORTS)
支持事务, 如果没有事务也不会创建新事务
@Transactional(propagation=Propagation.REQUIRES_NEW)
必须是新事务, 如果有当前事务, 挂起当前事务并且开启新事务.

手写JDBC

六个步骤实现JDBC
Connection conn = null;
Statement stat = null;
ResultSet rs = null;
try{
//1.注册数据库驱动
//–驱动注册了两次
//–程序和具体的数据库驱动绑死在了一起
//DriverManager.registerDriver(new Driver());
//–通过反射的方式注册数据库驱动,第一只会注册一次,第二只和一个代表驱动的类的全路径名字符串绑死,可以提取到配置文件中,不会和具体的驱动绑死在一起
Class.forName(“com.mysql.jdbc.Driver”);
//2.获取数据库连接
conn = DriverManager.getConnection(“jdbc:mysql:///day12?user=root&password=root”);
//3.获得传输器对象
stat = conn.createStatement();
//4.利用传输器传输sql到数据库执行,获取执行的结果
rs = stat.executeQuery(“select * from account”);
//5.遍历结果集获取结果数据
while(rs.next()){
String name = rs.getString(“name”);
System.out.println(name);
}
}catch (Exception e) {
e.printStackTrace();
}finally{
//6.关闭资源
if(rs!=null){
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
rs = null;
}
}
if(stat!=null){
try {
stat.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
stat = null;
}
}
if(conn!=null){
try {
conn.close();
} catch (SQLException e) {
e.printStackTrace();
} finally{
conn = null;
}
}
}

4.PreparedStatement -- Statement的孩子 -- 可以防止sql注入攻击
	SQL注入攻击 
		由于后台的SQL语句是拼接而来的,其中的参数是用户提交的值,所以用户可以传入一些特殊的sql关键字,从而改变sql语句原有的语意,执行一些意外的操作。
		select * from user where username = '张飞' or '1=1' and password = ''

	优点:
		防止SQL注入攻击
		采用了预编译的操作,性能会更好一些
		省去了拼接字符串的操作,改为用方法来设置参数,使代码更加的优雅。。。。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值