远景能源面试

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开发手册》

https://www.cnblogs.com/jian0110/p/9452592.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值