本帖最后由 朱龙华 于 2017-12-14 08:18 编辑
[size=10.5000pt]引言:学了几个月的java,收获很大,经历很多,从认识这个物质世界到进入电脑语言的世界,从世界上第一台计算机到互联网时代,世界在一步步缩小,而人也在一步步进步。学习java这段时间,对于我这种入行不久的小白来说,首选计算机语言java还是不错的,可能对于一些老程序员来说学习这些东西如鱼得水,时常阅读到大神讲述自己经历的时候,语言的概述都是一笔带过,很大一部分是把这些语言和一些框架结合,作为工具来写它们是这么帮助自己完成需求的,在我看来,他们在比我们资源缺乏的时代走到现在这一步,除了自身的毅力之外,也因为他们养成了很好的学习习惯,即使轻描淡写,依然让我感到敬畏,可以这么说,没有老一辈,就没有巨人的肩膀在我们面前。
[size=10.5000pt]从我学习的角度看,年轻人嘛,接收新事物的能力是不错,但是有句话说的好,好记性不如烂笔头,巨人也是从跬步开始滴,所以很早就开始做笔记,也一直坚持下来,收获挺多的,马上学完框架了,回顾了一下之前的内容,发现自己记录了一些老师或者同学们提到过的面试题,今天总结了一下,发上来大家一起参考吧,好东西,得用对地方。
[size=10.5000pt]其实另外我还想补充一点,我觉得最基本的,你在简历中写的那些你会的技术,最起码的在你脑中需要知道它是什么,有什么作用,有什么案例我可以使用,如果你给我需求我可以使用什么技术去解决,这样才能让别人相信你确实会这个技术,而不是课堂讲了,在你的认知中就会了,两者是不等价的,所以每当学习或使用一门技术时,带着问题去学,学完了多问问自己,这样才会对编程有大纲式思维,以后没有老师教,也可以自己学。
[size=10.5000pt]言归正传,开始一轮小面试,其中要自己脑补相关的问题,毕竟文章是死的,人是活的 - -
[size=10.5000pt]
1. 最近老师们都说很多面试之前需要手写JDK动态代理,这里我总结了一下,还扩展了CGLIB动态代理(扩展的看看就行)/** * 这是通用版JDK动态代理的模板类 * 1.接收目标对象,并扩大它的作用范围(声明到成员位置) * 2.写一个方法去返回代理对象 return Proxy.newProxyInstance(三个参数) * 3.方法中第三个参数是代理接口InvocationHandler对象,这个对象种又有一个方法invoke(三个参数)来实现方法增强 * 实现JDK动态代理可以有两种方法 * 1.可以使用匿名内部类的方式做 * 2.为了代码的整洁,这里使用实现invocationHandler接口的方式来实现 * @author zlh */
// 5.本类实现InvocationHandler接口 public class ProxyFactory implements InvocationHandler { // 2.将目标对象的作用范围扩大到全类 public Object target; // 1.接收目标对象(需要代理的对象),使用有参构造 public ProxyFactory(Object target) { this.target = target; };
// 3.创建一个方法返回动态代理实例(注意:这里不能使用静态修饰,因为我们的target目标对象是通过有参构造传递过来,如果直接静态调用就出错了) public Object createProxy() { // 4.使用JDK提供的代理类创建 方法实现代理 return Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), this); }
// 6.重写invoke方法 // 返回值是Object // 参数列表是:代理对象Object proxy,目标对象的方法 Method method,方法的参数Object[] args // 此处记得抛出异常 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 7.这里可以对切入点cart point和通知advice进行操作 System.err.println("切入点cart point和通知advice进行操作...");
// 8.调用我们原先的业务逻辑,执行 return method.invoke(target, args); }; }
====》
/** * 使用cglib代理进行目标对象的增强 * 1.有参构造接收目标对象,并扩大作用范围 * 2.创建方法返回CGLIB代理对象,里面使用Enhancer对象进行设置 * 3.创建enhancer增强者对象 * 3. * @author zlh */ public class CglibProxyFactory implements MethodInterceptor{ //1.接收目标对象并扩大作用域 private Object target; public CglibProxyFactory(Object target) { this.target=target; }
/** * 总体来说返回代理对象有两种解决方式: * 一:傻瓜式,一步步来 * 1.创建Enhancer增强者对象 * 2.设置目标对象类型(target.class) * 3.设置回调对象类型(Callback接口) * 4.执行create()方法并返回 * 二:直接使用Enhancer有参构造传递目标类和代理对象类型 * @return */ //2.创建方法返回CGLIB代理对象,还是要注意因为这里使用的是传参,所以不能使用static public Object createCglibProxy(){ //2.1这里一个增强器进行增强Enhancer Enhancer enhance = new Enhancer();
//2.2设置目标对象的类型 //enhance.setSuperclass(target.getClass());
//2.3设置回调类型,也就是我们需要设置代理对象返回的类型 //这里的参数是Callback类型的,需要我们的一个类实现Callback后多态调用到这里,而本类实现了Callback的子接口,并重写了方法,所以可以直接调用this //enhance.setCallback(this);
//2.4调用enhance中的方法增强函数(需要) //return enhance.create();
return enhance.create(target.getClass(), this); }
/** * 3.实现CallBack子接口MethodInterceptor,重写方法 * */ @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { System.err.println("CGLIB代理加强"); return arg1.invoke(target, arg2); //return arg3.invoke(arg0, arg2); 这是通过方法对应MethodProxy对象去执行,跟上面的其实一样 } 2.设计模式中,你了解过多少?(这里我只记录了两个)饿汉模式1.加载:在类加载时直接赋值,占用一定内存 2.时间:较快,调用方法直接返回对象 3.线程安全,高效 public class MyRuntime { //饿汉式设计模式,永远返回一个对象,不管调用多少次,都是一个对象 //私有构造 private MyRuntime(){} //私有本类对象 private static MyRuntime md = new MyRuntime(); //定义方法得到本类对象 public static MyRuntime getInstance(){ return md; } } 懒汉模式1.加载:在调用方法时创建对象,节省空间 2.时间:较慢,在调用时才创建对象 3.线程存在安全隐患,需要使用同步锁改进,高效 public class MyRuntime2 { /* * 懒汉模式 1.加载:在调用方法时创建对象,节省空间 2.时间:较慢,在调用时才创建对象 3.线程存在安全隐患,需要使用同步锁改进,高效 */ private MyRuntime2 (){} private static MyRuntime2 mr2 = null;
//在调用方法返回对象时才创建对象 public static MyRuntime2 getInstance(){ //只有第一次调用方法需要创建对象,再往后就可以直接返回对象,所以在外面加上非空判断,提高效率 if (mr2==null) { //如果直接走这样的程序存在线程安全隐患,所以加上同步锁就不会出现 synchronized (MyRuntime2.class) { //如果mr2对象为空,就创建对象,否则直接返回 if (mr2 == null) mr2 = new MyRuntime2(); } } return mr2; } } 区别:饿汉模式创建类时直接赋值给私有对象,占用一定内存,但是高效 懒汉模式在调用方法得到对象时才赋值,节省资源但是费时,并且需要加上同步锁来解决他的线程安全隐患。
|