在路上

一、基础
1、equals和==区别?

对于基本数据类型:其比较的是数值,只能使用“==”。

对于字符串:“==”比较两者的内存地址;equals比较两者的内容是否相等。

对于对象:“==”比较两者的内存地址;

                 当默认重写Object类的equals方法时,比较内存地址;当自己重写equals方法时,比较其内容是否相等。

【特别注意】Object类中的equals方法和“==”是一样的,没有区别,而String类,Integer类等等一些类,是重写了equals方法,才使得equals和“==不同”,所以,当自己创建类时,自动继承了Object的equals方法,要想实现不同的等于比较,必须重写equals方法。
"=="比"equal"运行速度快,因为"=="只是比较引用.


2、为什么重写equals需要重写hascode?

目的:保证同一个对象在equals相同的情况下hashcode值必定相同。如果两个对象相同(即用equals比较返回true),那么它们的hashCode值一定要相同;如果两个对象的hashCode相同,它们并不一定相同(即用equals比较返回false)。

主要是针对Map、Set等集合类型的使用:Map、Set等集合类型存放的对象必须是唯一的;集合类判断两个对象是否相等,是先判断HashCode返回值是否ture,如果HashCode返回true,还要再判断equals是否相等,只有两者都返回ture,才认为该两个对象是相等的,这样才能使得集合中存放的对象唯一

由于为了提高程序的效率才实现了hashcode方法,先进行hashcode的比较(采用了hash表,利用哈希算法(也叫散列算法)),如果不同,那没就不必在进行equals的比较了,这样就大大减少了equals比较的次数,这对比需要比较的数量很大的效率提高是很明显的,一个很好的例子就是在集合中的使用。

publicV put(K key, V value) {
  if(key == null)
   returnputForNullKey(value);
  inthash = hash(key.hashCode());
  inti = indexFor(hash, table.length);
  for(Entry<k , V> e = table[i]; e != null; e = e.next) {
   Object k;
   if(e.hash == hash && ((k = e.key) == key || key.equals(k))) {
    V oldValue = e.value;
    e.value = value;
    e.recordAccess(this);
    returnoldValue;
   }
  }
  modCount++;
  addEntry(hash, key, value, i);
  returnnull;
 }

源码中可以看出以下关键点:

  • HashMap有一个叫做Entry的内部类,它用来存储key-value对。
  • 上面的Entry对象是存储在一个叫做table的Entry数组中。
  • table的索引在逻辑上叫做“桶”(bucket),它存储了链表的第一个元素。
  • key的hashcode()方法用来找到Entry对象所在的桶。
  • 如果两个key有相同的hash值,他们会被放在table数组的同一个桶里面。
  • key的equals()方法用来确保key的唯一性。
  • value对象的equals()和hashcode()方法根本一点用也没有。

3、Java参数传递是传值还是传引用?

按值传递

Java 应用程序按引用传递对象(对象是按引用传递的)并不意味着 Java应用程序按引用传递参数。

Java 应用程序中的变量可以为以下两种类型之一:引用类型或基本类型。

Java中对象作为参数传递时,是把对象在内存中的地址拷贝了一份传给了参数

术语定义:按值传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的一个副本。因此,如果函数修改了该参数,仅改变副本,而原始值保持不变。按引用传递意味着当将一个参数传递给一个函数时,函数接收的是原始值的内存地址,而不是值的副本。因此,如果函数修改了该参数,调用代码中的原始值也随之改变。

1)引用是一种数据类型,保存了对象在内存中的地址,这种类型即不是我们平时所说的简单数据类型也不是类实例(对象);

2)不同的引用可能指向同一个对象,换句话说,一个对象可以有多个引用,即该类类型的变量。

理解地址:http://blog.sina.com.cn/s/blog_4b622a8e0100c1bo.html


4、面向对象的理解?抽象的理解?

面向对象的四大特征:封装、继承、多态、抽象。

封装是指属性私有化,提供公有方法访问私有属性。(增强安全性,简化编程)

继承是指自类自动共享父类的数据和方法的机制。(提高软件可重用性和可扩展性)

多态是指通过传递给父类对象引用不同的子类对象从而表现出不同的行为。(将接口和实现分离)

抽象是指一类具有相同属性和相似行为的具体对象的集合。


