@SpringBootApplication
@EnableAsync
public class XApplication{
public static void main(String[] args){
ConfigurableApplicationContext run = new SpringApplicationBuilder(XApplication.class).web(true).run(args);
run.publishEvent("test");}}
@Async
@EventListener
public void test(String wrapped){
System.out.println("当前线程 "+Thread.currentThread().getName());
System.out.println(wrapped.getMchId());}
还可以配置线程池taskExecutor
@Configuration
public class GenericConfiguration {
@Bean
public Executor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//核心线程数:线程池创建时候初始化的线程数
//最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
//缓冲队列:用来缓冲执行任务的队列
//允许线程的空闲时间60秒:当超过了核心线程出之外的线程在空闲时间到达之后会被销毁
//线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
//线程池对拒绝任务的处理策略:这里采用了CallerRunsPolicy策略,当线程池没有处理能力的时候,该策略会直接在 execute 方法的调用线程中运行被拒绝的任务;如果执行程序已关闭,则会丢弃该任务
executor.setCorePoolSize(5);
executor.setMaxPoolSize(10);
executor.setQueueCapacity(20);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());return executor;}}
public class ApplicationListenerMethodAdapter implements GenericApplicationListener {
protected final Log logger = LogFactory.getLog(getClass());
private final String beanName;
private final Method method;
private final Method targetMethod;
private final AnnotatedElementKey methodKey;
private final List declaredEventTypes;
@Nullable
private final String condition;
private final int order;
@Nullable
private ApplicationContext applicationContext;
@Nullable
private EventExpressionEvaluator evaluator;
..................................
}
protected void processBean(
final List factories, final String beanName, final Class> targetType) {
if (!this.nonAnnotatedClasses.contains(targetType)) {
Map annotatedMethods = null;
try {
// 拿到使用了@EventListener注解的方法
annotatedMethods = MethodIntrospector.selectMethods(targetType,
(MethodIntrospector.MetadataLookup) method ->
AnnotatedElementUtils.findMergedAnnotation(method, EventListener.class));
}
catch (Throwable ex) {
// An unresolvable type in a method signature, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve methods for bean with name '" + beanName + "'", ex);
}
}
if (CollectionUtils.isEmpty(annotatedMethods)) {
this.nonAnnotatedClasses.add(targetType);
if (logger.isTraceEnabled()) {
logger.trace("No @EventListener annotations found on bean class: " + targetType.getName());
}
}
else {
// Non-empty set of methods
ConfigurableApplicationContext context = getApplicationContext();
for (Method method : annotatedMethods.keySet()) {
for (EventListenerFactory factory : factories) {
// 判断是否支持该方法 这里用的DefaultEventListenerFactory spring5.0.8 写死的返回true
if (factory.supportsMethod(method)) {
//选择方法 beanName 这里是AddDataEventListener的beanName 默认是addDataEventListener
Method methodToUse = AopUtils.selectInvocableMethod(method, context.getType(beanName));
// 这里是创建一个ApplicationListenerMethodAdapter对象
ApplicationListener> applicationListener =
factory.createApplicationListener(beanName, targetType, methodToUse);
if (applicationListener instanceof ApplicationListenerMethodAdapter) {
// 如果是ApplicationListenerMethodAdapter对象 就把context和evaluator传进去
((ApplicationListenerMethodAdapter) applicationListener).init(context, this.evaluator);
}
// 添加到ApplicationListener事件Set集合中去
context.addApplicationListener(applicationListener);
break;
}
}
}
if (logger.isDebugEnabled()) {
logger.debug(annotatedMethods.size() + " @EventListener methods processed on bean '" +
beanName + "': " + annotatedMethods);
}
}
}
}
private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
try {
listener.onApplicationEvent(event);
}
catch (ClassCastException ex) {
String msg = ex.getMessage();
if (msg == null || matchesClassCastMessage(msg, event.getClass().getName())) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception and just log a debug message.
Log logger = LogFactory.getLog(getClass());
if (logger.isDebugEnabled()) {
logger.debug("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}
@Override
public void onApplicationEvent(ApplicationEvent event) {
processEvent(event);
}
ApplicationListenerMethodAdapter#processEvent
public void processEvent(ApplicationEvent event) {
Object[] args = resolveArguments(event);
if (shouldHandle(event, args)) {
// 执行真正的方法
Object result = doInvoke(args);
if (result != null) {
handleResult(result);
}
else {
logger.trace("No result object given - no result to handle");
}
}
}
protected Object getTargetBean() {
Assert.notNull(this.applicationContext, "ApplicationContext must no be null");
return this.applicationContext.getBean(this.beanName);
}
--只包含执行部分的PL/SQL块
--set serveroutput off
begin
dbms_output.put_line('Hello,everyone!');
end;
select * from emp;
--包含定义部分和执行部分的PL/SQL块
declare
v_ename varchar2(5);
begin
select
转:http://stackoverflow.com/questions/6352208/how-to-solve-plugin-execution-not-covered-by-lifecycle-configuration-for-sprin
maven报错:
Plugin execution not covered by lifecycle configuration:
要使用MonkeyRunner,就要学习使用Python,哎
先抄一段官方doc里的代码
作用是启动一个程序(应该是启动程序默认的Activity),然后按MENU键,并截屏
# Imports the monkeyrunner modules used by this program
from com.android.monkeyrunner import MonkeyRun