IOC,控制反转,将原本在程序中手动创建对象的控制权,交由Spring框架来管理。spring实现的方式是IOC容器,就是一个map,存放各种对象。
具体实现是依赖注入:将底层类作为参数传递给上层类,实现上层类对底层类的控制。有通过构造方法传递的,还有通过Set传递和接口传递。
控制反转容器:就是依赖注入需要注入上层类依赖的底层类,这些底层类的初始化就是容器做的。
https://www.zhihu.com/question/23277575/answer/169698662
AOP,面向切面编程,将与业务无关的逻辑封装起来,减少系统代码重复。
基于动态代理,代理的对象实现了某个接口,则使用JDK的JDKProxy。否则使用Cglib,生成一个被代理对象的子类
//JDKproxypackage 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(); }}
//Cglilbpackage 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的作用域
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都会回滚