5、java和python心得?

Python一门强类型、动态型语言;而Java是一门强类型、静态型语言。(体现在Python变量无需指定类型,运行过程中可以随时改变变量的类型。

Python属于解释型语言;Java属于编译型语言。(体现在Python直接解释源代码,同时会分析语法;Java需要编译再解释。

从某种意义上看,Python比Java语言更具灵活性,而且代码简单,清晰明了,方便开发者理解,从这个层次去看,Python的优势是入门快、开发效率快,而Java语言则是强调整体性,统一性,注重模式开发,通过大量的类、接口的调用,实现功能以及业务。


6、java队列?

队列分为阻塞队列和非阻塞队列。其中阻塞队列的典型例子是BlockingQueue,非阻塞队列的典型例子是ConcurrentLinkedQueue。

非阻塞队列ConcurrentLinkedQueue是一个无锁的并发线程安全的队列。

阻塞队列:要想要实现阻塞功能,需要调用put(e) take() 方法。当不满足约束条件时,会阻塞线程。

ArrayBlockingQueue:基于数组实现的一个阻塞队列,在创建ArrayBlockingQueue对象时必须制定容量大小。并且可以指定公平性与非公平性,默认情况下为非公平的,即不保证等待时间最长的队列最优先能够访问队列。

LinkedBlockingQueue:基于链表实现的一个阻塞队列,在创建LinkedBlockingQueue对象时如果不指定容量大小,则默认大小为Integer.MAX_VALUE。

PriorityBlockingQueue:以上2种队列都是先进先出队列,而PriorityBlockingQueue却不是,它会按照元素的优先级对元素进行排序,按照优先级顺序出队,每次出队的元素都是优先级最高的元素。注意,此阻塞队列为无界阻塞队列,即容量没有上限(通过源码就可以知道,它没有容器满的信号标志),前面2种都是有界队列。

DelayQueue:基于PriorityQueue,一种延时阻塞队列,DelayQueue中的元素只有当其指定的延迟时间到了,才能够从队列中获取到该元素。DelayQueue也是一个无界队列,因此往队列中插入数据的操作(生产者)永远不会被阻塞,而只有获取数据的操作(消费者)才会被阻塞。

http://www.cnblogs.com/end/archive/2012/10/25/2738493.html

7、并发队列ConcurrentLinkedQueue和阻塞队列LinkedBlockingQueue

ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部,当我们获取一个元素时,它会返回队列头部的元素。

LinkedBlockingQueue实现是线程安全的,实现了先进先出等特性,是作为生产者消费者的首选,LinkedBlockingQueue 可以指定容量,也可以不指定,不指定的话,默认最大是Integer.MAX_VALUE,其中主要用到put和take方法,put方法在队列满的时候会阻塞直到有队列成员被消费,take方法在队列空的时候会阻塞,直到有队列成员被放进来。

另判断队列是否为空:ConcurrentLinkedQueue的API原来.size()是要遍历一遍集合的,难怪那么慢,所以尽量要避免用size而改用isEmpty().

并行和并发区别

1、并行是指两者同时执行一件事,比如赛跑,两个人都在不停的往前跑;
2、并发是指资源有限的情况下,两者交替轮流使用资源,比如一段路(单核CPU资源)同时只能过一个人,A走一段后,让给B,B用完继续给A ,交替使用,目的是提高效率

8、消息队列(mq

Redis、RabbitMQ、ZeroMQ、ActiveMQ、Jafka/Kafka

9、常量池存放什么数据,有什么特点?

存放基本类型常量和字符串常量。

常量池中的值只会被第一次赋值,其余的直接调用,所以其内存地址相同。

eg:String s1 = "china"; String ss1 = new String("china"); 

对于通过 new 产生一个字符串(假设为 ”china” )时,会先去常量池中查找是否已经有了 ”china” 对象,如果没有则在常量池中创建一个此字符串对象,然后堆中再创建一个常量池中此 ”china” 对象的拷贝对象。

好处:常量池是为了避免频繁的创建和销毁对象而影响系统性能,其实现了对象的共享。例如字符串常量池,在编译阶段就把所有的字符串文字放到一个常量池中。
1)节省内存空间:常量池中所有相同的字符串常量被合并,只占用一个空间。
2)节省运行时间:比较字符串时,==比equals()快。对于两个引用变量,只用==判断引用是否相等,也就可以判断实际值是否相等。

堆、栈、常量池、方法区介绍:http://www.cnblogs.com/w-wfy/p/6412593.html

(数据共享)对于栈和常量池中的数据可以共享(具有多个引用对象),对于堆中的对象不可以共享(一个引用对象)。         

(线程共享)比如:同一个进程的多个线程堆栈共享状况哪个描述正确?线程共享堆,但是每个线程有自己的寄存器和栈。

10、Lock和synchronized

  1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现;
  2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;
          而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁;
  3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;
  4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。
  5)Lock可以提高多个线程进行读操作的效率。

