day05:断续学小知识的第五天
Day05 小小知识点
如何判断一个对象是否相等?
java中的基本数据类型判断是否相等,直接使用"=="
java中的引用类型的对象比较,需要重写equals方法和hashCode方法
重写equals方法的步骤:
1、先用“==”判断是否相等。
2、判断equals()方法的参数是否为null,如果为null,则返回false;因为当前对象不可能为null,如果为null,则不能调用其equals()方法,否则抛java.lang.NullPointerException异常。
3、当参数不为null,则如果两个对象的运行时类(通过getClass()获取)不相等,返回false,否则继续判断。
4、判断类的属性等是否对应相等。
什么时候重写hashCode?
重写equals方法时需要重写hashCode方法,主要是针对Map、Set等集合类型的使用;
hashcode有在创建某个类的散列表的时候才有用,需要根据hashcode值确认对象在散列表中的位置。
java中本质上是散列表的类常见的有HashMap,HashSet,HashTable
所以,如果一个对象一定不会在散列表中使用,那么是没有必要重写hashCode方法的。但一般情况下还是建议在重写equals方法的时候,同时也重写hashCode方法,从而防止在使用Set、Map等集合添加元素时,出现hashCode不等而带来的问题。
controller层如何获取 header里面的东西?
接口的参数中使用注解@RequestHeader
@RequestHeader("User-Agent") final String userAgent
接口的参数为HttpServletRequest 类型的 request
使用request.getHeader("User-Agent")获取Header中的内容
autowire注解和resource注解?
@Resource 根据byName进行装配,名称可以通过name属性指定。
如果没有指定name
当注解在字段上时,默认取name=字段名称装配。
当注解在setter方法上时,默认取name=属性名称装配。
- 当按照名称(by-name)装配未匹配时,按照类型(by-type)装配。
当显示指定name属性后,只能按照名称(by-name)装配。
@Autowire通过默认byType进行装配,如果使用按照名称(by-name)装配,需结合@Qualifier注解使用
如果@Autowired自动装配的环境比较复杂,自动装配无法通过一个注解[@Autowired]完成的时候、我们可以 使用@Qualifier(value="xx")去配置@Autowired的使用,指定一个唯一 的bean对象注入!
Java中aop如何实现?
主要步骤:
- 添加aop依赖
- 创建AOP实现类。并在类上面添加注解
@Aspect
和@Component
注解,@Aspect会将该类定义为一个切面类。 - 定义PointCut切点。一个切面中可以定义多个Pointcut。
@Pointcut
注解包括表达式和签名(一个空方法)。表达式是拿来确定切入点的位置的,就是通过一些规则来确定,哪些方法是要增强的,也就是要拦截哪些方法。 - 定义方法来实现切点要实现的业务逻辑。在方法上面需要指定AOP通知类型,通知类型的参数要指定为 切点,也就是哪些切点指定此方法。
相关资料:
https://blog.csdn.net/liboyang71/article/details/76432538
两个list如何实现交集?
- lisi中的retainAll()方法可以实现,listA.retainAll(listB)方***移除listB中不存在但listA中存在的元素,即会剩下listA与listB共同的元素
- CollectionUtils.intersection(listA, listB)
protected 与default的区别
protected:自身、子类及同一个包中类可以访问
default:同一包中的类可以访问
mybatis的作用?
MyBatis是持久层框架,它是支持JDBC的,简化了持久层开发。
- MyBatis相当灵活,不会对应用程序或者数据库的现有设计强加任何影响,SQL写在XML里,从程序代码中彻底分离,降低耦合度,便于统一管理和优化,并可重用。
- MyBatis 封装了底层 JDBC API 的调用细节,并能自动将结果集转换成 Java Bean 对象, 大大简化了 Java 数据库编程的重复工作。
- 因为 MyBatis 需要程序员自己去编写 sql 语句,程序员可以结合数据库自身的特点灵活控制 sql 语句,因此能够实现比 Hibernate 等全自动 orm 框架更高的查询效率,能够完成复杂查询。
@Autowire的注入过程?
记住:主要通过Bean的后置处理器来进行解析的。
在创建一个Spring上下文的时,在构造函数中进行注册AutowiredAnnotationBeanPostProcessor
在Bean的创建过程中进行解析
在实例化以后进行预解析(解析@Autowired标注的属性、方法,比如:把属性的类型、名称,属性所在类.....源数据原存起来)
在属性注入的时候进行真正的解析(拿到上一步缓存的源数据,去IoC容器中进行查找,并注入返回)
如果查询(按照类型)结果刚好为1个,就将该Bean装配给@Autowired指定的数据;
如果查询的结果不止一个,那么会根据 名称来查找;
如果上述查找结果为null,会抛出异常。
解决方法:使用required=false 来防止抛异常
bean有哪些生命周期回调方法?
生命周期的回到方法主要分2种,一种是在初始化的时候进行回调的方法,另一种是在销毁的时候进行回调的方法。
bean的生命周期方法的实现方式
3种实现方式
- 基于注解的实现方式,将注解标注到方法上面,就会在生命周期的过程中进行执行【@PostConstruct,@PreDestroy】
- 实现接口的方式【InitializingBean、DisposableBean】
- 通过配置Bean的属性的方式【@Bean(initMethod="init",destroyMethod="destroy")】
bean的生命周期【这东西看了N遍,也记不住= =】
bean从创建和销毁的整个过程,主要分为4步
实例化 createBeanInstance()
a. 通过反射推断构造函数,从而进行实例化
b.在实例化过程中 会使用实例工厂、静态工厂等来进行对bean的实例化工作
属性赋值 populateBean()
a. 解析自动装配(byName,byType),DI的体现
b.在此过程中,有循环依赖的概念
初始化 initializeBean()
a. 调用一系列XXXXAware的set方法,来进行初始化之前的准备工作。
- 调用 BeanNameAware 的 setBeanName 方法(可以获得 Bean 的名字)
- 调用BeanClassLoaderAware的setBeanClassLoader方法(可以获得ClassLoader对象的实例)
- 依次:BeanFactoryAware的setBeanFactory方法EnvironmentAware的setEnvironment方法等
b.调用初始化生命周期回调(三种)
c.如果bean实现了aop,会进行动态代理的创建
销毁
a.在spring容器关闭的时候进行调用
b.调用 销毁生命周期 回调