title | tags | categories | keywords | description | cover | abbrlink | date | |||
---|---|---|---|---|---|---|---|---|---|---|
Spring源码系列-第7章-AOP的执行流程原理和监听器原理 |
|
|
Spring,框架,spring源码 |
AOP执行流程和监听器原理 |
fb3552e0 |
2022-04-17 05:01:02 -0700 |
断点打到这里,F7进入方法
自然而然的跳到了cglib这里
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
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;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
- 把5个增强器变成了方法拦截器,增强器只是保存信息的,真正执行还得靠方法拦截器。
- 我们再给上面的470行打上断点,看下之前是如何生成方法拦截器的。因为第一次生成的时候没有缓存,肯定能进去470行。
可以看到就是在之前创建代理对象的时候增强器转成的拦截器
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);//(如果是通知方法)把增强器转拦截器
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList; //所有增强器转好拦截器
}
private final List<AdvisorAdapter> adapters = new ArrayList<>(3);
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) { //这里应该是一个适配器模式
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
- 增强器只是保存了哪些方法是通知方法的详细信息
- 拦截器里写了反射执行通知方法的逻辑,具体执行还得要方法拦截器
适配器模式适配一下
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable {
private final MethodBeforeAdvice advice;
/**
* Create a new MethodBeforeAdviceInterceptor for the given advice.
* @param advice the MethodBeforeAdvice to wrap
*/
public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
Assert.notNull(advice, "Advice must not be null");
this.advice = advice;
}
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable { //invoke真正执行
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
}
然后debug回到accept()方法
- F7进入方法,上面讲过会调用CglibAopProxy内部类的DynamicAdvisedInterceptor#intercept()。这次我们来说下为什么会跳到DynamicAdvisedInterceptor#intercept()方法
- HelloService是一个代理对象,它的AOP代理是一个DynamicAdvisedInterceptor对象
- 而DynamicAdvisedInterceptor实现了MethodInterceptor接口
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable{...}
- cglib代理就是,当你调用方法的时候,真正会调用到实现了MethodInterceptor接口的DynamicAdvisedInterceptor#intercept()
- 至于具体的cglib原理,可以自己百度下。下面就看看intercept()的逻辑
注意有两个MethodInterceptor,包名不一样
package org.springframework.cglib.proxy;
import java.lang.reflect.Method;
public interface MethodInterceptor extends Callback {
Object intercept(Object var1, Method var2, Object[] var3, MethodProxy var4) throws Throwable;
}
package org.aopalliance.intercept; //Spring定义的AOP规范接口
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@FunctionalInterface
public interface MethodInterceptor extends Interceptor {
@Nullable
Object invoke(@Nonnull MethodInvocation invocation) throws Throwable;
}
有intercept的是cglib的MethodInterceptor接口
@Nullable //回调方法
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
// 这里面有最原生的HelloService对象
TargetSource targetSource = this.advised.getTargetSource();
try { //使用了代理对象就有增强功能
if (this.advised.exposeProxy) { //使用ThreadLocal线程共享这个代理对象;
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal; //chain是AOP后置处理器在第一次的时候就生成好的5个增强器,然后封装成的MethodInterceptor
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else { //CglibMethodInvocation【FilterChain(维护索引)】,5个MethodInterceptor就是Filter
//创建一个方法执行的东西(拦截器链在此执行) 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;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
在前面创建HelloService代理对象时创建好的方法拦截器,然后调用proceed()
顾名思义,就是用来执行Cglib生成的代理对象的方法
public Object proceed() throws Throwable {
try {
return super.proceed(); //调用父类的方法
}
catch (RuntimeException ex) {
throw ex;
}
catch (Exception ex) {
if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
// Propagate original exception if declared on the target method
// (with callers expecting it). Always propagate it for Kotlin code
// since checked exceptions do not have to be explicitly declared there.
throw ex;
}
else {
// Checked exception thrown in the interceptor but not declared on the
// target method signature -> apply an UndeclaredThrowableException,
// aligned with standard JDK dynamic proxy behavior.
throw new UndeclaredThrowableException(ex);
}
}
}
public Object proceed() throws Throwable {
// 当前拦截器的索引有没有超过 拦截器总数量-1 We start with an index of -1 and increment early.
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
上面5个拦截器都继承了Spring的org.aopalliance.intercept.MethodInterceptor,和Cglib的MethodInterceptor没关系了
获取第一个拦截器ExposeInvocationInterceptor
往下走,直接走到了这里,准备调用ExposeInvocationInterceptor的invoke()
public Object proceed() throws Throwable {
try {
return super.proceed(); //调用父类的方法
}
catch (RuntimeException ex) {
throw ex;
}
catch (Exception ex) {
if (ReflectionUtils.declaresException(getMethod(), ex.getClass()) ||
KotlinDetector.isKotlinType(getMethod().getDeclaringClass())) {
// Propagate original exception if declared on the target method
// (with callers expecting it). Always propagate it for Kotlin code
// since checked exceptions do not have to be explicitly declared there.
throw ex;
}
else {
// Checked exception thrown in the interceptor but not declared on the
// target method signature -> apply an UndeclaredThrowableException,
// aligned with standard JDK dynamic proxy behavior.
throw new UndeclaredThrowableException(ex);
}
}
}
结果又调回了,很明显这是个递归调用
然后后面的调用逻辑和前面就一样了,如下
这个时候就先执行切面的before方法,前置通知就执行了
继续调父类的方法
后置通知这里先不执行,先继续执行下面的方法拦截器链路,最后finally再执行后置通知
- 先往下走,我们就继续
继续往下发现索引要超了
放行之后看控制台,sayhello方法就打印了。并且到目前为止,只有前面说的前置通知执行了。
然后咱们就往后返,
咱们这里没异常,就继续返回了
返回到这里,准备执行返回通知
放行之后的控制台
继续返回
准备执行后置通知
放行finally之后的控制台
继续返回
最后over,回到刚开头说的那个地方
@Component
public class AppEventListener {
public AppEventListener(){
System.out.println("AppEventListener...");
}
@EventListener(MessageEvent.class) //监听事件
public void listenMessage(MessageEvent event){
System.out.println("Message事件到达..."+event+";已发送邮件....");
}
@EventListener(ChangeEvent.class)
public void listenChange(ChangeEvent event){
System.out.println("Change事件到达..."+event+";已同步状态....");
}
@EventListener(PayloadApplicationEvent.class) //感知任意对象事件的
public void listenPayload(PayloadApplicationEvent<A> event){
System.out.println("Payload事件到达..."+event.getPayload()+";已进行处理....");
}
}
@Component
public class AppEventPublisher implements ApplicationEventPublisherAware {
ApplicationEventPublisher eventPublisher;
public AppEventPublisher(){
System.out.println("AppEventPublisher....");
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
this.eventPublisher = applicationEventPublisher;
}
public void publish(ApplicationEvent applicationEvent){
eventPublisher.publishEvent(applicationEvent);
}
public void publish(Object o){
eventPublisher.publishEvent(o);
}
}
/**
* 事件需要实现序列化接口
*/
public class ChangeEvent extends ApplicationEvent implements Serializable {
private static final long serialVersionUID = 0L;
private String state;
private ChangeEvent(Object source) {
super(source);
}
public ChangeEvent(Object source,String state){
super(source);
this.state = state;
}
public String getState() {
return state;
}
@Override
public String toString() {
return "ChangeEvent{" +
"state='" + state + '\'' +
", source=" + source +
'}';
}
}
/**
* 事件需要实现序列化接口
*/
public class MessageEvent extends ApplicationEvent implements Serializable {
private static final long serialVersionUID = 0L;
public MessageEvent(String source) {
super(source);
}
@Override
public String toString() {
return "MessageEvent{" +
", source=" + source +
'}';
}
}
package cn.imlql.spring;
/**
* 注解版Spring的用法
*/
public class AnnotationMainTest {
public static void main(String[] args) {
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(MainConfig.class);
// 下面两种使用方法都可以
// applicationContext.publishEvent(new Object());
// applicationContext.publishEvent(new ApplicationEvent() {
// @Override
// public String toString() {
// return super.toString();
// }
// });
//测试事件
AppEventPublisher eventPublisher = applicationContext.getBean(AppEventPublisher.class);
eventPublisher.publish(new A());
eventPublisher.publish(new MessageEvent("hello,你好"));
eventPublisher.publish(new ChangeEvent(eventPublisher,"sending..."));
}
}
在还未进行refresh()十二大步刷新时,容器就已经有了这两事件相关的Bean定义信息了。
- 我们看到实现了SmartInitializingSingleton和BeanFactoryPostProcessor
- BeanFactoryPostProcessor我们反复在说,就是工厂后置处理环节。EventListenerMethodProcessor实现了BeanFactoryPostProcessor,说明他在工厂后置处理环节会做事
- SmartInitializingSingleton我们虽然说的不多,但也说过几次,调用链路如下。说明它会在容器刷新12大步的最后一步做事,并且看代码位置是在所有Bean创建完成之后做事。
AbstractApplicationContext#refresh() ==> AbstractApplicationContext#finishBeanFactoryInitialization() ==> DefaultListableBeanFactory#preInstantiateSingletons()
怎么分析呢?还是老办法,给EventListenerMethodProcessor标注@Override的方法打上断点
Debug启动
果然是从工厂后置处理那里过来的
放行,继续往下走。果然SmartInitializingSingleton这里开始做事了
public void afterSingletonsInstantiated() {
ConfigurableListableBeanFactory beanFactory = this.beanFactory;
Assert.state(this.beanFactory != null, "No ConfigurableListableBeanFactory set");
String[] beanNames = beanFactory.getBeanNamesForType(Object.class);
for (String beanName : beanNames) {
if (!ScopedProxyUtils.isScopedTarget(beanName)) {
Class<?> type = null;
try {
type = AutoProxyUtils.determineTargetClass(beanFactory, beanName);
}
catch (Throwable ex) {
// An unresolvable bean type, probably from a lazy bean - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target class for bean with name '" + beanName + "'", ex);
}
}
if (type != null) {
if (ScopedObject.class.isAssignableFrom(type)) {
try {
Class<?> targetClass = AutoProxyUtils.determineTargetClass(
beanFactory, ScopedProxyUtils.getTargetBeanName(beanName));
if (targetClass != null) {
type = targetClass;
}
}
catch (Throwable ex) {
// An invalid scoped proxy arrangement - let's ignore it.
if (logger.isDebugEnabled()) {
logger.debug("Could not resolve target bean for scoped proxy '" + beanName + "'", ex);
}
}
}
try {
processBean(beanName, type); //主要是这里
}
catch (Throwable ex) {
throw new BeanInitializationException("Failed to process @EventListener " +
"annotation on bean with name '" + beanName + "'", ex);
}
}
}
}
}
我们在这里打上条件断点
F7进入下面的方法
咱们发现是创建了一个适配器
public ApplicationListenerMethodAdapter(String beanName, Class<?> targetClass, Method method) {
this.beanName = beanName;
this.method = BridgeMethodResolver.findBridgedMethod(method);
this.targetMethod = (!Proxy.isProxyClass(targetClass) ?
AopUtils.getMostSpecificMethod(method, targetClass) : this.method);
this.methodKey = new AnnotatedElementKey(this.targetMethod, targetClass);
EventListener ann = AnnotatedElementUtils.findMergedAnnotation(this.targetMethod, EventListener.class);
this.declaredEventTypes = resolveDeclaredEventTypes(method, ann);
this.condition = (ann != null ? ann.condition() : null);
this.order = resolveOrder(this.targetMethod);
}
为啥要创建这样一个适配器呢?虽然我们的AppEventListener不是监听器,它只是在方法里标注了监听注解,我们自己没有写监听器。但是咱们解析@EventListener注解之后,在这里生成的适配器却实现了EventListener,也就说明这个适配器就是个监听器。
继续往下放行
把适配器放到了事件多播器里
- 这个思想就是,咱们自己创建的AppEventListener不是监听器,只在方法里标了注解
- spring准备了另外一个类ApplicationListenerMethodAdapter,把你这个beanName和方法名等等信息封装到这里。然后放到事件多播器里
- 等以后真正的事件来了之后派发给ApplicationListenerMethodAdapter,ApplicationListenerMethodAdapter再用之前保存的信息反射调用实际的方法
最后就是三个方法,三个适配器
给下面的位置打上断点
public void publishEvent(Object event) {
publishEvent(event, null);
}
protected void publishEvent(Object event, @Nullable ResolvableType eventType) {
Assert.notNull(event, "Event must not be null");
// Decorate event as an ApplicationEvent if necessary
ApplicationEvent applicationEvent;
if (event instanceof ApplicationEvent) { // ApplicationEvent接口下的事件
applicationEvent = (ApplicationEvent) event;
}
else { //任意对象作为事件最终被封装到了 PayloadApplicationEvent
applicationEvent = new PayloadApplicationEvent<>(this, event);
if (eventType == null) {
eventType = ((PayloadApplicationEvent<?>) applicationEvent).getResolvableType();
}
}
// Multicast right now if possible - or lazily once the multicaster is initialized
if (this.earlyApplicationEvents != null) {
this.earlyApplicationEvents.add(applicationEvent);
}
else { //拿到多播器发送事件即可
getApplicationEventMulticaster().multicastEvent(applicationEvent, eventType);
}
// Publish event via parent context as well...
if (this.parent != null) {
if (this.parent instanceof AbstractApplicationContext) {
((AbstractApplicationContext) this.parent).publishEvent(event, eventType);
}
else {
this.parent.publishEvent(event);
}
}
}
//事件派发可以是异步
@Override
public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
Executor executor = getTaskExecutor();
for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
if (executor != null) { //使用观察者模式,把所有事件监听器拿来,调用他们的onApplicationEvent方法即可
executor.execute(() -> invokeListener(listener, event));
}
else {
invokeListener(listener, event);
}
}
}
protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
ErrorHandler errorHandler = getErrorHandler();
if (errorHandler != null) {
try {
doInvokeListener(listener, event);
}
catch (Throwable err) {
errorHandler.handleError(err);
}
}
else {
doInvokeListener(listener, event);
}
}
@SuppressWarnings({"rawtypes", "unchecked"})
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()) ||
(event instanceof PayloadApplicationEvent &&
matchesClassCastMessage(msg, ((PayloadApplicationEvent) event).getPayload().getClass()))) {
// Possibly a lambda-defined listener which we could not resolve the generic event type for
// -> let's suppress the exception.
Log loggerToUse = this.lazyLogger;
if (loggerToUse == null) {
loggerToUse = LogFactory.getLog(getClass());
this.lazyLogger = loggerToUse;
}
if (loggerToUse.isTraceEnabled()) {
loggerToUse.trace("Non-matching event type for listener: " + listener, ex);
}
}
else {
throw ex;
}
}
}