11、ArrayList和LinkedList区别?

1)ArrayList是实现了基于动态数组的数据结构将对象放在连续的位置中;LinkedList基于链表的数据结构将对象放在独立的空间中,而且在每个空间中还保存下一个链接的索引。
2)对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3)对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。这一点要看实际情况的。若只对单条数据插入或删除,ArrayList的速度反而优于LinkedList。但若是批量随机的插入删除数据,LinkedList的速度大大优于ArrayList. 因为ArrayList每插入一条数据,要移动插入点及之后的所有数据。  

有些说法认为LinkedList做插入和删除更快,这种说法其实是不准确的:

(1)LinkedList做插入、删除的时候,慢在寻址,快在只需要改变前后Entry的引用地址

(2)ArrayList做插入、删除的时候,慢在数组元素的批量copy,快在寻址

从这个分析看出,如果你十分确定你插入、删除的元素是在前半段,那么就使用LinkedList;如果你十分确定你删除、删除的元素在比较靠后的位置,那么可以考虑使用ArrayList。如果你不能确定你要做的插入、删除是在哪儿呢?那还是建议你使用LinkedList吧,因为一来LinkedList整体插入、删除的执行效率比较稳定,没有ArrayList这种越往后越快的情况;二来插入元素的时候,弄得不好ArrayList就要进行一次扩容,记住,ArrayList底层数组扩容是一个既消耗时间又消耗空间的操作。

ArrayList原理:

默认初始容量为10的空列表,初始化时也可以自定义大小。

ArrayList每当向数组中添加元素时,都要去检查添加后元素的个数是否会超出当前数组的长度,如果超出,数组将会进行扩容(创建新数组,将原数组数据向新数组重新拷贝,每次数组容量的增长大约是其原容量的1.5倍),以满足添加数据的需求。

最最想要提出的一点是:ArrayList使用for循环优于foreach;LinkedList一定要用foreach循环。如果使用普通for循环遍历LinkedList,其遍历速度将慢得令人发指。

for:for (int i = 0; i < list.size(); i++){......}

foreach:for (Integer i : list){......}

扩展:CopyOnWriteArrayList线程安全,适用于读操作远多于修改操作的并发场景中。

12、HashMap和HashTable区别和使用场景?

hashmap不是线程安全的,即不提供同步机制 ;允许插入空key和空value。

hashtable是线程安全的,即hashtable的方法都提供了同步机制;hashmap允许。

13、线程安全?

线程安全就是多线程访问时,采用了加锁机制,当一个线程访问该类的某个数据时,进行保护,其他线程不能进行访问直到该线程读取完,其他线程才可使用。不会出现数据不一致或者数据污染。

线程不安全就是不提供数据访问保护,多线程先后更改数据会产生数据不一致或者数据污染的情况。

一般使用synchronized关键字加锁同步控制,来解决线程不安全问题。

线程安全的集合对象:

  • ArrayList线程不安全,Vector线程安全;
  • HashMap线程不安全,HashTable线程安全;
  • StringBuilder线程不安全,StringBuffer线程安全。

14、单例的饿汉模式和懒汉模式?

饿汉模式的特点是加载类时比较慢,但运行时获取对象的速度比较快,线程安全。饿汉式是线程安全的,在类创建的同时就已经创建好一个静态的对象供系统使用,以后不在改变。

懒汉模式的特点是加载类时比较快,但是在运行时获取对象的速度比较慢,线程不安全, 懒汉式如果在创建实例对象时不加上synchronized则会导致对象的访问不是线程安全的。

推荐使用饿汉式,考虑到性能懒汉式。

