目录
一、try-catch-finally内部代码执行顺序
二、synchronized和Lock区别是什么?
三、线程休眠(阻塞)的几种方法
休眠方法之间的联系与区别
四、notify是随机唤醒还是顺序唤醒
五、maven是怎样解决依赖冲突的
六、Spring Boot的starter机制是什么
java基础部分易混淆问题总结
七、Springboot自动配置具体实现步骤
八、Spring的@Autowired注解为什么用在接口上
九、Spring Bean的生命周期
十、Java动态代理InvocationHandler和Proxy
1、Proxy
2、InvocationHandler
3、实例
一、try-catch-finally内部代码执行顺序
讯享网执行顺序:
先执行try中代码,如果没异常就在try中return语句执行之后,返回之前跳转执行finally中代码。
如果有异常,就在遇到异常之后跳转执行catch中代码,并在catch中return语句执行之后,返回之前跳转执行finally中代码。
但需要注意的是,在执行finally中代码之前,try中return的值已经确定,例如若try中代码最后为return a+b,此时a=1,b=2。则程序会将3保存起来,不管finally中对a、b做什么改变,最终都会返回3。但若干return的数据时引用数据类型,则在finally中对该引用数据类型的属性值的改变起作用。
finally中如果包含return,那么程序将在这里返回,而不是try或catch中的return返回,返回值就不是try或catch中保存的返回值了。
二、synchronized和Lock区别是什么?
1、类型不同:synchronized是一个关键字,而lock是一个接口,例如ReentrantLock类就是其一个实现类。
2、获取锁和释放锁方式不同:synchronized是隐式的加锁,会自动加锁和释放锁。lock是显示的加锁,在使用之前需要先创建一个 Lock 对象,然后使用lock()和unlock()方法手动加锁和释放锁。
3、用法不同:synchronized 可用来方法和代码块,而 Lock 只能用在代码块上。
4、锁类型不同:synchronized 属于非公平锁,而 ReentrantLock 既可以是公平锁也可以是非公平锁(默认非公平)。 公平锁指多个线程按照先到先得的策略获取锁。好处是所有线程都有机会获得锁,不会饿死。坏处是由于所有线程都会经历阻塞态,因此唤醒阻塞线程的开销会很大。 非公平锁指所有的线程拼运气,谁运气好,谁就获取到锁。好处是可以减少CPU唤醒线程的开销,整体的吞吐效率会高。坏处是可能会有线程长时间甚至永远获取不到锁,导致饿死。
5、响应中断不同:Lock 可以使用 lockInterruptibly 获取锁并响应中断指令,而 synchronized 不能响应中断,也就是如果发生了死锁,使用 synchronized 会一直等待下去,而使用 Lock 可以响应中断并释放锁,从而解决死锁的问题。
6、底层实现不同:synchronized采用的是monitor对象监视器,lock的底层原理是AQS。
参考来源:
http://t.csdn.cn/hUNow
三、线程休眠(阻塞)的几种方法
1、线程睡眠Thread.sleep
2、线程等待Object.wait
3、线程暂停LockSupport.park
休眠方法之间的联系与区别
1、sleep()和wait()以及park()都是可中断方法,但被中断后只有sleep()和wait()会收到中断异常。
2、sleep()后线程状态为TIMED_WAITING(限期等待),wait()以及park()后线程状态为WAITING(无限期等待)。
3、sleep()以及park()不会释放持有的锁,而wait()会释放持有的锁。
4、三个方法所属类不同。
5、wait()必须在同步方法中进行,sleep()不需要。
参考来源:http://t.csdn.cn/6A9k1

