面试的时候关于spirng的知识点中,AOP绝对是一大热点,那么该怎么回答关于AOP的面试问题呢,接下来,将我自己总结的关于AOP的面试问题分享给各位。
(1).Spring AOP用的是哪种设计模式?
代理模式。
通过代理,可以详细控制访问某个或者某类对象的方法,在调用这个方法前做前置处理,调用这个方法后做后置处理。
(2).谈谈你对代理模式的理解?
通过代理,控制对对象的访问,它的设计思路是:定义一个抽象角色,让代理角色和真实角色分别去实现它
真实角色就是实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用,它只关注真正的业务逻辑。
代理角色就是实现抽象角色,是真实角色的代理,通过真实角色的业务逻辑方法来实现抽象方法,并在前后可以附加自己的操作。
(3).静态代理和动态代理有什么区别?
代理模式分为静态代理和动态代理,静态代理是我们自己创建一个代理类,而动态代理是程序自动帮我们生成一个代理。
静态代理需要创建真实角色和代理角色,分别实现抽象角色,真实角色可以直接实现,代理类需要将真是的对象传进来。
(1).接受真实对象
(2).通过构造方法传进来真实的对象
动态代理比静态代理使用的更广泛,在本质上,动态代理的代理类不用我们来管,交给工具去生成代理类即可。
我们不需要去创建代理类,那我们只需要编写一个动态处理器就可以了,真正的代理对象由JDK在运行时为我们动态的创建。
动态代理处理类:
(1).接收真实对象
(2).通过构造方法传进来真实的对象
(3).给真实对象生成一个代理对象实例
相对于静态代理,JDK 动态代理大大减少了我们的开发任务,同时减少了对业务接口的依赖,降低了耦合度。JDK 动态代理是利用反射机制生成一个实现代理接口的匿名类,在调用具体方法前第啊用InvokeHandler来处理。
JDK 动态代理的特点:JDK 实现动态代理需要实现类通过接口定义业务方法。
2. CGLIB 动态代理:
对于没有接口的类,就需要CGLIB。
原理:通过字节码技术为一个类创建子类,并在子类中采用方法拦截的技术拦截所有父类方法的调用,顺势织入横切逻辑。采用继承,不能对final修饰的类进行代理
使用CGLIB需要实现MethodInterceptor接口,并重写intercept方法,在该方法中对原始要执行的方法前后做增强处理。该类的代理对象可以使用代码中的字节码增强器来获取。
CGLIB创建的动态代理对象比JDK创建的动态代理对象的性能更高,但是CGLIB创建代理对象时所花费的时间却比JDK多得多。所以对于单例对象,因为无需频繁创建对象,用CGLIB合适,反之使用JDK要合适一些。
CGLIB采用动态创建子类的方法,对于final修饰的方法无法进行代理。
要代理的类中可能不止一种方法,有时候需要对特定的方法进行增强处理,可以对传入的method参数进行方法名的判断,再做相应的处理。
(4).Spring AOP采用哪种代理?
JDK 动态代理和CGLIB 动态代理均是实现Spring AOP的基础。
在Spring 5源码中:
(1).判断是否是最优化的,判断是否是代理类,判断代理的对象是否又实现接口。前两个判断默认返回false
(2).判断目标类是否为null,若为null,则抛出异常 (AopConfigException)
(3).判断目标类是否是接口或者目标类是否是Proxy类型,若是则使用JDK动态代理
(4).若配置使用CGLIB进行动态代理或者目标类没有接口,那么使用CGLIB的方式创建代理对象
(5).若(2)、(3)、(4)方法中没有一个为true,那使用JDK的提供的代理方式生成代理对象。
如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP;如果目标对象没有实现接口,则采用CGLIB库,Spring会自动在JDK动态代理和CGLIB动态代理之间转换。