15、二叉树的遍历?


16、线程的sleep和wait区别?分别属于哪个类里的?为什么

sleep()是Thread的静态方法,让程序暂停执行指定的时间,让出cpu给其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。在调用sleep()方法的过程中,线程不会释放对象锁。

wait()方法,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备。获取对象锁进入运行状态。

sleep与wait的不同点是:

1)sleep()方法属于Thread类中的;wait()方法属于Object类中的。

2)sleep()并不释放锁。obj.wait会使线程进入obj对象的等待集合中并等待唤醒,wait()释放锁然后由notify()持有该锁来唤醒。

3)wait,notify和notifyAll只能在同步控制方法或者同步控制块里面使用,而sleep可以在任何地方使用。

4)sleep必须捕获异常,而wait,notify和notifyAll不需要捕获异常。

相同点:wait()和sleep()都可以通过interrupt()方法打断线程的暂停状态,从而使线程立刻抛出InterruptedException。但是wait()还可以用notify()直接唤起。

为什么wait()、notify()、notifyAll()被定义在Object类中?

我们知道被任意对象调用的方法是定义在object类中。

这些方法在操作同步线程时,都必须要标识它们操作线程的锁,只有同一个锁上的被等待线程,可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。而锁可以是任意对象。任意对象调用的方法是定义在object类中的。

简单说:因为synchronized中的这把锁可以是任意对象,所以任意对象都可以调用wait()和notify();所以wait和notify属于Object。

17、Socket和WebSocket基于的协议?

Socket基于TCP实现自己的通信协议。

WebSocket是为解决客户端与服务端实时通信而产生的技术。其本质是先通过HTTP/HTTPS协议进行握手后创建一个用于交换数据的TCP连接,此后服务端与客户端通过此TCP连接进行实时通信。

HTTP是基于传输层的TCP协议。

应用层协议(常用):HTTP、RTSP、FTP 
传输层协议:TCP、UDP

18、全局变量和静态变量的区别?

全局变量本身就是静态存储方式, 静态全局变量当然也是静态存储方式。 这两者在存储方式上并无不同。

这两者的区别在于非静态全局变量的作用域是整个源程序, 当一个源程序由多个源文件组成时,非静态的全局变量在各个源文件中都是有效的。 而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。由于静态全局变量的作用域局限于一个源文件内,只能为该源文件内的函数公用, 因此可以避免在其它源文件中引起错误。

结论:静态变量只是缩小了访问该变量的作用域,而不能防止并发操作。

19、缓存

所谓缓存,就是将程序或系统经常要调用的对象存在内存中,以便其使用时可以快速调用,不必再去创建新的重复的实例。这样做可以减少系统开销,提高系统效率。

缓存中间件:

Ehcache:是一个纯java的在进程中的缓存,它具有以下特性:快速,简单,为Hibernate2.1充当可插入的缓存,最小的依赖性,全面的文档和测试。

OSCache:缓存任何对象,你可以不受限制的缓存部分jsp页面或HTTP请求,任何java对象都可以缓存。

Memcached :是“分布式”的内存对象缓存系统。

Cacheonix – 高性能Java分布式缓存系统。

JBoss Cache – 基于事物的Java缓存框架。


19、Java GC机制

主要从三个方面回答:GC是针对什么对象进行回收(可达性分析法),什么时候开始GC(当新生代满了会进行Minor GC,升到老年代的对象大于老年代剩余空间时会进行Major GC),GC做什么(新生代采用复制算法,老年代采用标记-清除或标记-整理算法),感觉回答这些就差不多了,也可以补充一下可以调优的参数(-XX:newRatio,-Xms,-Xmx等等)。

20、Java创建对象有哪几种

大概有四种—new、工厂模式、反射和克隆,不过这个问题有可能衍生出关于设计模式,反射,深克隆,浅克隆等一系列问题。。。

21、悲观锁和乐观锁区别,乐观锁适用于什么情况