四、notify是随机唤醒还是顺序唤醒
notify 唤醒线程的规则是随机唤醒还是顺序唤醒取决于 JVM 的具体实现,作为主流的 HotSpot 虚拟机中的 notify 的唤醒规则是顺序的,也就是 notify 会按照线程的休眠顺序,依次唤醒线程。
五、maven是怎样解决依赖冲突的
1、路径最近者优先
相同jar不同版本,根据依赖的路径长短来决定引入哪个依赖。
该例中X(1.0)的路径长度为3,而X(2.0)的路径长度为2,因此X(2.0)会被解析使用。
2、第一声明原则
在pom.xml配置文件中,如果有两个名称相同,版本的不同依赖声明,先写的会生效,所以先声明自己要用的版本。这里的名称相同,版本不同的依赖声明,既可以是直接依赖,也可以是传递依赖。
六、Spring Boot的starter机制是什么
和自动配置一样,Spring Boot Starter的目的也是简化配置,而Spring Boot Starter解决的是依赖管理配置复杂的问题,有了它,当我需要构建一个Web应用程序时,不必再遍历所有的依赖包,一个一个地添加到项目的依赖管理中,而是只需要一个配置, 同理,如果想引入持久化功能,可以配置所有官方的starter都以spring-boot-starter-*的规则命名。
参考来源:https://zhuanlan.zhihu.com/p/
七、Springboot自动配置具体实现步骤
1.SpringBoot启动的时候加载主启动类,通过@EnableAutoConfiguration开启自动配置功能。
2.@EnableAutoConfiguration利用AutoConfigurationImportSelector给容器中导入一些组件。
3.通过protected List getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes)获取候选的配置和核心方法,扫描所有jar包类路径下"META-INF/spring.factories",通过@AutoConfigurationPackage自动配置包。
4.把扫描到的文件包装成Properties对象。
5.从properties中获取到EnableAutoConfiguration.class类名对应的值,并把他们添加在容器中。
6.整个过程就是将类路径下"META-INF/spring.factories"里面配置的所有EnableAutoConfiguration的值加入到容器中。
7.根据@Conditional注解中的条件判断,决定这个配置是否生效。
8.初始化Bean,自动配置完成。
总结
SpringBoot通过@EnableAutoConfiguration开启自动装配,通过 SpringFactoriesLoader 最终加载META-INF/spring.factories中的自动配置类实现自动装配,自动配置类其实就是通过@Conditional按需加载的配置类。

参考来源:https://blog.csdn.net/yanghang1122/article/details/
八、Spring的@Autowired注解为什么用在接口上
例如在Controller中使用@Autowired时,为什么是用在Service上而不是ServiceImpl上。
这里就要说到@Autowired的注入原理:@Autowired是Spring的注解,Autowired默认先按byType,如果发现找到多个bean,则再按照byName方式比对,如果还有多个bean,则报错Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException; 再来说Controller获取实例的过程:使用@Autowired,程序在spring的容器中查找类型时TestService的bean,刚好找到有且只有一个此类型的bean,即TestServiceImpl,所以就把testServiceImpl自动装配到了Controller的实例TestService中。
如果一个接口有多个实现类时,@Autowired需要结合@Qualifier("类名")使用,注:实现类的开头小写类名TestServiceImpl2->testServiceImpl2。
讯享网
问:为什么非要调用接口来多此一举,而不直接调用实现类serviceImpl的bean来得简单明了呢?
答:直接使用serviceImpl的bean是可以的,这样加一层接口的原因:1.AOP程序的思想,给别人调用的接口,调用这只想知道方法和功能,而对于这个方法内部逻辑实现并不关心。2.降低各个模块间的关联,实现松耦合、程序分成、最主要的体现了继承只能单继承,接口却可以多实现
参考来源:https://blog.csdn.net/m0_/article/details/
九、Spring Bean的生命周期
内容较多,结合着看:Springbean生命周期详解_爱吃巧克力的小男孩的博客-CSDN博客_springbean生命周期详解
十、Java动态代理InvocationHandler和Proxy
提到动态代理,就不得不提到其两个重要的类和接口InvocationHandler(接口)和Proxy(类),这一个类Proxy和接口InvocationHandler是我们实现动态代理的核心。
1、Proxy
首先简单梳理一下,假设存在一个被代理类Teacher,我们要生成其的代理类proxy,我们需要调用 Proxy 的 newProxyInstance 方法来生成代理类,而newProxyInstance方法有三个参数: 参数1 类加载器
ClassLoader classLoader = person.getClass().getClassLoader();
参数2 被代理对象实现的所有的接口的字节码数组
Class[] interfaces =person.getClass().getInterfaces();// {Court.class , ... , ...};
Class[] interfaces={Court.class};
参数3 执行处理器 用于定义方法的增强规则(加强后的方法)
InvocationHandler handler =new InvocationHandler(){} 这个参数3就是要将代理对象关联到InvocationHandler实现类对象上。
2、InvocationHandler
InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;当我们通过动态代理对象调用一个方法时候,这个方法的调用就会被转发到实现InvocationHandler接口类的invoke方法来调用,看如下invoke方法:
我们可以在这个invoke方法中对被代理对象的方法进行增强。
3、实例
- 首先我们定义一个接口People
讯享网
- 再定义一个Teacher类,实现People接口,这个类是真实的对象,也是我们的被代理类
- 现在我们要定义一个代理类的调用处理程序,每个代理类的调用处理程序都必须实现InvocationHandler接口,调用处理程序如下:
- 最后看一下主类
- 输出结果
参考来源:http://t.csdn.cn/i2HGd
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/8020.html