spring源码——事件监听器(注解方式)

14 篇文章 0 订阅

代码:https://github.com/shangjianan2/NormalTechnology.git

EventListener

使用

定义事件

需要继承ApplicationEvent

package com.ework.upms.server.event;

import lombok.Getter;
import lombok.Setter;
import lombok.ToString;
import org.springframework.context.ApplicationEvent;

@Getter
public class UserDTO extends ApplicationEvent {
    private Integer userId;
    private String name;
    private Integer age;

    public UserDTO(Object source, Integer userId, String name, Integer age) {
        super(source);
        this.userId = userId;
        this.name = name;
        this.age = age;
    }
}

监听器

package com.ework.upms.server.event;

import org.springframework.context.ApplicationListener;
import org.springframework.stereotype.Component;

// 通过实现接口实现监听器
@Component
public class UserRegisterEmailListener implements ApplicationListener<UserDTO> {
    @Override
    public void onApplicationEvent(UserDTO userDTO){
        System.out.println("监听到用户注册,准备发送邮件,user:" + userDTO.toString());
    }
}

发布事件的服务

package com.ework.upms.server.event;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class UserServiceImpl implements UserService{
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Override
    public void register(){
        UserDTO userDTO = new UserDTO(this, 18, "精灵王jinglingwang.cn", 1001);
//        userDTO.setAge(18);
//        userDTO.setName("精灵王jinglingwang.cn");
//        userDTO.setUserId(1001);
        System.out.println("register user");
        eventPublisher.publishEvent(userDTO);
    }
}

单元测试

package com.ework.upms.server.event;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;

@ContextConfiguration(locations = {"classpath:spring-servlet.xml"})
public class UserServiceImplTest extends AbstractTestNGSpringContextTests {
    private Logger logger = LoggerFactory.getLogger(this.getClass());

    @Autowired
    private UserService userService;

    @Test
    public void testUserEvent(){
        userService.register();
    }
}

分析

调用堆栈

handleUserEvent:15, UserRegisterSmsListener (com.ework.upms.server.event)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:253, ApplicationListenerMethodAdapter (org.springframework.context.event)
processEvent:174, ApplicationListenerMethodAdapter (org.springframework.context.event)
onApplicationEvent:137, ApplicationListenerMethodAdapter (org.springframework.context.event)
invokeListener:167, SimpleApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)
publishEvent:393, AbstractApplicationContext (org.springframework.context.support)
publishEvent:347, AbstractApplicationContext (org.springframework.context.support)
register:20, UserServiceImpl (com.ework.upms.server.event)
testUserEvent:19, UserServiceImplTest (com.ework.upms.server.event)

multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)中遍历了所有已经注册的且符合事件类型的监听器

	@Override
	public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {//遍历监听器
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(new Runnable() {
					@Override
					public void run() {
						invokeListener(listener, event);
					}
				});
			}
			else {
				invokeListener(listener, event);//第139行,运行过程中实际运行的位置
			}
		}
	}

Async+EventListener

待续

TransactionalEventListener

使用这个注解之后,整个事务正常提交之后才会触发事件监听

使用

EventListener大致相同。但是要注意,事件触发时需要包装在事务中。

服务

package com.ework.upms.server.service;

import com.ework.upms.server.annotation.MyAnnotation;
import com.ework.upms.server.event.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class TestTransaction {

    @Autowired
    private UserService userService;

    @Transactional(transactionManager = "adsTm")//需要在事务中调用事件
    public String helloWorld() {
        userService.register();
        return "adsf";
    }

}

单元测试

package com.ework.upms.server.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.annotations.Test;

@ContextConfiguration(locations = {"classpath:spring-servlet.xml"})
public class testAspectTest extends AbstractTestNGSpringContextTests {
    @Autowired
    private TestAspect testAspect;
    @Autowired
    private TestTransaction testTransaction;

    @Test
    public void test() {
//        testAspect.helloWorld();
        testTransaction.helloWorld();
    }
}

分析

调用堆栈

handleUserEvent:15, UserRegisterSmsListener (com.ework.upms.server.event)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:62, NativeMethodAccessorImpl (sun.reflect)
invoke:43, DelegatingMethodAccessorImpl (sun.reflect)
invoke:498, Method (java.lang.reflect)
doInvoke:253, ApplicationListenerMethodAdapter (org.springframework.context.event)
processEvent:174, ApplicationListenerMethodAdapter (org.springframework.context.event)//从此之后与使用EventListener时的调用堆栈相同
processEvent:127, ApplicationListenerMethodTransactionalAdapter$TransactionSynchronizationEventAdapter (org.springframework.transaction.event)
afterCompletion:116, ApplicationListenerMethodTransactionalAdapter$TransactionSynchronizationEventAdapter (org.springframework.transaction.event)
invokeAfterCompletion:168, TransactionSynchronizationUtils (org.springframework.transaction.support)//此处遍历触发事件
invokeAfterCompletion:1002, AbstractPlatformTransactionManager (org.springframework.transaction.support)
triggerAfterCompletion:977, AbstractPlatformTransactionManager (org.springframework.transaction.support)//从ThreadLocal中获取所有事件
processCommit:806, AbstractPlatformTransactionManager (org.springframework.transaction.support)
commit:730, AbstractPlatformTransactionManager (org.springframework.transaction.support)
commitTransactionAfterReturning:504, TransactionAspectSupport (org.springframework.transaction.interceptor)
invokeWithinTransaction:292, TransactionAspectSupport (org.springframework.transaction.interceptor)//事务正常提交之后运行这段代码
invoke:96, TransactionInterceptor (org.springframework.transaction.interceptor)
proceed:179, ReflectiveMethodInvocation (org.springframework.aop.framework)
intercept:673, CglibAopProxy$DynamicAdvisedInterceptor (org.springframework.aop.framework)
helloWorld:-1, TestTransaction$$EnhancerBySpringCGLIB$$7bdc734c (com.ework.upms.server.service)
test:18, testAspectTest (com.ework.upms.server.service)

