总结
面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。
以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考
// 生成代理对象并创建代理(设置 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 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。
有些面试官喜欢问自己擅长的问题,比如在实际编程中遇到的或者他自己一直在琢磨的这方面的问题,还有些面试官,尤其是大厂的比如 BAT 的面试官喜欢问面试者认为自己擅长的,然后通过提问的方式深挖细节,刨根到底。