2024年Java最全阿里P8面试被问:Spring AOP Proxy创建出来的到底是个啥?,javaredis面试题

文章强调了面试时自信表达的重要性,分享了蚂蚁技术面试中的常见问题,涵盖MySQL、Spring、Redis、JVM等内容。还讨论了CGLIB和Objenesis在代理类实例化中的作用,以及Java面试中对技术深度和沟通能力的考察。
摘要由CSDN通过智能技术生成

总结

面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。

以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考

一份还热乎的蚂蚁金服面经(已拿Offer)面试流程4轮技术面+1轮HR

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

// 生成代理对象并创建代理(设置 enhancer 的 callback 值)

return createProxyClassAndInstance(enhancer, callbacks);

// …

}

最后一般都会执行到CglibAopProxy子类

ObjenesisCglibAopProxy
createProxyClassAndInstance()

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {

// 创建代理类Class

Class<?> proxyClass = enhancer.createClass();

Object proxyInstance = null;

// spring.objenesis.ignore 默认为false

// 所以 objenesis.isWorthTrying() 一般为true

if (objenesis.isWorthTrying()) {

try {

// 创建实例

proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());

}

catch (Throwable ex) {

// …

}

}

if (proxyInstance == null) {

// 普通反射方式创建实例

try {

Constructor<?> ctor = (this.constructorArgs != null ?

proxyClass.getDeclaredConstructor(this.constructorArgTypes) :

proxyClass.getDeclaredConstructor());

ReflectionUtils.makeAccessible(ctor);

proxyInstance = (this.constructorArgs != null ?

ctor.newInstance(this.constructorArgs) : ctor.newInstance());

// …

}

}

// …

((Factory) proxyInstance).setCallbacks(callbacks);

return proxyInstance;

}

Spring会默认尝试使用objenesis方式实例化对象,如果失败则再次尝试使用常规方式实例化对象。

objenesis方式实例化对象的流程。

objenesis方式最后使用JDK的ReflectionFactory.newConstructorForSerialization()实例化代理对象。

这种方式创建出来的对象不会初始化类成员变量。

案例的核心是代理类实例的默认构建方式很特别。

总结对比下通过反射来实例化对象的方式,包括:

  • java.lang.Class.newInsance()

  • java.lang.reflect.Constructor.newInstance()

  • sun.reflect.ReflectionFactory.newConstructorForSerialization().newInstance()

前两种初始化方式都会同时初始化类成员变量,但最后一种通过ReflectionFactory.newConstructorForSerialization().newInstance()实例化类,不会初始化类成员变量,这就是bug的答案。

修正

=================================================================

既然是因为无法直接访问被拦截类的成员变量,那就换个方式,在UserService里写个getUser()方法,从内部访问获取。

在AdminUserService里加个getUser():

在CouponService通过getUser()获取User对象:

这就观察到了登录日志:

既然代理类的类属性不会被初始化,为何可通过在AdminUserService里的getUser()获取代理类实例的属性?

createProxyClassAndInstance

创建代理类后,会调用setCallbacks来设置拦截后需要注入的代码:

protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {

Class<?> proxyClass = enhancer.createClass();

Object proxyInstance = null;

if (objenesis.isWorthTrying()) {

try {

proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());

}

// …

((Factory) proxyInstance).setCallbacks(callbacks);

return proxyInstance;

}

callbacks存在一种服务于AOP的DynamicAdvisedInterceptor,它的接口是MethodInterceptor(callback的子接口),实现了拦截方法intercept()

public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {

// …

TargetSource targetSource = this.advised.getTargetSource();

// …

if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {

Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);

retVal = methodProxy.invoke(target, argsToUse);

}

else {

// We need to create a method invocation…

retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

}

retVal = processReturnType(proxy, target, method, retVal);

return retVal;

}

// …

}

当代理类方法被调用,会被Spring拦截,从而进入此intercept(),并在此方法中获取被代理的原始对象。

总结

虽然面试套路众多,但对于技术面试来说,主要还是考察一个人的技术能力和沟通能力。不同类型的面试官根据自身的理解问的问题也不尽相同,没有规律可循。

上面提到的关于这些JAVA基础、三大框架、项目经验、并发编程、JVM及调优、网络、设计模式、spring+mybatis源码解读、Mysql调优、分布式监控、消息队列、分布式存储等等面试题笔记及资料

有些面试官喜欢问自己擅长的问题,比如在实际编程中遇到的或者他自己一直在琢磨的这方面的问题,还有些面试官,尤其是大厂的比如 BAT 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

有些面试官喜欢问自己擅长的问题,比如在实际编程中遇到的或者他自己一直在琢磨的这方面的问题,还有些面试官,尤其是大厂的比如 BAT 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值