1、invokeWithinTransaction:292, TransactionAspectSupport (org.springframework.transaction.interceptor)在事务正常提交之后触发事件监听

	protected Object invokeWithinTransaction(Method method, Class<?> targetClass, final InvocationCallback invocation)
			throws Throwable {

		........................

		if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				cleanupTransactionInfo(txInfo);
			}
			commitTransactionAfterReturning(txInfo);//第292行
			return retVal;
		}

		else {
			// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
			............................
		}
	}

2、triggerAfterCompletion:977, AbstractPlatformTransactionManager (org.springframework.transaction.support),此处开始使用ThreadLocal

	private void triggerAfterCompletion(DefaultTransactionStatus status, int completionStatus) {
		if (status.isNewSynchronization()) {
			List<TransactionSynchronization> synchronizations = TransactionSynchronizationManager.getSynchronizations();//从ThreadLocal中获取所有事件
			TransactionSynchronizationManager.clearSynchronization();
			if (!status.hasTransaction() || status.isNewTransaction()) {
				if (status.isDebug()) {
					logger.trace("Triggering afterCompletion synchronization");
				}
				// No transaction or new transaction for the current scope ->
				// invoke the afterCompletion callbacks immediately
				invokeAfterCompletion(synchronizations, completionStatus);//第977行
			}
			else if (!synchronizations.isEmpty()) {
				// Existing transaction that we participate in, controlled outside
				// of the scope of this Spring transaction manager -> try to register
				// an afterCompletion callback with the existing (JTA) transaction.
				registerAfterCompletionWithExistingTransaction(status.getTransaction(), synchronizations);
			}
		}
	}

synchronizations的声明为

private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
			new NamedThreadLocal<Set<TransactionSynchronization>>("Transaction synchronizations");

事件触发时会插入到这个ThreadLocal中
触发前
在这里插入图片描述 触发后
在这里插入图片描述
在这里插入图片描述
之后在TransactionAspectSupport中会调用

		if (txAttr == null || !(tm instanceof > CallbackPreferringPlatformTransactionManager)) {
			// Standard transaction demarcation with getTransaction and commit/rollback calls.
			TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
			Object retVal = null;
			try {
				// This is an around advice: Invoke the next interceptor in the chain.
				// This will normally result in a target object being invoked.
				retVal = invocation.proceedWithInvocation();
			}
			catch (Throwable ex) {
				// target invocation exception
				completeTransactionAfterThrowing(txInfo, ex);
				throw ex;
			}
			finally {
				cleanupTransactionInfo(txInfo);
			}
			commitTransactionAfterReturning(txInfo);//在这里触发
			return retVal;
		}

3、invokeAfterCompletion:168, TransactionSynchronizationUtils (org.springframework.transaction.support),遍历事件

	public static void invokeAfterCompletion(List<TransactionSynchronization> synchronizations, int completionStatus) {
		if (synchronizations != null) {
			for (TransactionSynchronization synchronization : synchronizations) {
				try {
					synchronization.afterCompletion(completionStatus);//第168行,completionStatus=0
				}
				catch (Throwable tsex) {
					logger.error("TransactionSynchronization.afterCompletion threw exception", tsex);
				}
			}
		}
	}

4、processEvent:174, ApplicationListenerMethodAdapter (org.springframework.context.event),此处之后,与EventListener相同

	public void processEvent(ApplicationEvent event) {
		Object[] args = resolveArguments(event);//第174行
		if (shouldHandle(event, args)) {
			Object result = doInvoke(args);
			if (result != null) {
				handleResult(result);
			}
			else {
				logger.trace("No result object given - no result to handle");
			}
		}
	}

多个Listener

this.eventPublisher.applicationEventMulticaster.defaultRetriever.applicationListeners中记录所有的listener
在这里插入图片描述multicastEvent:139, SimpleApplicationEventMulticaster (org.springframework.context.event)中遍历了所有已经注册的且符合事件类型的监听器

而过滤出监听器的责任由getApplicationListeners负责

	public void multicastEvent(final ApplicationEvent event, ResolvableType eventType) {
		ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
		//下面getApplicationListeners将符合要求的监听器过滤出来
		for (final ApplicationListener<?> listener : getApplicationListeners(event, type)) {
			Executor executor = getTaskExecutor();
			if (executor != null) {
				executor.execute(new Runnable() {
					@Override
					public void run() {
						invokeListener(listener, event);
					}
				});
			}
			else {
				invokeListener(listener, event);
			}
		}
	}
retrieveApplicationListeners:220, AbstractApplicationEventMulticaster (org.springframework.context.event)//遍历所有监听器,寻找符合要求的
getApplicationListeners:192, AbstractApplicationEventMulticaster (org.springframework.context.event)
multicastEvent:128, SimpleApplicationEventMulticaster (org.springframework.context.event)
publishEvent:393, AbstractApplicationContext (org.springframework.context.support)
publishEvent:347, AbstractApplicationContext (org.springframework.context.support)
publish:14, MyEventPublisher (com.ework.upms.server.event.event2)
test:21, MyEventTest (com.ework.upms.server.event.event2)

retrieveApplicationListeners:220, AbstractApplicationEventMulticaster (org.springframework.context.event)从上下文中遍历出所有符合要求的,然后在multicastEvent:128, SimpleApplicationEventMulticaster (org.springframework.context.event)中触发。

SqlSessionFactoryBean好像是所有事件的监听器

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值