悲观锁,就是总觉得有刁民想害朕,每次访问数据的时候都觉得会有别人修改它,所以每次拿数据时都会上锁,确保在自己使用的过程中不会被他人访问。乐观锁就是很单纯,心态好,所以每次拿数据的时候都不会上锁,只是在更新数据的时候去判断该数据是否被别人修改过。
大多数的关系数据库写入操作都是基于悲观锁,缺点在于如果持有锁的客户端运行的很慢,那么等待解锁的客户端被阻塞的时间就越长。Redis的事务是基于乐观锁的机制,不会在执行WATCH命令时对数据进行加锁,只是会在数据已经被其他客户端抢先修改了的情况下,通知执行WATCH命令的客户端。乐观锁适用于读多写少的情况,因为在写操作比较频繁的时候,会不断地retry,从而降低性能。

22、使用“+”拼接字符串还是使用StringBuilder和StringBuffer

StringBuffer和StringBuilder原理一样,无非是在底层维护了一个char数组,每次append的时候就往char数组里面放字符而已,在最终sb.toString()的时候,用一个new String()方法把char数组里面的内容都转成String,这样,整个过程中只产生了一个StringBuilder对象与一个String对象,非常节省空间。StringBuilder唯一的性能损耗点在于char数组不够的时候需要进行扩容,扩容需要进行数组拷贝,一定程度上降低了效率。

编译器每次碰到”+”的时候,会new一个StringBuilder出来,接着调用append方法,在调用toString方法,生成新字符串虽然说不要用”+”拼接字符串,因为会产生大量的无用StringBuilder对象,但也不是不可以,就这种连续+的情况,实际上编译的时候JVM会只产生一个StringBuilder并连续append等号后面的字符串。


二、数据库
1、怎么防止sql注入?

1)绑定变量,采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。

凡涉及到执行的SQL中有变量时,用JDBC(或者其他数据持久层)提供的如:PreparedStatement就可以 ,切记不要用拼接字符串的方法就可以了。

使用好处: (1).代码的可读性和可维护性. (2).PreparedStatement尽最大可能提高性能. (3).最重要的一点是极大地提高了安全性. 

原理: sql注入只对sql语句的准备(编译)过程有破坏作用 ,而PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理, 而不再对sql语句进行解析,准备,因此也就避免了sql注入问题.

2) 使用正则表达式过滤传入的参数。

3)检查变量数据类型和格式。只要是有固定格式的变量,在SQL语句执行前,应该严格按照固定格式去检查,确保变量是我们预想的格式(例如int类型id,邮箱格式)。

4)使用javascript在客户端进行不安全字符屏蔽,检查是否含有”‘”,”\\”,”/”。

5)数据库信息加密安全。


2、大数据/高并发访问数据库的优化?

1)数据缓存-内存机制

2)数据库结构的设计

能够用数字类型的字段尽量选择数字类型而不用字符串类型,这会降低查询和连接的性能,并会增加存储开销。

对于不可变字符类型char和可变字符类型varchar,char查询快,但是耗存储空间,varchar查询相对慢一些但是节省存储空间。例如用户名、密码等长度变化不大的字段可以选择CHAR。

字段的长度在最大限度的满足可能的需要的前提下,应该尽可能的设得短一些,这样可以提高查询的效率,而且在建立索引的时候也可以减少资源的消耗。

3)查询优化

保证在实现功能的基础上,尽量减少对数据库的访问次数;通过搜索参数,尽量减少对表的访问行数,最小化结果集,从而减轻网络负担;能够分开的操作尽量分开处理,提高每次的响应速度;在数据窗口使用SQL时,尽量把使用的索引放在选择的首列;算法的结构尽量简单;在查询时,不要过多地使用通配符如SELECT * FROM T1语句,要用到几列就选择几列如:SELECT COL1,COL2 FROM T1;在可能的情况下尽量限制尽量结果集行数如:SELECT TOP 300 COL1,COL2,COL3 FROM T1,因为某些情况下用户是不需要那么多的数据的。   

4)建立索引

维护被索引列的唯一性和提供快速访问表中数据的策略。

怎么建立索引?


5)使用负载均衡技术

当网站面临大规模访问时,用户的请求会通过负载均衡程序,根据不同服务器的繁忙和资源情况,自动分配到处理性能最优的服务器上,从而将大规模用户产生的高并发访问均衡地分流到各个服务器上。这样就能大大减轻单台服务器处理高并发请求,确保整个网站系统面临高负载时的可靠性。

3、数据库事物管理:多个表更新,某个表出错回滚机制?

