篇幅的原因,面试答案分次发送。
一、spring都有哪些机制?AOP底层如何实现的?IOC呢?
1、运行机机制
(1)内部最核心的就是IOC(Inversion of control): 控制反转。①控制权由对象本身转向容器;由容器根据配置文件去创建实例并创建各个实例之间的依赖关系。②核心:bean工厂;在Spring中,bean工厂创建的各个实例称作bean。
(2)还有一个核心就是AOP(Aspect-Oriented Programming): 面向方面编程。有两种代理方式:a.静态代理:针对每个具体类分别编写代理类;针对一个接口编写一个代理类。b.动态代理:针对一个方面编写一个InvocationHandler,然后借用JDK反射包中的Proxy类为各种接口动态生成相应的代理类。
2、AOP底层的实现:采用动态代理来实现切面拦截的实现机制。①AOP的源码中用到了两种动态代理来实现拦截切入功能:jdk动态代理和cglib动态代理。
②AOP实现的强弱在很大程度上取决于连接点模型。目前,Spring只支持方法级的连接点。这和一些其他AOP框 架不一样,如AspectJ和JBoss,它们还提供了属性接入点,这样可以防止你创建特别细致的通知,如对更新对象属性值进行拦截。然而,由于 Spring关注于提供一个实现J2EE 服务的框架,所以方法拦截可以满足大部分要求,而且Spring的观点是属性拦截破坏了封装,让Advice触发在属性值改变而不是方法调用上无疑是破坏了这个概念。
③Spring的AOP框架的关键点如下:
(1)Spring实现了AOP联盟接口。在Spring AOP中,存在如下几种通知(Advice)类型
Before通知:在目标方法被调用前调用,涉及接口org.springFramework .aop.MethodBeforeAdvice;
After通知:在目标方法被调用后调用,涉及接口为org.springframework.aop.AfterReturningAdvice;
Throws通知:目标方法抛出异常时调用,涉及接口org.springframework.aop.MethodBeforeAdvice;
Around通知:拦截对目标对象方法调用,涉及接口为org.aopalliance.intercept.MethodInterceptor。
(2)用Java 编写Spring通知,并在Spring的配置文件中,定义在什么地方应用通知的切入点。
(3)Spring的运行时通知对象。代理Bean只有在第一次被应用系统需要的时候才 被创建。如果你使用的是ApplicationContext,代理对象在BeanFactory载入所有Bean的时候被创建。Spring有两种代理 创建方式。如果目标对象实现了一个或多个接口暴露的方法,Spring将使用JDK 的 java.lang.reflect.Proxy类创建代理。这个类让Spring动态产生一个新的类,它实现所需的接口,织入了通知,并且代理对目标对 象的所有请求。如果目标对象没有实现任何接口,Spring使用CGLIB库生成目标对象的子类。在创建这个子类的时候,Spring将通知织入,并且将 对目标对象的调用委托给这个子类。此时,需要将Spring发行包lib/cglib目录下的JAR文件发布到应用系统中。
3、IOC实现机制:主要的实现形式有两种 :a.依赖查找:容器提供回调接口和上下文环境给组件。b.依赖注入:组件不做定位查询,只是提供普通的Java方法让容器去决定依赖关系。容器全权负责组件的装配,它会把符合依赖关系的对象通过JavaBean属性或者构造子传递给需要的对象。通过JavaBean属性注射依赖关系的做法称为设值方法注入(Setter Injection );将依赖关系作为构造子参数传入的做法称为构造子注入(Constructor Injection )。
二、cgLib知道吗?他和jdk动态代理什么区别?手写一个jdk动态代理呗?
1、cgLib是一个功能强大,高性能的代码生成包。它为没有实现接口的类提供代理,为JDK的动态代理提供了很好的补充。通常可以使用Java的动态代理创建代理,但当要代理的类没有实现接口或者为了更好的性能,cgLib是一个好的选择。cgLib原理:动态生成一个要代理类的子类,子类重写要代理的类的所有不是final的方法。在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。它比使用java反射的JDK动态代理要快。
2、jdk动态代理和cglib动态代理的区别:两种方法同时存在,各有优劣。jdk动态代理是由java内部的反射机制来实现的,cglib动态代理底层则是借助asm来实现的。总的来说,反射机制在生成类的过程中比较高效,而asm在生成类之后的相关执行过程中比较高效(可以通过将asm生成的类进行缓存,这样解决asm生成类过程低效问题)。还有一点必须注意:jdk动态代理的应用前提,必须是目标类基于统一的接口。如果没有上述前提,jdk动态代理不能应用。由此可以看出,jdk动态代理有一定的局限性,cglib这种第三方类库实现的动态代理应用更加广泛,且在效率上更有优势;cbLib的缺点对于final方法,无法进行代理。
3、jdk动态代理
JDK动态代理是基于接口的代理
代理类:proxy,代理动作必须要基于一个proxy实例来执行
代理执行类:实现InvocationHandler,案例中是TestInvocationHandler
被代理类:基于接口的用户自己的方法,案例中是SayImpl
首先说明下InvocationHandler的invoke
public interface InvocationHandler {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable;
}
public interface Say {
void sayHello(String words);
}
public class SayImpl implements Say {
@Override
public void sayHello(String words) {
System.out.println('hello:' + words);
}
}
public class TestInvocationHandler implements InvocationHandler {
private Object target;
public TestInvocationHandler(Object target) {
this.target=target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println('invoke begin');
System.out.println('method :'+ method.getName()+' is invoked!');
method.invoke(target,args);
System.out.println('invoke end');
return null;
}
}
public static void main(String[] args) {
TestInvocationHandler testInvocationHandler = new TestInvocationHandler(new SayImpl());
Say say = (Say)Proxy.newProxyInstance(SayImpl.class.getClassLoader(), SayImpl.class.getInterfaces(), testInvocationHandler );
say.sayHello('my dear');
}
执行结果:
invoke begin
method :sayHello is invoked!
hello:my dear
invoke end
下篇解答问题:
数据库
一、使用mysq1索引都有哪些原则? ?索引什么数据结构? 3+tree 和B tree 什么区别?
二、mysq1有哪些存储引擎啊?都有啥区别? 要详细!
三、设计高并发系统数据库层面该怎么设计??数据库锁有哪些类型?如何实现呀?
四、数据库事务有哪些?
联系客服