重要的Spring模块
- Spring Core:核心模块,主要提供IOC依赖注入功能
- Spring AOP:面向切面的编程实现
- Spring JDBC : 连接数据库
- Spring Web:创建Web程序
- Spring Test:Junit和TestNG的测试功能
- Spring WebSocket:很方便实现即使聊天的组件
@RestController和@Controller
- 前者:放到一个类上面,代表此类的所有接口返回的是JSON类型的数据。
- 后者:返回一个页面,如果想要某个接口返回JSON数据,则需在接口加上@ResponseBody
Spring IOC 和 AOP
IOC,控制反转,将原本在程序中手动创建对象的控制权,交由Spring框架来管理。spring实现的方式是IOC容器,就是一个map,存放各种对象。
具体实现是依赖注入:将底层类作为参数传递给上层类,实现上层类对底层类的控制。有通过构造方法传递的,还有通过Set传递和接口传递。
控制反转容器:就是依赖注入需要注入上层类依赖的底层类,这些底层类的初始化就是容器做的。https://www.zhihu.com/question/23277575/answer/169698662
AOP,面向切面编程,将与业务无关的逻辑封装起来,减少系统代码重复。
基于动态代理,代理的对象实现了某个接口,则使用JDK的JDKProxy。否则使用Cglib,生成一个被代理对象的子类
//JDKproxy
package com.example.demo;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class JDKProxyDemo {
static interface Inter{
void oneMethod();
}
//被代理类
static class interImpl implements Inter {
@Override
public void oneMethod() {
System.out.println("被代理类的方法执行");
}
}
//生成代理类的处理类
static class JdkProxy implements InvocationHandler {
//被代理类对象
private Object object;
//将被代理对象和处理类绑定
public Object bind(Object o) {
this.object = o;
return Proxy.newProxyInstance(object.getClass().getClassLoader(),
object.getClass().getInterfaces(),this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理类对方法的增强");
Object invoke = method.invoke(object, args);
return invoke;
}
}
public static void main(String[] args) {
//生成一个代理类
JdkProxy jdkProxy = new JdkProxy();
Inter inter = (Inter) jdkProxy.bind(new interImpl());
//动态生成代理类对象
inter.oneMethod();
}
}
//Cglilb
package com.example.demo;
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibDemo {
static class SayHello {
public void sayHello() {
System.out.println("say hello");
}
}
static class CglibDemoE implements MethodInterceptor {
public Object getProxy(Class cls) {
//cglib增强类对象
Enhancer enhancer = new Enhancer();
//设置增强类型
enhancer.setSuperclass(cls);
//定义代理逻辑对象为当前对象
enhancer.setCallback(this);
return enhancer.create();
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("增强了");
Object o1 = methodProxy.invokeSuper(o, objects);
return o1;
}
}
public static void main(String[] args) {
CglibDemoE cglibDemoE = new CglibDemoE();
SayHello proxy = (SayHello) cglibDemoE.getProxy(SayHello.class);
proxy.sayHello();
}
}
JDK 动态代理使用的是反射技术,被代理的类要实现方法接口。
CGLIB 动态代理使用的是字节码增强技术,被代理的类不用实现方法接口
Spring Bean
-
Spring Bean的作用域
Singleton:唯一bean实例
prototype: 每次请求都会创建一个新的bean
request:一次请求期间一个bean
session:一个会话期间一个bean -
Spring 中的单例 bean 的线程安全问题了解吗?
单例bean,是所有线程都使用这一个bean,存在多线程操作安全问题。但是spring默认是单例bean,是因为大多数的bean是无状态的,就是只是controller,dao,service层使用,只操作方法。
无状态就是不会存储数据。且无状态就是只有方法,而方法对应着jvm的虚拟机栈。可以使用ThreadLocal来封装。
-
@Component 和 @Bean 的区别是什么?
作用对象不同:前者作用与类,而后者作用与方法。
@Component通常是通过类路径扫描来自动侦测以及自动装配到Spring容器中(我们可以使用 @ComponentScan 注解定义要扫描的路径从中找出标识了需要装配的类自动装配到 Spring 的 bean 容器中)。@Bean 注解通常是我们在标有该注解的方法中定义产生这个 bean,@Bean告诉了Spring这是某个类的示例,当我需要用它的时候还给我。 -
将一个类声明为Spring的 bean 的注解有哪些?
@Component :通用的注解,可标注任意类为 Spring 组件。如果一个Bean不知道属于哪个层,可以使用@Component 注解标注。@Repository : 对应持久层即 Dao 层,主要用于数据库相关操作
@Service : 对应服务层,主要涉及一些复杂的逻辑,需要用到 Dao层。
@Controller : 对应 Spring MVC 控制层,主要用户接受用户请求并调用 Service 层返回数据给前端页面
Spring MVC工作原理
- 客户端发送请求到DispacherServlet,
- 前端控制器,根据请求调用HanlerMapping,解析出请求对应的handler,也就是对应的Controller控制器。
- 之后就由HandlerAdapter适配器,执行具体的流程。
- 处理完毕就返回一个modelAndView对象,Model是数据,View是逻辑上的页面。
- 视图解析器通过View找到真正的页面view
- 前端控制器将数据渲染到视图,填充数据到request,响应数据。
spring事务
声明式事务,基于xml或者注解
-
事务隔离级别?
TransactionDefinition定义了5个
默认隔离级别,就是和数据库隔离级别保持一致,myslq就是可重复读,oracle则是读已提交其余就是读未提交,读已提交,可重复读、序列化
-
事务传播行为?
支持当前事务:
当前有事务,则加入当前事务、当前没有则新创建一个
当前有事务,加入,没有则已非事务运行。
当前有事务,加入,否则抛异常不支持当前事务
创建一个新的事务,当前有则挂起当前的
以非事务运行,当前有则挂起当前
以非事务运行,当前有则抛异常 -
@Transactional(rollbackFor = Exception.class)注解了解吗?
如果不加则只会有运行时异常抛出时才会回滚数据,加了就是Exception都会回滚