在与数据库操作时,如果执行多条更新的SQL语句(如:update或insert语句),在执行某条后如果出现异常或电脑断电,则后面的SQL语句执行不了,这时候设定我们自己提交SQL语句,不让JDBC自动提交。

conn.setAutoCommit(false);--excute sql--conn.commit();--conn.setAutoCommit(true);

执行代码位于try中,如果执行sql过程中发生异常,需要在catch中进行回滚:conn.rollback();conn.setAutoCommit(true);

三、Spring
1、Spring工作流程

1) 用户向服务器发送请求,请求被Spring 前端控制Servelt DispatcherServlet捕获;
2) DispatcherServlet对请求URL进行解析,得到请求资源标识符(URI)。然后根据该URI,调用HandlerMapping获得该Handler配置的所有相关的对象(包括Handler对象以及Handler对象对应的拦截器),最后以HandlerExecutionChain对象的形式返回;
3) DispatcherServlet 根据获得的Handler,选择一个合适的HandlerAdapter。(附注:如果成功获得HandlerAdapter后,此时将开始执行拦截器的preHandler(...)方法)
4)  提取Request中的模型数据,填充Handler入参,开始执行Handler(Controller)。 在填充Handler的入参过程中,根据你的配置,Spring将帮你做一些额外的工作:
      HttpMessageConveter: 将请求消息(如Json、xml等数据)转换成一个对象,将对象转换为指定的响应信息
      数据转换:对请求消息进行数据转换。如String转换成Integer、Double等
      数据根式化:对请求消息进行数据格式化。 如将字符串转换成格式化数字或格式化日期等
      数据验证: 验证数据的有效性(长度、格式等),验证结果存储到BindingResult或Error中
5)  Handler执行完成后,向DispatcherServlet 返回一个ModelAndView对象;
6)  根据返回的ModelAndView,选择一个适合的ViewResolver(必须是已经注册到Spring容器中的ViewResolver)返回给DispatcherServlet ;
7) ViewResolver 结合Model和View,来渲染视图
8) 将渲染结果返回给客户端
Spring为什么要结合使用HandlerMapping以及HandlerAdapter来处理Handler?
符合面向对象中的单一职责原则,代码架构清晰,便于维护,最重要的是代码可复用性高。如HandlerAdapter可能会被用于处理多种Handler。

2、bean是单例还是多例?DispatcherServlet呢?Controller呢?

bean默认为单例(singleton),可配置为多例(prototype)

singleton:单例模式,当spring创建applicationContext容器的时候,spring会预初始化所有的该作用域实例,加上lazy-init就可以避免预处理;

prototype:原型模式,每次通过getBean获取该bean就会新产生一个实例,创建后spring将不再对其管理。

DispatcherServlet的核心本质:是一个Servlet

它的生命周期是随着容器的, 所以只有一个实例。

Controller默认是单例的。

建议:不要在controller中定义成员变量。;万一必须要定义一个非静态成员变量时候,则通过注解@Scope("prototype"),将其设置为多例模式。

3、一个bean需要调用另一个bean,需要怎么配置?

<bean id="bean_date" class="java.util.Date" /> 

1)ref

<bean id="bean_test" class="cn.qtone.test.HelloWorld"> 
    <ref  bean="另一个bean的id" />
</bean>

2)ref作属性

<bean id="bean_test" class="cn.qtone.test.HelloWorld"> 
    <constructor-arg   index="0"  ref="另一个bean的id"  />
</bean>

3)引用当前容器的bean

<ref  local=" ">

4)引用父容器的bean

<ref parent=""  />

4、Spring拦截器原理?


过滤器和拦截器的区别:

  ①拦截器是基于Java的反射机制的,而过滤器是基于函数回调。
  ②拦截器不依赖与servlet容器,过滤器依赖与servlet容器。
  ③拦截器只能对action请求起作用,而过滤器则可以对几乎所有的请求起作用。
  ④拦截器可以访问action上下文、值栈里的对象,而过滤器不能访问。
  ⑤在action的生命周期中,拦截器可以多次被调用,而过滤器只能在容器初始化时被调用一次。

  ⑥拦截器可以获取IOC容器中的各个bean,而过滤器就不行,这点很重要,在拦截器里注入一个service,可以调用业务逻辑。

5、AOP使用?

