> 文章列表 > springboot Aspect切面

springboot Aspect切面

springboot Aspect切面

问题描述
配置切面,但未切到目标类上

切面类

@Component
@Aspect
public class ControllerAspect {//@Pointcut("execution(* com.yzk.learn.springbootsecurity.controller.UserController.info(..))")@Pointcut("execution(* com.learn..*.controller.*.*(..))")//@Pointcut("@annotation(org.springframework.web.bind.annotation.GetMapping)")public void around(){}@Around("around()")public Object doAround(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {try{Object proceed = proceedingJoinPoint.proceed();return proceed;}catch (Exception e){e.printStackTrace();}return null;}
}

目标类

@RestController
@RequestMapping("/user")
@Slf4j
public class UserController extends ApiController {@GetMapping("/info")public String info(HttpSession session) {return null;}

源码分析
因代码复杂且分支多,目前截图的顺序是按照从调用链的末端开始,是为了更好的能debug及找到调用线头,不被别的分支代码影响,debug时可以按照文章顺序,非debug可以从后往前看,从后往前是正常的调用顺序

SignaturePattern类
springboot Aspect切面

JoinPointSignature aMethod 目标类
springboot Aspect切面
World world 切面类及表达式
springboot Aspect切面

private FuzzyBoolean matchesExactlyMethod(JoinPointSignature aMethod, World world, boolean subjectMatch) {//判断参数是否匹配if (parametersCannotMatch(aMethod)) {// System.err.println("Parameter types pattern " + parameterTypes + " pcount: " + aMethod.getParameterTypes().length);return FuzzyBoolean.NO;}// OPTIMIZE only for exact match do the pattern match now? Otherwise defer it until other fast checks complete?//判断方法名称是否匹配 此处name为* aMethod.getName为infoif (!name.matches(aMethod.getName())) {return FuzzyBoolean.NO;}// Check the throws pattern//判断异常类型是否匹配if (subjectMatch && !throwsPattern.matches(aMethod.getExceptions(), world)) {return FuzzyBoolean.NO;}// '*' trivially matches everything, no need to check further//判断路径是否匹配if (!declaringType.isStar()) {if (!declaringType.matchesStatically(aMethod.getDeclaringType().resolve(world))) {return FuzzyBoolean.MAYBE;}}// '*' would match any return value//判断返回值是否匹配if (!returnType.isStar()) {boolean b = returnType.isBangVoid();if (b) {String s = aMethod.getReturnType().getSignature();if (s.length() == 1 && s.charAt(0) == 'V') {// it is void, so not a matchreturn FuzzyBoolean.NO;}} else {if (returnType.isVoid()) {String s = aMethod.getReturnType().getSignature();if (s.length() != 1 || s.charAt(0) != 'V') {// it is not void, so not a matchreturn FuzzyBoolean.NO;}} else {if (!returnType.matchesStatically(aMethod.getReturnType().resolve(world))) {// looking bad, but there might be parameterization to consider...if (!returnType.matchesStatically(aMethod.getGenericReturnType().resolve(world))) {// ok, it's bad.return FuzzyBoolean.MAYBE;}}}}}// The most simple case: pattern is (..) will match anything//参数为(..) 匹配所有参数的方法if (parameterTypes.size() == 1 && parameterTypes.get(0).isEllipsis()) {return FuzzyBoolean.YES;}if (!parameterTypes.canMatchSignatureWithNParameters(aMethod.getParameterTypes().length)) {return FuzzyBoolean.NO;}// OPTIMIZE both resolution of these types and their annotations should be deferred - just pass down a world and do it lower// down// ResolvedType[] resolvedParameters = world.resolve(aMethod.getParameterTypes());ResolvableTypeList rtl = new ResolvableTypeList(world, aMethod.getParameterTypes());// Only fetch the parameter annotations if the pointcut is going to be matching on themResolvedType[][] parameterAnnotationTypes = null;if (isMatchingParameterAnnotations()) {parameterAnnotationTypes = aMethod.getParameterAnnotationTypes();if (parameterAnnotationTypes != null && parameterAnnotationTypes.length == 0) {parameterAnnotationTypes = null;}}if (!parameterTypes.matches(rtl, TypePattern.STATIC, parameterAnnotationTypes).alwaysTrue()) {// It could still be a match based on the generic sig parameter types of a parameterized typeif (!parameterTypes.matches(new ResolvableTypeList(world, aMethod.getGenericParameterTypes()), TypePattern.STATIC,parameterAnnotationTypes).alwaysTrue()) {return FuzzyBoolean.MAYBE;// It could STILL be a match based on the erasure of the parameter types??// to be determined via test cases...}}// check that varargs specifications matchif (!matchesVarArgs(aMethod, world)) {return FuzzyBoolean.MAYBE;}// passed all the guards..return FuzzyBoolean.YES;}

在else if (kind == Member.METHOD) 处调用上一个方法

private FuzzyBoolean matchesExactly(JoinPointSignature aMember, World inAWorld, boolean allowBridgeMethods, boolean subjectMatch) {// Java5 introduces bridge methods, we match a call to them but nothing else...if (aMember.isBridgeMethod() && !allowBridgeMethods) {return FuzzyBoolean.MAYBE;}// Only the subject is checked for modifiers// see http://www.eclipse.org/aspectj/doc/next/adk15notebook/join-point-modifiers.htmlif (subjectMatch && !modifiers.matches(aMember.getModifiers())) {return FuzzyBoolean.NO;}FuzzyBoolean matchesIgnoringAnnotations = FuzzyBoolean.YES;if (kind == Member.STATIC_INITIALIZATION) {matchesIgnoringAnnotations = matchesExactlyStaticInitialization(aMember, inAWorld);} else if (kind == Member.FIELD) {matchesIgnoringAnnotations = matchesExactlyField(aMember, inAWorld);} else if (kind == Member.METHOD) {//上个方法调用处matchesIgnoringAnnotations = matchesExactlyMethod(aMember, inAWorld, subjectMatch);} else if (kind == Member.CONSTRUCTOR) {matchesIgnoringAnnotations = matchesExactlyConstructor(aMember, inAWorld);}if (matchesIgnoringAnnotations.alwaysFalse()) {return FuzzyBoolean.NO;}// Only the subject is checked for annotations (239441/119749)// see http://www.eclipse.org/aspectj/doc/next/adk15notebook/join-point-modifiers.htmlif (subjectMatch) {// The annotations must match if specifiedif (!matchesAnnotations(aMember, inAWorld).alwaysTrue()) {return FuzzyBoolean.NO;} else {return matchesIgnoringAnnotations;}} else {// Unless they specified any annotation then it is a failureif (annotationPattern instanceof AnyAnnotationTypePattern) {return matchesIgnoringAnnotations;} else {return FuzzyBoolean.NO;}}// if (subjectMatch && !matchesAnnotations(aMember, inAWorld).alwaysTrue()) {// return FuzzyBoolean.NO;// } else {//			// return matchesIgnoringAnnotations;// }}

在FuzzyBoolean matchResult = matchesExactly(aSig, world, allowBridgeMethods, subjectMatch);处调用上一个方法

public boolean matches(Member joinPointSignature, World world, boolean allowBridgeMethods) {// fail (or succeed!) fast tests...if (joinPointSignature == null) {return false;}if (kind != joinPointSignature.getKind()) {return false;}if (kind == Member.ADVICE) {return true;}// do the hard work then...boolean subjectMatch = true;boolean wantsAnnotationMatch = wantToMatchAnnotationPattern();JoinPointSignatureIterator candidateMatches = joinPointSignature.getJoinPointSignatures(world);while (candidateMatches.hasNext()) {JoinPointSignature aSig = candidateMatches.next();// System.out.println(aSig);FuzzyBoolean matchResult = matchesExactly(aSig, world, allowBridgeMethods, subjectMatch);if (matchResult.alwaysTrue()) {return true;} else if (matchResult.alwaysFalse()) {return false;}// if we got a "MAYBE" it's worth looking at the other signatures// The first signature is the subject signature - and against it we must match modifiers/annotations/throws// see http://www.eclipse.org/aspectj/doc/next/adk15notebook/join-point-modifiers.htmlsubjectMatch = false;// Early exitif (wantsAnnotationMatch) {return false;}}return false;}

KindedPointcut类

在!signature.matches(shadow.getMatchingSignature(), shadow.getIWorld(), this.kind == Shadow.MethodCall)) 处调用上一个方法

protected FuzzyBoolean matchInternal(Shadow shadow) {if (shadow.getKind() != kind) {return FuzzyBoolean.NO;}if (shadow.getKind() == Shadow.SynchronizationLock && kind == Shadow.SynchronizationLock) {return FuzzyBoolean.YES;}if (shadow.getKind() == Shadow.SynchronizationUnlock && kind == Shadow.SynchronizationUnlock) {return FuzzyBoolean.YES;}if (!signature.matches(shadow.getMatchingSignature(), shadow.getIWorld(), this.kind == Shadow.MethodCall)) {if (kind == Shadow.MethodCall) {warnOnConfusingSig(shadow);// warnOnBridgeMethod(shadow);}return FuzzyBoolean.NO;}return FuzzyBoolean.YES;}

Pointcut类
在ret = matchInternal(shadow);处调用上一个方法

public final FuzzyBoolean match(Shadow shadow) {if (shadow.shadowId == lastMatchedShadowId) {return lastMatchedShadowResult;}FuzzyBoolean ret;// this next test will prevent a lot of un-needed matching going on....if (shadow.getKind().isSet(couldMatchKinds())) {ret = matchInternal(shadow);} else {ret = FuzzyBoolean.NO;}lastMatchedShadowId = shadow.shadowId;lastMatchedShadowResult = ret;return ret;}

PointcutExpressionImpl类
在org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);处调用上一个方法

private ShadowMatchImpl getShadowMatch(Shadow forShadow) {org.aspectj.util.FuzzyBoolean match = pointcut.match(forShadow);Test residueTest = Literal.TRUE;ExposedState state = getExposedState();if (match.maybeTrue()) {residueTest = pointcut.findResidue(forShadow, state);}ShadowMatchImpl sm = new ShadowMatchImpl(match, residueTest, state, parameters);sm.setMatchingContext(this.matchContext);return sm;}

在ShadowMatchImpl sm = getShadowMatch(s);处调用上一个方法

private ShadowMatch matchesExecution(Member aMember) {Shadow s = ReflectionShadow.makeExecutionShadow(world, aMember, this.matchContext);ShadowMatchImpl sm = getShadowMatch(s);sm.setSubject(aMember);sm.setWithinCode(null);sm.setWithinType(aMember.getDeclaringClass());return sm;}

在ShadowMatch match = matchesExecution(aMethod);处调用上一个方法

public ShadowMatch matchesMethodExecution(Method aMethod) {ShadowMatch match = matchesExecution(aMethod);if (MATCH_INFO && match.maybeMatches()) {System.out.println("MATCHINFO: method execution match on '" + aMethod + "' for '" + this.expression + "': "+ (match.alwaysMatches() ? "YES" : "MAYBE"));}return match;}

AspectJExpressionPointcut类
在shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);处调用上一个方法

private ShadowMatch getShadowMatch(Method targetMethod, Method originalMethod) {// Avoid lock contention for known Methods through concurrent access...ShadowMatch shadowMatch = this.shadowMatchCache.get(targetMethod);if (shadowMatch == null) {synchronized (this.shadowMatchCache) {// Not found - now check again with full lock...PointcutExpression fallbackExpression = null;shadowMatch = this.shadowMatchCache.get(targetMethod);if (shadowMatch == null) {Method methodToMatch = targetMethod;try {try {shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);}catch (ReflectionWorldException ex) {// Failed to introspect target method, probably because it has been loaded// in a special ClassLoader. Let's try the declaring ClassLoader instead...try {fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());if (fallbackExpression != null) {shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);}}catch (ReflectionWorldException ex2) {fallbackExpression = null;}}if (targetMethod != originalMethod && (shadowMatch == null ||(shadowMatch.neverMatches() && Proxy.isProxyClass(targetMethod.getDeclaringClass())))) {// Fall back to the plain original method in case of no resolvable match or a// negative match on a proxy class (which doesn't carry any annotations on its// redeclared methods).methodToMatch = originalMethod;try {shadowMatch = obtainPointcutExpression().matchesMethodExecution(methodToMatch);}catch (ReflectionWorldException ex) {// Could neither introspect the target class nor the proxy class ->// let's try the original method's declaring class before we give up...try {fallbackExpression = getFallbackPointcutExpression(methodToMatch.getDeclaringClass());if (fallbackExpression != null) {shadowMatch = fallbackExpression.matchesMethodExecution(methodToMatch);}}catch (ReflectionWorldException ex2) {fallbackExpression = null;}}}}catch (Throwable ex) {// Possibly AspectJ 1.8.10 encountering an invalid signaturelogger.debug("PointcutExpression matching rejected target method", ex);fallbackExpression = null;}if (shadowMatch == null) {shadowMatch = new ShadowMatchImpl(org.aspectj.util.FuzzyBoolean.NO, null, null, null);}else if (shadowMatch.maybeMatches() && fallbackExpression != null) {shadowMatch = new DefensiveShadowMatch(shadowMatch,fallbackExpression.matchesMethodExecution(methodToMatch));}this.shadowMatchCache.put(targetMethod, shadowMatch);}}}return shadowMatch;}

在return getShadowMatch(targetMethod, method);处调用上一个方法

private ShadowMatch getTargetShadowMatch(Method method, Class<?> targetClass) {Method targetMethod = AopUtils.getMostSpecificMethod(method, targetClass);if (targetMethod.getDeclaringClass().isInterface()) {// Try to build the most specific interface possible for inherited methods to be// considered for sub-interface matches as well, in particular for proxy classes.// Note: AspectJ is only going to take Method.getDeclaringClass() into account.Set<Class<?>> ifcs = ClassUtils.getAllInterfacesForClassAsSet(targetClass);if (ifcs.size() > 1) {try {Class<?> compositeInterface = ClassUtils.createCompositeInterface(ClassUtils.toClassArray(ifcs), targetClass.getClassLoader());targetMethod = ClassUtils.getMostSpecificMethod(targetMethod, compositeInterface);}catch (IllegalArgumentException ex) {// Implemented interfaces probably expose conflicting method signatures...// Proceed with original target method.}}}return getShadowMatch(targetMethod, method);}

在ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);处调用上一个方法

public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {obtainPointcutExpression();ShadowMatch shadowMatch = getTargetShadowMatch(method, targetClass);// Special handling for this, target, @this, @target, @annotation// in Spring - we can optimize since we know we have exactly this class,// and there will never be matching subclass at runtime.if (shadowMatch.alwaysMatches()) {return true;}else if (shadowMatch.neverMatches()) {return false;}else {// the maybe caseif (hasIntroductions) {return true;}// A match test returned maybe - if there are any subtype sensitive variables// involved in the test (this, target, at_this, at_target, at_annotation) then// we say this is not a match as in Spring there will never be a different// runtime subtype.RuntimeTestWalker walker = getRuntimeTestWalker(shadowMatch);return (!walker.testsSubtypeSensitiveVars() || walker.testTargetInstanceOfResidue(targetClass));}}

AopUtils类
在(introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass))处调用上一个方法

public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {Assert.notNull(pc, "Pointcut must not be null");if (!pc.getClassFilter().matches(targetClass)) {return false;}MethodMatcher methodMatcher = pc.getMethodMatcher();if (methodMatcher == MethodMatcher.TRUE) {// No need to iterate the methods if we're matching any method anyway...return true;}IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;if (methodMatcher instanceof IntroductionAwareMethodMatcher) {introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;}Set<Class<?>> classes = new LinkedHashSet<>();if (!Proxy.isProxyClass(targetClass)) {classes.add(ClassUtils.getUserClass(targetClass));}classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));for (Class<?> clazz : classes) {Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);for (Method method : methods) {if (introductionAwareMethodMatcher != null ?introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :methodMatcher.matches(method, targetClass)) {return true;}}}return false;}

在return canApply(pca.getPointcut(), targetClass, hasIntroductions);调用上一个方法

public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {if (advisor instanceof IntroductionAdvisor) {return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);}else if (advisor instanceof PointcutAdvisor) {PointcutAdvisor pca = (PointcutAdvisor) advisor;return canApply(pca.getPointcut(), targetClass, hasIntroductions);}else {// It doesn't have a pointcut so we assume it applies.return true;}}

在canApply(candidate, clazz, hasIntroductions)处调用上一个方法

public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {if (candidateAdvisors.isEmpty()) {return candidateAdvisors;}List<Advisor> eligibleAdvisors = new ArrayList<>();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {eligibleAdvisors.add(candidate);}}boolean hasIntroductions = !eligibleAdvisors.isEmpty();for (Advisor candidate : candidateAdvisors) {if (candidate instanceof IntroductionAdvisor) {// already processedcontinue;}if (canApply(candidate, clazz, hasIntroductions)) {eligibleAdvisors.add(candidate);}}return eligibleAdvisors;}

AbstractAdvisorAutoProxyCreator类
在return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);处调用上一个方法

protected List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {ProxyCreationContext.setCurrentProxiedBeanName(beanName);try {return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);}finally {ProxyCreationContext.setCurrentProxiedBeanName(null);}}

在List eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);处调用上一个方法

protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {List<Advisor> candidateAdvisors = findCandidateAdvisors();List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);extendAdvisors(eligibleAdvisors);if (!eligibleAdvisors.isEmpty()) {eligibleAdvisors = sortAdvisors(eligibleAdvisors);}return eligibleAdvisors;}

在List advisors = findEligibleAdvisors(beanClass, beanName);处调用上一个方法

protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);if (advisors.isEmpty()) {return DO_NOT_PROXY;}return advisors.toArray();}

AbstractAutoProxyCreator类
在Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);处调用上一个方法

此处需要关注的地方就是
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
生成了相应的代理类

protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {return bean;}if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {return bean;}if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}// Create proxy if we have advice.Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);if (specificInterceptors != DO_NOT_PROXY) {this.advisedBeans.put(cacheKey, Boolean.TRUE);Object proxy = createProxy(bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));this.proxyTypes.put(cacheKey, proxy.getClass());return proxy;}this.advisedBeans.put(cacheKey, Boolean.FALSE);return bean;}

在return wrapIfNecessary(bean, beanName, cacheKey);处调用上一个方法

public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {if (bean != null) {Object cacheKey = getCacheKey(bean.getClass(), beanName);if (this.earlyProxyReferences.remove(cacheKey) != bean) {return wrapIfNecessary(bean, beanName, cacheKey);}}return bean;}

AbstractAutowireCapableBeanFactory类
在Object current = processor.postProcessAfterInitialization(result, beanName);处调用上一个方法

public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)throws BeansException {Object result = existingBean;for (BeanPostProcessor processor : getBeanPostProcessors()) {Object current = processor.postProcessAfterInitialization(result, beanName);if (current == null) {return result;}result = current;}return result;}

在wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);处调用上一个方法

protected Object initializeBean(String beanName, Object bean, @Nullable RootBeanDefinition mbd) {if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {invokeAwareMethods(beanName, bean);return null;}, getAccessControlContext());}else {invokeAwareMethods(beanName, bean);}Object wrappedBean = bean;if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);}try {invokeInitMethods(beanName, wrappedBean, mbd);}catch (Throwable ex) {throw new BeanCreationException((mbd != null ? mbd.getResourceDescription() : null),beanName, "Invocation of init method failed", ex);}if (mbd == null || !mbd.isSynthetic()) {wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);}return wrappedBean;}

