使用Scheduled注解实现定时任务
- 在配置文件配置
<task:annotation-driven scheduler="taskScheduler"/> <task:scheduler id="taskScheduler" pool-size="8"/>
- 在bean(必须是实现类不能是接口)方法中添加Scheduled注解
@Scheduled(fixedDelay = 5000)
public void scheduleFindOvertimeGroupCalls() {
LOGGER.info("[schedule] begin to find over time group calls");
}
支持静态资源配置
<mvc:resources mapping="/resources/**" location="/resources/"/>
spring启动流程
- 加载bean
bean分为默认的bean和定制的bean,根据bean的标签采用不同的namespaceHandler处理.
<task:executor id="taskExecutor" pool-size="2-4" queue-capacity="50000"
rejection-policy="DISCARD"/>
task对应命名空间TaskNamespaceHandler. 在TaskNamespaceHandler中不同的元素采用不同的parser解析。i.e
public class TaskNamespaceHandler extends NamespaceHandlerSupport {
@Override
public void init() {
this.registerBeanDefinitionParser("annotation-driven", new AnnotationDrivenBeanDefinitionParser());
this.registerBeanDefinitionParser("executor", new ExecutorBeanDefinitionParser());
this.registerBeanDefinitionParser("scheduled-tasks", new ScheduledTasksBeanDefinitionParser());
this.registerBeanDefinitionParser("scheduler", new SchedulerBeanDefinitionParser());
}
}
- bean初始化以及启动异步事件如schedule等
开发spring插件流程
- 自定义插件注解
- 定义BeanPostProcessor,处理自定义注解
识别使用了自定义注解的bean或者方法,然后进行处理。
通常使用到spring的反射工具类ReflectionUtils - 如果使用了新的bean标签,则需要定义新的namespaceHandler以及元素的解析类如task
namespace
- 缺省为beans namespace
支持beans、bean、import、alias元素
定制元素查找相对应的namespace handler处理
如task命名空间对应的处理类为TaskNamespaceHandler
*spring查找所有jar包中META-INF/spring.handlers文件配置的namespace和namespaceHandler。 使用的方法为:
public static Properties loadAllProperties(String resourceName, ClassLoader classLoader) throws IOException {
Assert.notNull(resourceName, "Resource name must not be null");
ClassLoader classLoaderToUse = classLoader;
if (classLoaderToUse == null) {
classLoaderToUse = ClassUtils.getDefaultClassLoader();
}
Enumeration<URL> urls = (classLoaderToUse != null ? classLoaderToUse.getResources(resourceName) :
ClassLoader.getSystemResources(resourceName));
Properties props = new Properties();
while (urls.hasMoreElements()) {
URL url = urls.nextElement();
URLConnection con = url.openConnection();
ResourceUtils.useCachesIfNecessary(con);
InputStream is = con.getInputStream();
try {
if (resourceName.endsWith(XML_FILE_EXTENSION)) {
props.loadFromXML(is);
}
else {
props.load(is);
}
}
finally {
is.close();
}
}
return props;
}
spring aop
- 应用场景
对原来的逻辑做统一处理,如增加缓存、事务、日志等 - 使用xml配置 aop
<aop:config>
<aop:aspect id="concurrentOperationRetry" ref="concurrentOperationExecutor">
<aop:pointcut id="idempotentOperation"
expression="execution(* com.xyz.myapp.service.*.*(..))"/>
<aop:around
pointcut-ref="idempotentOperation"
method="doConcurrentOperation"/>
</aop:aspect>
</aop:config>