2019年9月4日远景能源面试记录
面试题记录
还有自己找的一些答案
1、Bean的生命周期
Spring IOC容器对Bean的生命周期进行管理的过程如下:
1、通过构造器或者工厂方法创建Bean实例;
2、为Bean的属性设置值和对其他Bean的引用;
3、调用Bean的初始化方法;
4、Bean可以使用;
5、当容器关闭时,调用Bean的销毁方法
2、动态代理的实现
JDK:
public class ProxyHandler implements InvocationHandler {
private Object proxied;
public ProxyHandler(Object proxied){
this.proxied = proxied;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args ) throws Throwable
{
//在转调具体目标对象之前,可以执行一些功能处理
System.out.println("before");
//转调具体目标对象的方法
Object object = method.invoke( proxied, args);
//在转调具体目标对象之后,可以执行一些功能处理
System.out.println("after");
return object;
}
}
public class DynamicProxy {
public static void main( String args[] )
{
RealSubject real = new RealSubject();
/**
* 一共有三个参数:
* 1、第一个参数是被代理类的类加载器,通过此类加载器将代理类加载入jvm中;
*2、第二个参数则是被代理类所实现的所有接口,
* 3、第三个参数则是真正的扩展,使用动态代理的主要目的就是能够对原方法进行扩展,尤其是对于大部分方法都具有的重复方法(例如记录日志),
* 可以理解为面向切面编程中的增强.
*/
Subject proxySubject = (Subject) Proxy.newProxyInstance(Subject.class.getClassLoader(),
new Class[]{Subject.class},
new ProxyHandler(real));
proxySubject.doSomething();
//write proxySubject class binary data to file
}
}
1、代理类实现InvocationHandler接口,重写invoke方法,实现代理逻辑,传入被代理对象
2、通过Proxy类的newProxyInstance方法创建代理实现
cglib:
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;
public class CglibDynamicProxy implements MethodInterceptor {
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("这是前处理==============");
methodProxy.invokeSuper(o, objects);
System.out.println("这是前处理==============");
return null;
}
}
import net.sf.cglib.proxy.Enhancer;
public class CglibProxyDemo {
public static void main(String[] args) {
/**
* 创建字节码增强器
*/
Enhancer enhancer = new Enhancer();
/**
* 被代理类设置为字节码增强父类,cglib使用的是继承方式去创建代理类
*/
enhancer.setSuperclass(UserImpl.class);
/**
* 设置字节码增强器回调方法。对于代理类上所有方法的调用,都会调用CallBack,
* 而Callback则需要实现intercept()方法进行拦截
*/
enhancer.setCallback(new CglibDynamicProxy());
/*
* 创建代理实例
*/
UserImpl userImpl = (UserImpl)enhancer.create();
userImpl.work("敲代码");
}
1、代理类实现MethodInterceptor接口,重写intercept方法;
2、创建字节码增强器,在字节码增强器中设置字节码增强父类(传入被代理类),设置回调方法(传入代理类);
3、通过字节码增强器创建代理实现。
3、四种线程池
固定线程数的线程池(newFixedThreadPool)
这种线程池里面的线程被设计成存放固定数量的线程,具体线程数可以考虑为CPU核数*N(N可大可小,取决于并发的线程数,计算机可用的硬件资源等)
这种线程池不会拒绝任务,而且不会开辟新的线程,也不会因为线程的长时间不使用而销毁线程。这是典型的生产者----消费者问题,这种线程池适合用在稳定且固定的并发场景,比如服务器
缓存的线程池(newCachedThreadPool)
核心池大小为0,线程池最大线程数目为最大整型,这意味着所有的任务一提交就会加入到阻塞队列中
单个线程的线程池(newSingleThreadExecutor)
固定个数的线程池(newScheduledThreadPool)
相比于第一个固定个数的线程池强大在 ①可以执行延时任务,②也可以执行带有返回值的任务
线程池不允许使用Executors去创建,而是通过ThreadPoolExecutor的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。
说明:Executors返回的线程池对象的弊端如下:
1) FixedThreadPool和SingleThreadPool: 允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求,从而导致OOM。
2) CachedThreadPool: 允许的创建线程数量为Integer.MAX_VALUE,可能会创建大量的线程,从而导致OOM。
4、阻塞队列
阻塞队列首先是一个队列,当队列是空的时候,从队列获取元素的操作将会被阻塞,当队列是满的时候,从队列插入元素的操作将会被阻塞。
(1)ArrayBlockingQueue:由数组结构组成的有界阻塞队列。
(2)LinkedBlockingQueue:由链表结果组成的有界阻塞队列(默认大小Integer.MAX_VALUE)阻塞队列。
(3)SychronousQueue:不存储元素的阻塞队列,也即单个元素队列。
(4)PriorityBlockingQueue:支持优先级排序的无界阻塞队列。
(5)DelayQueue:使用优先级队列实现的延迟无界阻塞队列。
(6)LinkedTransferQueue:由链表结构组成的无界阻塞队列。
(7)LinkedBlockingDeque:由链表结构组成的双端阻塞队列。
5、MyBatis组件
SqlSessionFactoryBuilder (构造器):它会根据配置或者代码来生成 SqISessionFactory,采用的是分步构建的 Builder 模式。
SqlSessionFactory (工厂接口):依靠它来生成 SqlSession,使用的是工厂模式。
SqlSession (会话): 一个既可以发送 SQL 执行返回结果,也可以获取 Mapper 的接 口。在现有的技术中, 一般我们会让其在业务逻辑代码中“消失”,而使用的是 MyBatis 提供的 SQLMapper 接口编程技术,它能提高代码的可读性和可维护性。
SqlSession提供select/insert/update/delete方法
SqlSession重要的四个对象
1)Execute:调度执行StatementHandler、ParmmeterHandler、ResultHandler执行相应的SQL语句;
2)StatementHandler:使用数据库中Statement(PrepareStatement)执行操作,即底层是封装好了的prepareStatement;
3)ParammeterHandler:处理SQL参数;
4)ResultHandler:结果集ResultSet封装处理返回。
SQL Mapper (映射器): MyBatis 新设计存在的组件,它由一个 Java 接口和 XML 文件(或注解)构成,需要给出对应的 SQL 和映射规则。它负责发送SQL去执行, 并返回结果
6、MySQL锁机制
行级锁
行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。行级锁分为共享锁和排他锁.
特点
开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高。
表级锁
表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁定。表级锁定分为共享锁和排他锁.
特点
开销小,加锁快;不会出现死锁;锁定粒度大,发出锁冲突的概率最高,并发度最低。
悲观锁,
正如其名,它指的是对数据被外界(包括本系统当前的其他事务,以及来自外部系统的事务处理)修改持保守态度(悲观),因此,在整个数据处理过程中,将数据处于锁定状态。 悲观锁的实现,往往依靠数据库提供的锁机制 (也只有数据库层提供的锁机制才能真正保证数据访问的排他性,否则,即使在本系统中实现了加锁机制,也无法保证外部系统不会修改数据)
乐观锁( Optimistic Locking )
相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,所以在数据进行提交更新的时候,才会正式对数据的冲突与否进行检测,如果发现冲突了,则让返回用户错误的信息,让用户决定如何去做。
相对于悲观锁,在对数据库进行处理的时候,乐观锁并不会使用数据库提供的锁机制。一般的实现乐观锁的方式就是记录数据版本。
实现数据版本有两种方式,第一种是使用版本号,第二种是使用时间戳。
乐观锁使用CAS(Compare And Swep)操作保证数据一致性
7、过滤器和拦截器的区别
Filter 接口定义在 javax.servlet 包中 | 接口 HandlerInterceptor 定义在org.springframework.web.servlet 包中 | |
Filter 定义在 web.xml 中 | ||
Filter在只在 Servlet 前后起作用。Filters 通常将 请求和响应(request/response) 当做黑盒子,Filter 通常不考虑servlet 的实现。 | 拦截器能够深入到方法前后、异常抛出前后等,因此拦截器的使用具有更大的弹性。允许用户介入(hook into)请求的生命周期,在请求过程中获取信息,Interceptor 通常和请求更加耦合。 | 在Spring构架的程序中,要优先使用拦截器。几乎所有 Filter 能够做的事情, interceptor 都能够轻松的实现 |
Filter 是 Servlet 规范规定的。 | 而拦截器既可以用于Web程序,也可以用于Application、Swing程序中。 | 使用范围不同 |
Filter 是在 Servlet 规范中定义的,是 Servlet 容器支持的。 | 而拦截器是在 Spring容器内的,是Spring框架支持的。 | 规范不同 |
Filter 不能够使用 Spring 容器资源 | 拦截器是一个Spring的组件,归Spring管理,配置在Spring文件中,因此能使用Spring里的任何资源、对象,例如 Service对象、数据源、事务管理等,通过IoC注入到拦截器即可 | Spring 中使用 interceptor 更容易 |
Filter 是被 Server(like Tomcat) 调用 | Interceptor 是被 Spring 调用 | 因此 Filter 总是优先于 Interceptor 执行 |
8、HTTP中GET,POST和PUT的区别
RESTFUL特点包括:
1、每一个URI代表1种资源;
2、客户端使用GET、POST、PUT、DELETE4个表示操作方式的动词对服务端资源进行操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源;
3、通过操作资源的表现形式来操作资源;
4、资源的表现形式是XML或者HTML;
5、客户端与服务端之间的交互在请求之间是无状态的,从客户端到服务端的每个请求都必须包含理解请求所必需的信息。
幂等性概念:幂等通俗来说是指不管进行多少次重复操作,都是实现相同的结果。
GET,PUT,DELETE都是幂等操作,而POST不是,以下进行分析:
PUT请求:如果两个请求相同,后一个请求会把第一个请求覆盖掉。(所以PUT用来改资源)
Post请求:后一个请求不会把第一个请求覆盖掉。(所以Post用来增资源)
9、数据库连接池
1 dbcp
dbcp可能是使用最多的开源连接池
这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有
优缺点:稳定性还是可以,不过速度稍慢,在大并发量的压力下稳定性有所下降,此外不提供连接池监控
2 c3p0
c3p0是另外一个开源的连接池,在业界也是比较有名的,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。
优缺点:连接池的持续运行的稳定性相当不错,在大并发量的压力下稳定性也有一定保证,此外不提供连接池监控。
3 proxool
proxool这个连接池可能用到的人比较少,但也有一定知名度,这个连接池可以设置最大和最小连接,连接等待时间等,基本功能都有。
优缺点:稳定性有一定问题,有一个需要长时间跑批的任务场景任务,优势--连接池监控
4.Druid
Druid是Java语言中最好的数据库连接池。Druid能够提供强大的监控和扩展功能。
参考链接:
https://blog.csdn.net/Doctor_LY/article/details/82993483
https://www.cnblogs.com/junzi2099/p/8022058.html#_label2
https://blog.csdn.net/qq_37933685/article/details/80717515
https://blog.csdn.net/qq_33082731/article/details/74230813
https://www.cnblogs.com/zhuleixiao/p/8974982.html
《阿里巴巴Java开发手册》