在exposedObject = initializeBean(beanName, exposedObject, mbd);处调用上一个方法

protected Object doCreateBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {// Instantiate the bean.BeanWrapper instanceWrapper = null;if (mbd.isSingleton()) {instanceWrapper = this.factoryBeanInstanceCache.remove(beanName);}if (instanceWrapper == null) {instanceWrapper = createBeanInstance(beanName, mbd, args);}Object bean = instanceWrapper.getWrappedInstance();Class<?> beanType = instanceWrapper.getWrappedClass();if (beanType != NullBean.class) {mbd.resolvedTargetType = beanType;}// Allow post-processors to modify the merged bean definition.synchronized (mbd.postProcessingLock) {if (!mbd.postProcessed) {try {applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);}catch (Throwable ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Post-processing of merged bean definition failed", ex);}mbd.postProcessed = true;}}// Eagerly cache singletons to be able to resolve circular references// even when triggered by lifecycle interfaces like BeanFactoryAware.boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&isSingletonCurrentlyInCreation(beanName));if (earlySingletonExposure) {if (logger.isTraceEnabled()) {logger.trace("Eagerly caching bean '" + beanName +"' to allow for resolving potential circular references");}addSingletonFactory(beanName, () -> getEarlyBeanReference(beanName, mbd, bean));}// Initialize the bean instance.Object exposedObject = bean;try {populateBean(beanName, mbd, instanceWrapper);exposedObject = initializeBean(beanName, exposedObject, mbd);}catch (Throwable ex) {if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {throw (BeanCreationException) ex;}else {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);}}if (earlySingletonExposure) {Object earlySingletonReference = getSingleton(beanName, false);if (earlySingletonReference != null) {if (exposedObject == bean) {exposedObject = earlySingletonReference;}else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {String[] dependentBeans = getDependentBeans(beanName);Set<String> actualDependentBeans = new LinkedHashSet<>(dependentBeans.length);for (String dependentBean : dependentBeans) {if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {actualDependentBeans.add(dependentBean);}}if (!actualDependentBeans.isEmpty()) {throw new BeanCurrentlyInCreationException(beanName,"Bean with name '" + beanName + "' has been injected into other beans [" +StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +"] in its raw version as part of a circular reference, but has eventually been " +"wrapped. This means that said other beans do not use the final version of the " +"bean. This is often the result of over-eager type matching - consider using " +"'getBeanNamesForType' with the 'allowEagerInit' flag turned off, for example.");}}}}// Register bean as disposable.try {registerDisposableBeanIfNecessary(beanName, bean, mbd);}catch (BeanDefinitionValidationException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Invalid destruction signature", ex);}return exposedObject;}

在Object beanInstance = doCreateBean(beanName, mbdToUse, args);处调用上一个方法

@Overrideprotected Object createBean(String beanName, RootBeanDefinition mbd, @Nullable Object[] args)throws BeanCreationException {if (logger.isTraceEnabled()) {logger.trace("Creating instance of bean '" + beanName + "'");}RootBeanDefinition mbdToUse = mbd;// Make sure bean class is actually resolved at this point, and// clone the bean definition in case of a dynamically resolved Class// which cannot be stored in the shared merged bean definition.Class<?> resolvedClass = resolveBeanClass(mbd, beanName);if (resolvedClass != null && !mbd.hasBeanClass() && mbd.getBeanClassName() != null) {mbdToUse = new RootBeanDefinition(mbd);mbdToUse.setBeanClass(resolvedClass);}// Prepare method overrides.try {mbdToUse.prepareMethodOverrides();}catch (BeanDefinitionValidationException ex) {throw new BeanDefinitionStoreException(mbdToUse.getResourceDescription(),beanName, "Validation of method overrides failed", ex);}try {// Give BeanPostProcessors a chance to return a proxy instead of the target bean instance.Object bean = resolveBeforeInstantiation(beanName, mbdToUse);if (bean != null) {return bean;}}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName,"BeanPostProcessor before instantiation of bean failed", ex);}try {Object beanInstance = doCreateBean(beanName, mbdToUse, args);if (logger.isTraceEnabled()) {logger.trace("Finished creating instance of bean '" + beanName + "'");}return beanInstance;}catch (BeanCreationException | ImplicitlyAppearedSingletonException ex) {// A previously detected exception with proper bean creation context already,// or illegal singleton state to be communicated up to DefaultSingletonBeanRegistry.throw ex;}catch (Throwable ex) {throw new BeanCreationException(mbdToUse.getResourceDescription(), beanName, "Unexpected exception during bean creation", ex);}}

DefaultSingletonBeanRegistry类
在singletonObject = singletonFactory.getObject();处调用上面的方法

public Object getSingleton(String beanName, ObjectFactory<?> singletonFactory) {Assert.notNull(beanName, "Bean name must not be null");synchronized (this.singletonObjects) {Object singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {if (this.singletonsCurrentlyInDestruction) {throw new BeanCreationNotAllowedException(beanName,"Singleton bean creation not allowed while singletons of this factory are in destruction " +"(Do not request a bean from a BeanFactory in a destroy method implementation!)");}if (logger.isDebugEnabled()) {logger.debug("Creating shared instance of singleton bean '" + beanName + "'");}beforeSingletonCreation(beanName);boolean newSingleton = false;boolean recordSuppressedExceptions = (this.suppressedExceptions == null);if (recordSuppressedExceptions) {this.suppressedExceptions = new LinkedHashSet<>();}try {singletonObject = singletonFactory.getObject();newSingleton = true;}catch (IllegalStateException ex) {// Has the singleton object implicitly appeared in the meantime ->// if yes, proceed with it since the exception indicates that state.singletonObject = this.singletonObjects.get(beanName);if (singletonObject == null) {throw ex;}}catch (BeanCreationException ex) {if (recordSuppressedExceptions) {for (Exception suppressedException : this.suppressedExceptions) {ex.addRelatedCause(suppressedException);}}throw ex;}finally {if (recordSuppressedExceptions) {this.suppressedExceptions = null;}afterSingletonCreation(beanName);}if (newSingleton) {addSingleton(beanName, singletonObject);}}return singletonObject;}}

AbstractBeanFactory类
在sharedInstance = getSingleton(beanName, () ->{})处调用上一个方法 此处需要注意,是在匿名内部类中的执行

protected <T> T doGetBean(String name, @Nullable Class<T> requiredType, @Nullable Object[] args, boolean typeCheckOnly)throws BeansException {String beanName = transformedBeanName(name);Object beanInstance;// Eagerly check singleton cache for manually registered singletons.Object sharedInstance = getSingleton(beanName);if (sharedInstance != null && args == null) {if (logger.isTraceEnabled()) {if (isSingletonCurrentlyInCreation(beanName)) {logger.trace("Returning eagerly cached instance of singleton bean '" + beanName +"' that is not fully initialized yet - a consequence of a circular reference");}else {logger.trace("Returning cached instance of singleton bean '" + beanName + "'");}}beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, null);}else {// Fail if we're already creating this bean instance:// We're assumably within a circular reference.if (isPrototypeCurrentlyInCreation(beanName)) {throw new BeanCurrentlyInCreationException(beanName);}// Check if bean definition exists in this factory.BeanFactory parentBeanFactory = getParentBeanFactory();if (parentBeanFactory != null && !containsBeanDefinition(beanName)) {// Not found -> check parent.String nameToLookup = originalBeanName(name);if (parentBeanFactory instanceof AbstractBeanFactory) {return ((AbstractBeanFactory) parentBeanFactory).doGetBean(nameToLookup, requiredType, args, typeCheckOnly);}else if (args != null) {// Delegation to parent with explicit args.return (T) parentBeanFactory.getBean(nameToLookup, args);}else if (requiredType != null) {// No args -> delegate to standard getBean method.return parentBeanFactory.getBean(nameToLookup, requiredType);}else {return (T) parentBeanFactory.getBean(nameToLookup);}}if (!typeCheckOnly) {markBeanAsCreated(beanName);}StartupStep beanCreation = this.applicationStartup.start("spring.beans.instantiate").tag("beanName", name);try {if (requiredType != null) {beanCreation.tag("beanType", requiredType::toString);}RootBeanDefinition mbd = getMergedLocalBeanDefinition(beanName);checkMergedBeanDefinition(mbd, beanName, args);// Guarantee initialization of beans that the current bean depends on.String[] dependsOn = mbd.getDependsOn();if (dependsOn != null) {for (String dep : dependsOn) {if (isDependent(beanName, dep)) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"Circular depends-on relationship between '" + beanName + "' and '" + dep + "'");}registerDependentBean(dep, beanName);try {getBean(dep);}catch (NoSuchBeanDefinitionException ex) {throw new BeanCreationException(mbd.getResourceDescription(), beanName,"'" + beanName + "' depends on missing bean '" + dep + "'", ex);}}}// Create bean instance.if (mbd.isSingleton()) {sharedInstance = getSingleton(beanName, () -> {try {return createBean(beanName, mbd, args);}catch (BeansException ex) {// Explicitly remove instance from singleton cache: It might have been put there// eagerly by the creation process, to allow for circular reference resolution.// Also remove any beans that received a temporary reference to the bean.destroySingleton(beanName);throw ex;}});beanInstance = getObjectForBeanInstance(sharedInstance, name, beanName, mbd);}else if (mbd.isPrototype()) {// It's a prototype -> create a new instance.Object prototypeInstance = null;try {beforePrototypeCreation(beanName);prototypeInstance = createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}beanInstance = getObjectForBeanInstance(prototypeInstance, name, beanName, mbd);}else {String scopeName = mbd.getScope();if (!StringUtils.hasLength(scopeName)) {throw new IllegalStateException("No scope name defined for bean '" + beanName + "'");}Scope scope = this.scopes.get(scopeName);if (scope == null) {throw new IllegalStateException("No Scope registered for scope name '" + scopeName + "'");}try {Object scopedInstance = scope.get(beanName, () -> {beforePrototypeCreation(beanName);try {return createBean(beanName, mbd, args);}finally {afterPrototypeCreation(beanName);}});beanInstance = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);}catch (IllegalStateException ex) {throw new ScopeNotActiveException(beanName, scopeName, ex);}}}catch (BeansException ex) {beanCreation.tag("exception", ex.getClass().toString());beanCreation.tag("message", String.valueOf(ex.getMessage()));cleanupAfterBeanCreationFailure(beanName);throw ex;}finally {beanCreation.end();}}return adaptBeanInstance(name, beanInstance, requiredType);}
public Object getBean(String name) throws BeansException {return doGetBean(name, null, null, false);}

DefaultListableBeanFactory类
在getBean(beanName);处调用上一个方法

public void preInstantiateSingletons() throws BeansException {if (logger.isTraceEnabled()) {logger.trace("Pre-instantiating singletons in " + this);}// Iterate over a copy to allow for init methods which in turn register new bean definitions.// While this may not be part of the regular factory bootstrap, it does otherwise work fine.List<String> beanNames = new ArrayList<>(this.beanDefinitionNames);// Trigger initialization of all non-lazy singleton beans...for (String beanName : beanNames) {RootBeanDefinition bd = getMergedLocalBeanDefinition(beanName);if (!bd.isAbstract() && bd.isSingleton() && !bd.isLazyInit()) {if (isFactoryBean(beanName)) {Object bean = getBean(FACTORY_BEAN_PREFIX + beanName);if (bean instanceof FactoryBean) {FactoryBean<?> factory = (FactoryBean<?>) bean;boolean isEagerInit;if (System.getSecurityManager() != null && factory instanceof SmartFactoryBean) {isEagerInit = AccessController.doPrivileged((PrivilegedAction<Boolean>) ((SmartFactoryBean<?>) factory)::isEagerInit,getAccessControlContext());}else {isEagerInit = (factory instanceof SmartFactoryBean &&((SmartFactoryBean<?>) factory).isEagerInit());}if (isEagerInit) {getBean(beanName);}}}else {getBean(beanName);}}}// Trigger post-initialization callback for all applicable beans...for (String beanName : beanNames) {Object singletonInstance = getSingleton(beanName);if (singletonInstance instanceof SmartInitializingSingleton) {StartupStep smartInitialize = this.getApplicationStartup().start("spring.beans.smart-initialize").tag("beanName", beanName);SmartInitializingSingleton smartSingleton = (SmartInitializingSingleton) singletonInstance;if (System.getSecurityManager() != null) {AccessController.doPrivileged((PrivilegedAction<Object>) () -> {smartSingleton.afterSingletonsInstantiated();return null;}, getAccessControlContext());}else {smartSingleton.afterSingletonsInstantiated();}smartInitialize.end();}}}

AbstractApplicationContext类
在beanFactory.preInstantiateSingletons();处调用上一个方法

protected void finishBeanFactoryInitialization(ConfigurableListableBeanFactory beanFactory) {// Initialize conversion service for this context.if (beanFactory.containsBean(CONVERSION_SERVICE_BEAN_NAME) &&beanFactory.isTypeMatch(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class)) {beanFactory.setConversionService(beanFactory.getBean(CONVERSION_SERVICE_BEAN_NAME, ConversionService.class));}// Register a default embedded value resolver if no BeanFactoryPostProcessor// (such as a PropertySourcesPlaceholderConfigurer bean) registered any before:// at this point, primarily for resolution in annotation attribute values.if (!beanFactory.hasEmbeddedValueResolver()) {beanFactory.addEmbeddedValueResolver(strVal -> getEnvironment().resolvePlaceholders(strVal));}// Initialize LoadTimeWeaverAware beans early to allow for registering their transformers early.String[] weaverAwareNames = beanFactory.getBeanNamesForType(LoadTimeWeaverAware.class, false, false);for (String weaverAwareName : weaverAwareNames) {getBean(weaverAwareName);}// Stop using the temporary ClassLoader for type matching.beanFactory.setTempClassLoader(null);// Allow for caching all bean definition metadata, not expecting further changes.beanFactory.freezeConfiguration();// Instantiate all remaining (non-lazy-init) singletons.beanFactory.preInstantiateSingletons();}

在finishBeanFactoryInitialization(beanFactory);处调用上一个方法

public void refresh() throws BeansException, IllegalStateException {synchronized (this.startupShutdownMonitor) {StartupStep contextRefresh = this.applicationStartup.start("spring.context.refresh");// Prepare this context for refreshing.prepareRefresh();// Tell the subclass to refresh the internal bean factory.ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();// Prepare the bean factory for use in this context.prepareBeanFactory(beanFactory);try {// Allows post-processing of the bean factory in context subclasses.postProcessBeanFactory(beanFactory);StartupStep beanPostProcess = this.applicationStartup.start("spring.context.beans.post-process");// Invoke factory processors registered as beans in the context.invokeBeanFactoryPostProcessors(beanFactory);// Register bean processors that intercept bean creation.registerBeanPostProcessors(beanFactory);beanPostProcess.end();// Initialize message source for this context.initMessageSource();// Initialize event multicaster for this context.initApplicationEventMulticaster();// Initialize other special beans in specific context subclasses.onRefresh();// Check for listener beans and register them.registerListeners();// Instantiate all remaining (non-lazy-init) singletons.finishBeanFactoryInitialization(beanFactory);// Last step: publish corresponding event.finishRefresh();}catch (BeansException ex) {if (logger.isWarnEnabled()) {logger.warn("Exception encountered during context initialization - " +"cancelling refresh attempt: " + ex);}// Destroy already created singletons to avoid dangling resources.destroyBeans();// Reset 'active' flag.cancelRefresh(ex);// Propagate exception to caller.throw ex;}finally {// Reset common introspection caches in Spring's core, since we// might not ever need metadata for singleton beans anymore...resetCommonCaches();contextRefresh.end();}}}

ServletWebServerApplicationContext类

public final void refresh() throws BeansException, IllegalStateException {try {super.refresh();}catch (RuntimeException ex) {WebServer webServer = this.webServer;if (webServer != null) {webServer.stop();}throw ex;}}

SpringApplication类

private void refreshContext(ConfigurableApplicationContext context) {if (this.registerShutdownHook) {shutdownHook.registerApplicationContext(context);}refresh(context);}
public ConfigurableApplicationContext run(String... args) {StopWatch stopWatch = new StopWatch();stopWatch.start();DefaultBootstrapContext bootstrapContext = createBootstrapContext();ConfigurableApplicationContext context = null;configureHeadlessProperty();SpringApplicationRunListeners listeners = getRunListeners(args);listeners.starting(bootstrapContext, this.mainApplicationClass);try {ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);ConfigurableEnvironment environment = prepareEnvironment(listeners, bootstrapContext, applicationArguments);configureIgnoreBeanInfo(environment);Banner printedBanner = printBanner(environment);context = createApplicationContext();context.setApplicationStartup(this.applicationStartup);prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);refreshContext(context);afterRefresh(context, applicationArguments);stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}listeners.started(context);callRunners(context, applicationArguments);}catch (Throwable ex) {handleRunFailure(context, ex, listeners);throw new IllegalStateException(ex);}try {listeners.running(context);}catch (Throwable ex) {handleRunFailure(context, ex, null);throw new IllegalStateException(ex);}return context;}
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);}
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {return run(new Class<?>[] { primarySource }, args);}
public static void main(String[] args) {SpringApplication.run(SpringBootSecurityApplication.class, args);}

凯普网