总结
就写到这了,也算是给这段时间的面试做一个总结,查漏补缺,祝自己好运吧,也希望正在求职或者打算跳槽的 程序员看到这个文章能有一点点帮助或收获,我就心满意足了。多思考,多问为什么。希望小伙伴们早点收到满意的offer! 越努力越幸运!
金九银十已经过了,就目前国内的面试模式来讲,在面试前积极的准备面试,复习整个 Java 知识体系将变得非常重要,可以很负责任的说一句,复习准备的是否充分,将直接影响你入职的成功率。但很多小伙伴却苦于没有合适的资料来回顾整个 Java 知识体系,或者有的小伙伴可能都不知道该从哪里开始复习。我偶然得到一份整理的资料,不论是从整个 Java 知识体系,还是从面试的角度来看,都是一份含技术量很高的资料。
If only one item needs to be customized, null can be returned to keep the default settings. Consider also extending from AsyncConfigurerSupport when possible.Note: In the above example the ThreadPoolTaskExecutor is not a fully managed Spring bean. Add the @Bean annotation to the getAsyncExecutor() method if you want a fully managed bean. In such circumstances it is no longer necessary to manually call the executor.initialize() method as this will be invoked automatically when the bean is initialized.
同比相关
<beans>
<task:annotation-driven executor="myExecutor" exception-handler="exceptionHandler"/>
<task:executor id="myExecutor" pool-size="7-42" queue-capacity="11"/>
<bean id="asyncBean" class="com.foo.MyAsyncBean"/>
<bean id="exceptionHandler" class="com.foo.MyAsyncUncaughtExceptionHandler"/>
</beans>
重点说明
The mode() attribute controls how advice is applied: If the mode is AdviceMode.PROXY (the default), then the other attributes control the behavior of the proxying. Please note that proxy mode allows for interception of calls through the proxy only; local calls within the same class cannot get intercepted that way.
- 这里就说明了 @Async 必须在不同方法中调用。
Note that if the mode() is set to AdviceMode.ASPECTJ, then the value of the proxyTargetClass() attribute will be ignored. Note also that in this case the spring-aspects module JAR must be present on the classpath, with compile-time weaving or load-time weaving applying the aspect to the affected classes. There is no proxy involved in such a scenario; local calls will be intercepted as well.//当然也可以用 Aspect 模式织入(需要引入 spring-aspects 模块需要的 jar)
功能解析
@Async
-
该注解可以标记一个异步执行的方法,也可以用来标注类,表示类中的所有方法都是异步执行的。
-
入参随意,但返回值只能是 void 或者 Future.(ListenableFuture 接口/CompletableFuture 类)
-
Future 是代理返回的切实的异步返回,用以追踪异步方法的返回值。当然也可以使用 AsyncResult 类(实现 ListenableFuture 接口)(Spring 或者 EJB 都有)或者 CompletableFuture 类
-
加在类上表示整个类都使用,加在方法上会覆盖类上的设置
-
value 字段用以限定执行方法的执行器名称(自定义):Executor 或者 TaskExecutor
@EnableAsync
-
开启 spring 异步执行器,类似 xml 中的 task 标签配置,需要联合 @Configuration 注解一起使用
-
默认情况下 spring 会先搜索 TaskExecutor 类型的 bean 或者名字为 taskExecutor 的 Executor 类型的 bean,都不存在使用 SimpleAsyncTaskExecutor 执行器
-
针对于上面章节的【覆盖定制化 UncaughtExceptionHandler/getAsyncExecutor】可实现 AsyncConfigurer 接口复写 getAsyncExecutor 获取异步执行器,getAsyncUncaughtExceptionHandler 获取异步未捕获异常处理器
-
@Configuration
-
注解类和 xml 基本一致,但是使用注解类还可以自定义线程名前缀(上面的 AppConfig-》getAsyncExecutor-》setThreadNamePrefix)
@Target(ElementType.TYPE)@Retention(RetentionPolicy.RUNTIME)
@Documented@Import(AsyncConfigurationSelector.class)
public @interface EnableAsync {`
/**该属性用来支持用户自定义异步注解,默认扫描spring的@Async和EJB3.1的@code @javax.ejb.Asynchronous
* Indicate the 'async' annotation type to be detected at either class
* or method level.
* <p>By default, both Spring's @{@link Async} annotation and the EJB 3.1
* {@code @javax.ejb.Asynchronous} annotation will be detected.
* <p>This attribute exists so that developers can provide their own
* custom annotation type to indicate that a method (or all methods of
* a given class) should be invoked asynchronously.
*/
Class<? extends Annotation> annotation() default Annotation.class;
/**标明是否需要创建CGLIB子类代理,AdviceMode=PROXY时才适用。注意设置为true时,其它spring管理的bean也会升级到CGLIB子类代理
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies.
* <p><strong>Applicable only if the {@link #mode} is set to {@link AdviceMode#PROXY}</strong>.
* <p>The default is {@code false}.
* <p>Note that setting this attribute to {@code true} will affect <em>all</em>
* Spring-managed beans requiring proxying, not just those marked with {@code @Async}.
* For example, other beans marked with Spring's {@code @Transactional} annotation
* will be upgraded to subclass proxying at the same time. This approach has no
* negative impact in practice unless one is explicitly expecting one type of proxy
* vs. another — for example, in tests.
*/
boolean proxyTargetClass() default false;
/**标明异步通知将会如何实现,默认PROXY,如需支持同一个类中非异步方法调用另一个异步方法,需要设置为ASPECTJ
* Indicate how async advice should be applied.
* <p><b>The default is {@link AdviceMode#PROXY}.</b>
* Please note that proxy mode allows for interception of calls through the proxy
* only. Local calls within the same class cannot get intercepted that way; an
* {@link Async} annotation on such a method within a local call will be ignored
* since Spring's interceptor does not even kick in for such a runtime scenario.
* For a more advanced mode of interception, consider switching this to
* {@link AdviceMode#ASPECTJ}.
*/
AdviceMode mode() default AdviceMode.PROXY;
/**标明异步注解bean处理器应该遵循的执行顺序,默认最低的优先级(Integer.MAX_VALUE,值越小优先级越高)
* Indicate the order in which the {@link AsyncAnnotationBeanPostProcessor}
* should be applied.
* <p>The default is {@link Ordered#LOWEST_PRECEDENCE} in order to run
* after all other post-processors, so that it can add an advisor to
* existing proxies rather than double-proxy.
*/
`int order() default Ordered.LOWEST_PRECEDENCE;``}
执行流程
核心注解就是 @Import(AsyncConfigurationSelector.class),就是属于 ImportSelector 接口的 selectImports()方法,源码如下:
查询器:基于 @EnableAsync 中定义的模式 AdviceMode 加在 @Configuration 标记的类上,确定抽象异步配置类的实现类
/**
* Selects which implementation of {@link AbstractAsyncConfiguration} should be used based
* on the value of {@link EnableAsync#mode} on the importing {@code @Configuration} class.
*
* @author Chris Beams
* @since 3.1
* @see EnableAsync
* @see ProxyAsyncConfiguration
*/``public class AsyncConfigurationSelector extends AdviceModeImportSelector<EnableAsync> {
private static final String ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME =
"org.springframework.scheduling.aspectj.AspectJAsyncConfiguration";
/**
* {@inheritDoc}
* @return {@link ProxyAsyncConfiguration} or {@code AspectJAsyncConfiguration} for
* {@code PROXY} and {@code ASPECTJ} values of {@link EnableAsync#mode()}, respectively
*/
@Override
public String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY://如果配置的PROXY,使用ProxyAsyncConfiguration
return new String[] { ProxyAsyncConfiguration.class.getName() };
case ASPECTJ://如果配置的ASPECTJ,使用ProxyAsyncConfiguration
return new String[] { ASYNC_EXECUTION_ASPECT_CONFIGURATION_CLASS_NAME };
default:
return null;
}
}``}
JDK 接口代理-选一个类 ProxyAsyncConfiguration:
@Configuration``@Role(BeanDefinition.ROLE_INFRASTRUCTURE)``public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration {
@Bean(name = TaskManagementConfigUtils.ASYNC_ANNOTATION_PROCESSOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public AsyncAnnotationBeanPostProcessor asyncAdvisor() {
Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected");
AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor();
Class<? extends Annotation> customAsyncAnnotation = this.enableAsync.getClass("annotation");
if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) {
bpp.setAsyncAnnotationType(customAsyncAnnotation);
}
if (this.executor != null) {
bpp.setExecutor(this.executor);
}
if (this.exceptionHandler != null) {
bpp.setExceptionHandler(this.exceptionHandler);
}
bpp.setProxyTargetClass(this.enableAsync.getBoolean("proxyTargetClass"));
bpp.setOrder(this.enableAsync.<Integer>getNumber("order"));
return bpp;
}``}
-
如果 @EnableAsync 中用户自定义了 annotation 属性,即异步注解类型
-
新建一个异步注解 bean 后处理器
-
设置 Executor:设置线程任务执行器
-
AsyncUncaughtExceptionHandler:设置异常处理器
-
设置是否升级到 CGLIB 子类代理,默认不开启
-
设置执行优先级,默认最后执行
ProxyAsyncConfiguration 就两点:
-
就是继承了 AbstractAsyncConfiguration 类
-
定义了一个 bean:AsyncAnnotationBeanPostProcessor
AbstractAsyncConfiguration
/**
* Abstract base {@code Configuration} class providing common structure for enabling
* Spring's asynchronous method execution capability.
* 抽象异步配置类,封装了通用结构,用以支持spring的异步方法执行能力
* @author Chris Beams
* @author Stephane Nicoll
* @since 3.1
* @see EnableAsync
*/``@Configuration``public abstract class AbstractAsyncConfiguration implements ImportAware {
protected AnnotationAttributes enableAsync;//enableAsync的注解属性
protected Executor executor;//Doug Lea老李头设计的线程任务执行器
protected AsyncUncaughtExceptionHandler exceptionHandler;//异常处理器
@Override
public void setImportMetadata(AnnotationMetadata importMetadata) {
this.enableAsync = AnnotationAttributes.fromMap(
importMetadata.getAnnotationAttributes(EnableAsync.class.getName(), false));
if (this.enableAsync == null) {
throw new IllegalArgumentException(
"@EnableAsync is not present on importing class " + importMetadata.getClassName());
}
}
/**
* Collect any {@link AsyncConfigurer} beans through autowiring.
*/
@Autowired(required = false)
void setConfigurers(Collection<AsyncConfigurer> configurers) {
if (CollectionUtils.isEmpty(configurers)) {
return;
}
if (configurers.size() > 1) {
throw new IllegalStateException("Only one AsyncConfigurer may exist");
}
AsyncConfigurer configurer = configurers.iterator().next();
this.executor = configurer.getAsyncExecutor();
this.exceptionHandler = configurer.getAsyncUncaughtExceptionHandler();
}``}
主要设置为一下三点
-
1)注解属性
-
2)异步任务执行器
-
3)异常处理器
方法:
-
1)setImportMetadata 设置注解属性
-
2)setConfigurers 设置异步任务执行器和异常处理器
AsyncAnnotationBeanPostProcessor
AsyncAnnotationBeanPostProcessor 这个类的 Bean 初始化时 : BeanFactoryAware 接口 setBeanFactory 方法中,对 AsyncAnnotationAdvisor 异步注解切面进行了构造。
@Override
public void setBeanFactory(BeanFactory beanFactory) {
super.setBeanFactory(beanFactory);
AsyncAnnotationAdvisor advisor = new AsyncAnnotationAdvisor(this.executor, this.exceptionHandler);
if (this.asyncAnnotationType != null) {
advisor.setAsyncAnnotationType(this.asyncAnnotationType);
}
advisor.setBeanFactory(beanFactory);
this.advisor = advisor;
}
AsyncAnnotationAdvisor:
通过 AsyncAnnotationAdvisor 建立异步化的 AOP 切面拦截操作处理机制
-
AsyncAnnotationBeanPostProcessor -> postProcessAfterInitialization()
-
具体的后置处理:AsyncAnnotationBeanPostProcessor 的后置 bean 处理是通过其父类 AbstractAdvisingBeanPostProcessor 来实现的,
-
该类实现了 BeanPostProcessor 接口,复写 postProcessAfterInitialization 方法
总结
面试建议是,一定要自信,敢于表达,面试的时候我们对知识的掌握有时候很难面面俱到,把自己的思路说出来,而不是直接告诉面试官自己不懂,这也是可以加分的。
以上就是蚂蚁技术四面和HR面试题目,以下最新总结的最全,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考
总结的最全**,范围包含最全MySQL、Spring、Redis、JVM等最全面试题和答案,仅用于参考
[外链图片转存中…(img-jQjmInCl-1715481852060)]