AOP的应用场景:权限,日志,处理异常,事务等等,个人理解就是把许多接口都要用的又和接口本身主要的业务逻辑无关的部分抽出来,写成一个切面,单独维护,比如权限验证。这样可以使接口符合“单一职责原则”,只关注主要的业务逻辑,也提高了代码的重用性。

6、Spring中用到的设计模式

工厂模式:IOC容器
代理模式:AOP
策略模式:在spring采取动态代理时,根据代理的类有无实现接口有JDK和CGLIB两种代理方式,就是采用策略模式实现的
单例模式:默认情况下spring中的bean只存在一个实例



四、Mybatis
1、Mybatis多个表查询


2、Mybatis如何进行分页?

Mybatis使用RowBounds对象进行分页,它是针对ResultSet结果集执行的内存分页,而非物理分页,可以在sql内直接书写带有物理分页的参数来完成物理分页功能,也可以使用分页插件来完成物理分页。

分页插件的基本原理是使用Mybatis提供的插件接口,实现自定义插件,在插件的拦截方法内拦截待执行的sql,然后重写sql,根据dialect方言,添加对应的物理分页语句和物理分页参数。

举例:select * from student,拦截sql后重写为:select t.* from (select * from student)t limit 0,10

3、如果一个SQL执行时间比较长怎么办?

可以利用pt-query-digest等工具分析慢查询日志,也可以用explain查看SQL的执行计划。具体可看我的另一篇博客MySQL调优

4、如果一张表中有上千万条数据应该怎么做分页

肯定不能直接limit,offset,主要就是要想办法避免在数据量大时扫描过多的记录。具体可看我的另一篇博客【译】优化MySQL中的分页

五、规范

1、webservice(SOAP/RESTFUL)和HTTP?

Http定义了与服务器交互的不同方法,最基本的方法有4种,分别是GET,POST,PUT,DELETE,就对应着对这个资源的 4个操作。
Webservice的一个最基本的目的就是提供在各个不同平台的不同应用系统的协同工作能力。 Web service 就是一个应用程序,它向外界暴露出一个能够通过Web进行调用的API。
区别:
1)HTTPService基于http协议;而WebService基于soap协议。

2)在处理数据上HTTP(超文本传输协议)效率较高,传输的都是字符串;WebService包装成了更复杂的对象

WebService的两种方式SOAP和REST比较 ?

soap:(Simple Object Access Protocol,SOAP)简单对象访问协议,是一种基于 XML 的协议,以xml作为消息载体。soap属于复杂的、重量级的协议。
rest:(Representational State Transfer)表述性状态转移,可以完全通过HTTP协议实现还可以利用缓存Cache来提高响应速度,面向资源的接口设计;无状态
soap比rest更为成熟,更为安全;rest比soap易用性好,效率更高。

2、什么是rest规范

全新的Web开发过程中的思维方式: 针对Web应用而设计,通过URL来设计系统结构。其目的是为了降低开发的复杂性,提高系统的可伸缩性(因为所有的操作都是无状态的)。

REST是基于Http协议的,任何对资源的操作行为都是通过Http协议来实现。

REST提出设计概念和准则为:

      1)网络上的所有事物都可以被抽象为资源(resource)
      2)每一个资源都有唯一的资源标识(resource identifier),对资源的操作不会改变这些标识
      3)所有的操作都是无状态的

3、微服务?

采用一组服务的方式来构建一个应用,服务独立部署在不同的进程中,不同服务通过一些轻量级交互机制来通信,例如 RPC、HTTP 等,服务可独立扩展伸缩,每个服务定义了明确的边界,不同的服务甚至可以采用不同的编程语言来实现,由独立的团队来维护。

采用微服务架构面临的第一个问题就是如何将一个单一应用拆分为多个服务。一般的原则是,单一服务提供的功能是可以独立被替换和升级的。

1)通过服务实现组件化。将应用拆散为一系列的服务运行在不同的进程中,那么单一服务的局部变化只需重新部署对应的服务进程。

2)按业务能力来划分服务与组织团队。

3)服务即产品。开发团队对软件在生产环境的运行负全部责任。

4)去中心统一化。微服务的架构意味着,你可以针对不同的业务服务特征选择不同的技术平台或产品,有针对性的解决具体的业务问题。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值