- 使用 Spring Initializr 创建 Spring Boot 应用程序
- 在Spring Boot中配置Cassandra
- 在 Spring Boot 上配置 Tomcat 连接池
- 将Camel消息路由到嵌入WildFly的Artemis上
上一篇文章已经详细介绍了两种aop自动代理创建器的导入流程分析,此时我们已经知道了自动代理创建器注册到容器中的流程,下面我们来探究一下,自动代理创建器对具体bean创建代理的流程,这里测试环境还是用上一篇中开头给出的测试环境。
Spring读源码系列之AOP–08–aop执行完整源码流程之自动代理创建器导入的两种方式
首先我们需要知道AnnotationAwareAspectJAutoProxyCreator是一个bean的后置处理器(Spring读源码系列之AOP–07—aop自动代理创建器(拿下AOP的最后一击))
这里对有关自动代理的后置处理器相关回调接口被调用时机不清楚的,看上面给出的那篇文章链接
对bean初始化源码流程不清楚的,去看我之前写的bean初始化流程源码分析
AbstractAutoProxyCreator是AnnotationAwareAspectJAutoProxyCreator的父类
postProcessAfterInitialization方法在该类中进行实现
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
//如果当前bean还没有通过getEarlyBeanReference方法提早暴露出去,那么尝试进行代理
//因为getEarlyBeanReference方法会尝试对提早暴露的bean进行代理,同样也是调用wrapIfNecessary方法
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
//如果已经处理过,不需要代理,是基础类,是OriginalInstance,那么当前bean都应该直接跳过,不做任何操作
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.
//获取到可以应用到当前bean上的拦截器链
//getAdvicesAndAdvisorsForBean在AbstractAutoProxyCreator类中为抽象方法,留给不同的子类去实现
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
//DO_NOT_PROXY代表一个空的Object[],如果不为空,说明需要代理
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;
}
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
//findEligibleAdvisors--寻找可用于当前bean上的增强器
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
//获取容器中所有Advisor类型bean
List<Advisor> candidateAdvisors = findCandidateAdvisors();
//进行过滤,找到能应用到当前bean上的拦截器链
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
//钩子方法,子类实现用来新增拦截器到拦截器链中
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
//对拦截器链中的拦截器进行排序操作
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
protected List<Advisor> findCandidateAdvisors() {
// Add all the Spring advisors found according to superclass rules.
//父类借助advisorRetrievalHelper去容器中获取所有可用的增强器
List<Advisor> advisors = super.findCandidateAdvisors();
// Build Advisors for all AspectJ aspects in the bean factory.
if (this.aspectJAdvisorsBuilder != null) {
advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
}
return advisors;
}
protected List<Advisor> findCandidateAdvisors() {
Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
return this.advisorRetrievalHelper.findAdvisorBeans();
}
advisorRetrievalHelper的findAdvisorBeans方法
public List<Advisor> findAdvisorBeans() {
// Determine list of advisor bean names, if not cached already.
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
// Do not initialize FactoryBeans here: We need to leave all regular beans
// uninitialized to let the auto-proxy creator apply to them!
//从容器中拿取到所有类型为Advisor的bean
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
//isEligibleBean通过正则匹配之类的方法,先过滤掉一批增强器
if (isEligibleBean(name)) {
//跳过正在创建的增强器
if (this.beanFactory.isCurrentlyInCreation(name)) {
if (logger.isTraceEnabled()) {
logger.trace("Skipping currently created advisor '" + name + "'");
}
}
else {
try {
//加入增强器集合,然后返回
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
...
}
}
}
return advisors;
}
public List<Advisor> buildAspectJAdvisors() {
List<String> aspectNames = this.aspectBeanNames;
//如果此时aspectBeanNames为空
//下面会去容器中解析出所有标注了AspectJ注解的切面类,然后将其解析为一组增强器链
if (aspectNames == null) {
synchronized (this) {
aspectNames = this.aspectBeanNames;
if (aspectNames == null) {
List<Advisor> advisors = new ArrayList<>();
aspectNames = new ArrayList<>();
//拿到容器中所有的bean
String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Object.class, true, false);
for (String beanName : beanNames) {
//通过正则表达式之类的匹配式,先过滤掉一批不符合的bean
if (!isEligibleBean(beanName)) {
continue;
}
// We must be careful not to instantiate beans eagerly as in this case they
// would be cached by the Spring container but would not have been weaved.
Class<?> beanType = this.beanFactory.getType(beanName, false);
if (beanType == null) {
continue;
}
//当前bean的上要标注了AspectJ注解才可以
if (this.advisorFactory.isAspect(beanType)) {
aspectNames.add(beanName);
//为当前标注了AspectJ注解的切面类构造一个切面类元数据信息
AspectMetadata amd = new AspectMetadata(beanType, beanName);
//如果切面是单例的,这里的单例指的是@AspectJ("singleton"),默认都是单例的
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
//创建生成切面对象的工厂
MetadataAwareAspectInstanceFactory factory =
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
//AspectJAdvisorFactory可以根据MetadataAwareAspectInstanceFactory
//获取到当前切面解析后的一组增强器链
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
//将解析后的结果进行保存,即当前切面已经关联了一组增强器链
if (this.beanFactory.isSingleton(beanName)) {
this.advisorsCache.put(beanName, classAdvisors);
}
else {
//如果当前切面是多例的--这里的多例指的是spring层面的多例
this.aspectFactoryCache.put(beanName, factory);
}
advisors.addAll(classAdvisors);
}
else {
//如果是Aspectj层面的其他类型的切面,例如perthis,pertarget,这里不多讲
// Per target or per this.
if (this.beanFactory.isSingleton(beanName)) {
throw new IllegalArgumentException("Bean with name '" + beanName +
"' is a singleton, but aspect instantiation model is not singleton");
}
MetadataAwareAspectInstanceFactory factory =
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
this.aspectFactoryCache.put(beanName, factory);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
}
this.aspectBeanNames = aspectNames;
//返回当前切面类解析后得到的一组增强器链
return advisors;
}
}
}
if (aspectNames.isEmpty()) {
return Collections.emptyList();
}
//如果第二次来,此时aspectBeanNames不为null,那么尝试从缓存中获取,如果缓存中获取不到,再通过AspectJAdvisorFactory去获取
List<Advisor> advisors = new ArrayList<>();
for (String aspectName : aspectNames) {
List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
if (cachedAdvisors != null) {
advisors.addAll(cachedAdvisors);
}
else {
MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
advisors.addAll(this.advisorFactory.getAdvisors(factory));
}
}
return advisors;
}
@Override
public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
//拿到切面工厂中保存的切面的class和切面name
Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
//对切面类进行校验,如果父类上也有AspectJ注解,但是父类不是抽象的,那么会抛出异常,并且当前切面必须是默认的单例--aspectj层面的
validate(aspectClass);
// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
// so that it will only instantiate once.
//防止对切面的重复实例化---还有一个特点是切面只要使用到的时候,才会创建,即懒加载策略
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new ArrayList<>();
//getAdvisorMethods--获取切面类中所有方法,除了被Pointcut注解标注的方法,并且这所有方法还包括其父类继承链的,继承的接口方法
for (Method method : getAdvisorMethods(aspectClass)) {
// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
// to getAdvisor(...) to represent the "current position" in the declared methods list.
// However, since Java 7 the "current position" is not valid since the JDK no longer
// returns declared methods in the order in which they are declared in the source code.
// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
// discovered via reflection in order to support reliable advice ordering across JVM launches.
// Specifically, a value of 0 aligns with the default value used in
// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
//将该adviceMethod构造为一个Adv返回isor
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
if (advisor != null) {
advisors.add(advisor);
}
}
// If it's a per target aspect, emit the dummy instantiating aspect.
//如果当前aspectJ不是signleton的,那么做相关处理
//默认都是单例的(不是spring层面的,是aspectj层面的)
if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
advisors.add(0, instantiationAdvisor);
}
// Find introduction fields.
//@DeclareParents注解的处理,引介增强处理--这里先不讲,感兴趣可以自己去了解一下
for (Field field : aspectClass.getDeclaredFields()) {
Advisor advisor = getDeclareParentsAdvisor(field);
if (advisor != null) {
advisors.add(advisor);
}
}
return advisors;
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
List<Method> methods = new ArrayList<>();
//adviceMethodFilter会过滤掉被pointCut标注的方法
//methods::add向methods集合存入当前切面类除了被过滤掉以外的方法
ReflectionUtils.doWithMethods(aspectClass, methods::add, adviceMethodFilter);
if (methods.size() > 1) {
methods.sort(adviceMethodComparator);
}
return methods;
}
adviceMethodFilter比较简单:
// Exclude @Pointcut methods
private static final MethodFilter adviceMethodFilter = ReflectionUtils.USER_DECLARED_METHODS
.and(method -> (AnnotationUtils.getAnnotation(method, Pointcut.class) == null));
ReflectionUtils的doWithMethods方法
public static void doWithMethods(Class<?> clazz, MethodCallback mc, @Nullable MethodFilter mf) {
// Keep backing up the inheritance hierarchy.
Method[] methods = getDeclaredMethods(clazz, false);
for (Method method : methods) {
//过滤器进行过滤
if (mf != null && !mf.matches(method)) {
continue;
}
try {
//mc.dowith操作就是将合法的方法加入集合
mc.doWith(method);
}
catch (IllegalAccessException ex) {
throw new IllegalStateException("Not allowed to access method '" + method.getName() + "': " + ex);
}
}
//还会沿着继承链一之去找,直到找到Object为止
if (clazz.getSuperclass() != null && (mf != USER_DECLARED_METHODS || clazz.getSuperclass() != Object.class)) {
doWithMethods(clazz.getSuperclass(), mc, mf);
}
//继承的接口里面的方法也不会放过
else if (clazz.isInterface()) {
for (Class<?> superIfc : clazz.getInterfaces()) {
doWithMethods(superIfc, mc, mf);
}
}
}
public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
int declarationOrderInAspect, String aspectName) {
//对切面类进行校验,如果父类上也有AspectJ注解,但是父类不是抽象的,那么会抛出异常,并且当前切面必须是默认的单例--aspectj层面的
validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());
//尝试去获取当前方法上的pointcut,如果获取不到,说明当前方法不是增强器方法
//这里不是去获取pointcut注解内的切点表达式,pointcut注解标注的方法在 getAdvisorMethods中就已经被过滤掉了
//这里获取到的是@Before("切点表达式")或者@Before("excution(* *.*.*.(..)")
AspectJExpressionPointcut expressionPointcut = getPointcut(
candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());
//返回的 AspectJExpressionPointcut 为null,说明当前方法上没有标注相关增强器注解
if (expressionPointcut == null) {
return null;
}
//构造一个aspectJ相关的advisor返回
return new InstantiationModelAwarePointcutAdvisorImpl(
//切点表达式 advice方法
expressionPointcut, candidateAdviceMethod,
//当前ReflectiveAspectJAdvisorFactory工厂
this, aspectInstanceFactory,
//固定为0 切面名
declarationOrderInAspect, aspectName);
}
@Nullable
private AspectJExpressionPointcut getPointcut(Method candidateAdviceMethod, Class<?> candidateAspectClass) {
//寻找到方法上第一个出现的增强器注解,如@Before,@After...
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
//没找到,返回null,说明当前方法不是增强器方法
if (aspectJAnnotation == null) {
return null;
}
//构造一个AspectJExpressionPointcut
AspectJExpressionPointcut ajexp =
new AspectJExpressionPointcut(candidateAspectClass, new String[0], new Class<?>[0]);
//设置AspectJExpressionPointcut的切点表达式,即@Before("切点表达式")
//当然括号里面可以直接是切点表达式,也可以是一个方法名(),该方法上标注的pointcut注解中写了真正的切点表达式
//所以一般情况下,这里拿到的切点表达式都长这个样子: point()
ajexp.setExpression(aspectJAnnotation.getPointcutExpression());
//设置该AspectJExpressionPointcut 关联的IOC容器
if (this.beanFactory != null) {
ajexp.setBeanFactory(this.beanFactory);
}
return ajexp;
}
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod方法
查找并返回给定方法的第一个 AspectJ 注解(无论如何应该只有一个…)。
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
}
return null;
}
public InstantiationModelAwarePointcutAdvisorImpl(AspectJExpressionPointcut declaredPointcut,
Method aspectJAdviceMethod, AspectJAdvisorFactory aspectJAdvisorFactory,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//pointcut
this.declaredPointcut = declaredPointcut;
//切面类型
this.declaringClass = aspectJAdviceMethod.getDeclaringClass();
//增强方法名
this.methodName = aspectJAdviceMethod.getName();
//增强方法的参数类型数组
this.parameterTypes = aspectJAdviceMethod.getParameterTypes();
//增强方法
this.aspectJAdviceMethod = aspectJAdviceMethod;
//解析切面类,创建advisor的工厂
this.aspectJAdvisorFactory = aspectJAdvisorFactory;
//生产切面的工厂
this.aspectInstanceFactory = aspectInstanceFactory;
//固定为0
this.declarationOrder = declarationOrder;
//切面名
this.aspectName = aspectName;
//如果切面是懒加载的
//isLazilyInstantiated--->return (isPerThisOrPerTarget() || isPerTypeWithin());
//因此这里先不用管,默认切面都是单例的
if (aspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
// Static part of the pointcut is a lazy type.
Pointcut preInstantiationPointcut = Pointcuts.union(
aspectInstanceFactory.getAspectMetadata().getPerClausePointcut(), this.declaredPointcut);
// Make it dynamic: must mutate from pre-instantiation to post-instantiation state.
// If it's not a dynamic pointcut, it may be optimized out
// by the Spring AOP infrastructure after the first evaluation.
this.pointcut = new PerTargetInstantiationModelPointcut(
this.declaredPointcut, preInstantiationPointcut, aspectInstanceFactory);
this.lazy = true;
}
else {
//切面是单例的,这里的单例是aspectj层面的
// A singleton aspect.
this.pointcut = this.declaredPointcut;
this.lazy = false;
//根据declaredPointcut实例化得到对应的advice
this.instantiatedAdvice = instantiateAdvice(this.declaredPointcut);
}
}
private Advice instantiateAdvice(AspectJExpressionPointcut pointcut) {
//内部还是靠aspectJAdvisorFactory来完成
Advice advice = this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pointcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
return (advice != null ? advice : EMPTY_ADVICE);
}
@Override
@Nullable
public Advice getAdvice(Method candidateAdviceMethod, AspectJExpressionPointcut expressionPointcut,
MetadataAwareAspectInstanceFactory aspectInstanceFactory, int declarationOrder, String aspectName) {
//拿到切面类型
Class<?> candidateAspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
validate(candidateAspectClass);
//拿到当前advicemethod上标注的增强器注解
AspectJAnnotation<?> aspectJAnnotation =
AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(candidateAdviceMethod);
//为空直接返回--说明不是一个增强器方法
if (aspectJAnnotation == null) {
return null;
}
// If we get here, we know we have an AspectJ method.
// Check that it's an AspectJ-annotated class
if (!isAspect(candidateAspectClass)) {
throw new AopConfigException("Advice must be declared inside an aspect type: " +
"Offending method '" + candidateAdviceMethod + "' in class [" +
candidateAspectClass.getName() + "]");
}
if (logger.isDebugEnabled()) {
logger.debug("Found AspectJ method: " + candidateAdviceMethod);
}
AbstractAspectJAdvice springAdvice;
//根据注解类型进行判断,构造不同的advice
switch (aspectJAnnotation.getAnnotationType()) {
//pointcut注解跳过
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
//增强方法上标注的是around注解
case AtAround:
//构造AspectJAroundAdvice返回
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//before注解
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//after注解
case AtAfter:
springAdvice = new AspectJAfterAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
//afterreturning注解
case AtAfterReturning:
springAdvice = new AspectJAfterReturningAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterReturning afterReturningAnnotation = (AfterReturning) aspectJAnnotation.getAnnotation();
//可以指定接收的返回变量名或者变量类型
if (StringUtils.hasText(afterReturningAnnotation.returning())) {
springAdvice.setReturningName(afterReturningAnnotation.returning());
}
break;
//afterreturning注解
case AtAfterThrowing:
springAdvice = new AspectJAfterThrowingAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
AfterThrowing afterThrowingAnnotation = (AfterThrowing) aspectJAnnotation.getAnnotation();
if (StringUtils.hasText(afterThrowingAnnotation.throwing())) {
//可以指定接收的异常名或异常类型
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
}
// Now to configure the advice...
//设置切面名
springAdvice.setAspectName(aspectName);
//固定为0
springAdvice.setDeclarationOrder(declarationOrder);
//获取增强方法的参数名数组
String[] argNames = this.parameterNameDiscoverer.getParameterNames(candidateAdviceMethod);
if (argNames != null) {
//设置到advice中
springAdvice.setArgumentNamesFromStringArray(argNames);
}
//计算参数绑定--感兴趣的可以研究一下--这里也可以看出joinpoint只能放在advice方法第一个参数位置
springAdvice.calculateArgumentBindings();
return springAdvice;
}
上面大部分代码流程都是在找所有可用的增强器候选集合,即findCandidateAdvisors
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;
}
下面既然已经拿到了所有可能会用到的候选增强器集合,那么下面就是判断这些增强器能否应用到当前被拦截的bean上,如果不能,说明当前bean不需要被代理
protected List<Advisor> findAdvisorsThatCanApply(
List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
ProxyCreationContext.setCurrentProxiedBeanName(beanName);
try {
//利用aoputils这个工具类来判断
return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
}
finally {
ProxyCreationContext.setCurrentProxiedBeanName(null);
}
}
public static List<Advisor> findAdvisorsThatCanApply(List<Advisor> candidateAdvisors, Class<?> clazz) {
if (candidateAdvisors.isEmpty()) {
return candidateAdvisors;
}
List<Advisor> eligibleAdvisors = new ArrayList<>();
for (Advisor candidate : candidateAdvisors) {
//优先处理IntroductionAdvisor ,然后通过canApply方法进行最终判决
if (candidate instanceof IntroductionAdvisor && canApply(candidate, clazz)) {
eligibleAdvisors.add(candidate);
}
}
boolean hasIntroductions = !eligibleAdvisors.isEmpty();
for (Advisor candidate : candidateAdvisors) {
//IntroductionAdvisor上面处理过了
if (candidate instanceof IntroductionAdvisor) {
// already processed
continue;
}
//其他类型的Advisor 进行最终判决
if (canApply(candidate, clazz, hasIntroductions)) {
eligibleAdvisors.add(candidate);
}
}
//返回最终适合作用于当前类上的增强器链集合
return eligibleAdvisors;
}
canapply方法:
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
//如果是IntroductionAdvisor,就直接进行类过滤即可
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(Pointcut pc, Class<?> targetClass, boolean hasIntroductions)重载方法
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;
}
//再进行方法过滤---如果AspectJExpressionPointcut,那么这里返回的是他自己
//因为他实现了IntroductionAwareMethodMatcher接口
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
//AspetJ会使用IntroductionAwareMethodMatcher,通过切点表达式进行过滤匹配
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
//如果当前类不是是jdk代理类了
if (!Proxy.isProxyClass(targetClass)) {
//那么再判断是否是cglib代理类,如果是拿到其superClass,即目标对象类型
classes.add(ClassUtils.getUserClass(targetClass));
}
//上面可以确保拿到的是目标对象类型,而不是代理对象的class类型
//下面再将目标对象实现的接口全部加入集合中去
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
//遍历该集合,获取每个class里面的所有方法
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
//如果introductionAwareMethodMatcher 不为空,说明Pointcut为AspectJExpressionPointcut
//挨个方法,调用introductionAwareMethodMatcher 的matches方法进行匹配
//如果introductionAwareMethodMatcher 为null,那么为普通pointCut,调用methodMatcher.matches方法进行匹配
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
@Override
public boolean matches(Method method, Class<?> targetClass, boolean hasIntroductions) {
//获取切点表达式---默认在BeanFactoryAspectJAdvisorsBuilder#buildAspectJAdvisors方法中就已经全部解析好了
obtainPointcutExpression();
//获取目标方法和切点表达式的匹配结果---这个过程比较复杂,这里就不多展开了,核心原理就是获取到切点表达式
//然后通过切点表达式判断当前放是否会被切入,结果封装在了 ShadowMatch 中
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.
//一般要么是alwaysMatches表示切入成功,要么是neverMatches表示切入失败
if (shadowMatch.alwaysMatches()) {
return true;
}
else if (shadowMatch.neverMatches()) {
return false;
}
else {
//一般很少使用: 因为当我们在切点表达式用到一些动态参数,需要运行时进行判断时,才会产生不确定性
// the maybe case
if (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));
}
}
到这里,我们已经走完了wrapIfNecessary一大半的方法,advisors增强器链已经创建出来了,下一步就是创建代理了
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(
//目标对象类型,目标对象名,增强器链,SingletonTargetSource
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
//需要代理,返回代理类,否则返回原样的bean
return bean;
}
//创建代理对象
protected Object createProxy(Class<?> beanClass, @Nullable String beanName,
@Nullable Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
//每个代理类都对应一个ProxyFactory
ProxyFactory proxyFactory = new ProxyFactory();
//这里copy的是ProxyConfig的配置,两者都继承了该类
proxyFactory.copyFrom(this);
//isProxyTargetClass为true,说明要用cglib代理
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets (for introduction advice scenarios)
//如果当前bean是jdk的代理类
if (Proxy.isProxyClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
for (Class<?> ifc : beanClass.getInterfaces()) {
//拿到jdk代理类继承的所有接口,添加进当前proxyFactory
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
//shouldProxyTargetClass返回值取决于:Boolean.TRUE.equals(bd.getAttribute(PRESERVE_TARGET_CLASS_ATTRIBUTE));
//即当前bean定义中的PRESERVE_TARGET_CLASS_ATTRIBUTE是否存在,并且对应的值是否为true,如果为true,则采用cglib进行代理
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
//进行常规判断,该方法属于父类ProxyProcessorSupport
//通过对目标对象实现的接口进行分析,判断是采用jdk还是cglib进行动态代理
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
//拦截器和targetSource设置进proxyFactory
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
//空实现,子类可以进行定制操作
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
//创建代理对象
return proxyFactory.getProxy(classLoader);
buildAdvisors方法:
/**
* Determine the advisors for the given bean, including the specific interceptors
* as well as the common interceptor, all adapted to the Advisor interface.
*/
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
//commonInterceptors是公共拦截器,即会应用到所有被该自动创建器创建的代理对象上
//这里解析的是用户设置的commonInterceptors的beanNames数组,默认为空
//resolveInterceptorNames就是拿着beanName去IOC容器中找出对应的bean,再通过适配器转换为统一的advisor后返回
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
//可以应用到当前目标对象上的拦截器链加入集合
if (specificInterceptors.length > 0) {
// specificInterceptors may equal PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
allInterceptors.addAll(Arrays.asList(specificInterceptors));
}
//公共拦截器链加入集合
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
if (logger.isTraceEnabled()) {
int nrOfCommonInterceptors = commonInterceptors.length;
int nrOfSpecificInterceptors = (specificInterceptors != null ? specificInterceptors.length : 0);
logger.trace("Creating implicit proxy for bean '" + beanName + "' with " + nrOfCommonInterceptors +
" common interceptors and " + nrOfSpecificInterceptors + " specific interceptors");
}
//进行适配操作
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
public Object getProxy(@Nullable ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
//返回的是DefaultAopProxyFactory,这里我们直接看DefaultAopProxyFactory的createAopProxy方法
return getAopProxyFactory().createAopProxy(this);
}
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
//如果proxyConfig的Optimize或者proxyTargetClass或者当前类没有实现任何接口,那么都将采用cglib完成代理
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
//但是,如果目标对象是个接口,或者目标对象是jdk代理类,那么还是使用jdk完成动态代理
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
//cglib完成动态代理
return new ObjenesisCglibAopProxy(config);
}
else {
//jdk完成动态代理
return new JdkDynamicAopProxy(config);
}
}
/**
* Determine whether the supplied {@link AdvisedSupport} has only the
* {@link org.springframework.aop.SpringProxy} interface specified
* (or no proxy interfaces specified at all).
*/
private boolean hasNoUserSuppliedProxyInterfaces(AdvisedSupport config) {
Class<?>[] ifcs = config.getProxiedInterfaces();
return (ifcs.length == 0 || (ifcs.length == 1 && SpringProxy.class.isAssignableFrom(ifcs[0])));
}
这里就不继续深入挖掘了,因为还需要对JdkDynamicAopProxy和ObjenesisCglibAopProxy区分讨论,感兴趣的可以看我之前写的文章,链接如下:
Spring读源码系列之AOP–06—AopProxy===>spring使用jdk和cglib生成代理对象的终极奥义
到此,一个代理对象被创建的完整流程就已经讲完了,这也是aop在spring中的灵魂流程
我尝试阅读有关 Spring BOM、Spring Boot 和 Spring IO 的文档。 但是没有说明,我们应该如何一起使用它们? 在我的项目中,我们已经有了自己的 Parent POM ,所以
我正在开发的很酷的企业应用程序正在转向 Spring。这对所有团队来说都是非常酷和令人兴奋的练习,但也是一个巨大的压力源。我们所做的是逐渐将遗留组件移至 Spring 上下文。现在我们有一个 huuu
我正在尝试使用 @Scheduled 运行 Spring 批处理作业注释如下: @Scheduled(cron = "* * * * * ?") public void launchMessageDi
我对这两个概念有点困惑。阅读 Spring 文档,我发现,例如。 bean 工厂是 Spring 容器。我还读到“ApplicationContext 是 BeanFactory 的完整超集”。但两者
我们有一个使用 Spring BlazeDS 集成的应用程序。到目前为止,我们一直在使用 Spring 和 Flex,它运行良好。我们现在还需要添加一些 Spring MVC Controller 。
假设我有一个类(class) Person带属性name和 age ,它可以像这样用 Spring 配置: 我想要一个自定义的 Spring 模式元素,这很容易做到,允许我在我的 Sp
如何在 Java 中以编程方式使用 Spring Data 创建 MongoDB 复合索引? 使用 MongoTemplate 我可以创建一个这样的索引:mongoTemplate.indexOps(
我想使用 spring-complex-task 执行我的应用程序,并且我已经构建了复杂的 spring-batch Flow Jobs,它执行得非常好。 你能解释一下spring批处理流作业与spr
我实现了 spring-boot 应用程序,现在我想将它用作非 spring 应用程序的库。 如何初始化 lib 类,以便 Autowiring 的依赖项按预期工作?显然,如果我使用“new”创建类实
我刚开始学习 spring cloud security,我有一个基本问题。它与 Spring Security 有何不同?我们是否需要在 spring boot 上构建我们的应用程序才能使用 spr
有很多人建议我使用 Spring Boot 而不是 Spring 来开发 REST Web 服务。我想知道这两者到底有什么区别? 最佳答案 总之 Spring Boot 减少了编写大量配置和样板代码的
您能向我解释一下如何使用 Spring 正确构建 Web 应用程序吗?我知道 Spring 框架的最新版本是 4.0.0.RELEASE,但是 Spring Security 的最新版本是 3.2.0
我如何才能知道作为 Spring Boot 应用程序的一部分加载的所有 bean 的名称?我想在 main 方法中有一些代码来打印服务器启动后加载的 bean 的详细信息。 最佳答案 如spring-
我有一个使用 Spring 3.1 构建的 RESTful API,也使用 Spring Security。我有一个 Web 应用程序,也是一个 Spring 3.1 MVC 应用程序。我计划让移动客
升级到 Spring 5 后,我在 Spring Rabbit 和 Spring AMQP 中遇到错误。 两者现在都设置为 1.5.6.RELEASE 有谁知道哪些版本应该与 Spring 5 兼容?
我现在已经使用 Spring Framework 3.0.5 和 Spring Security 3.0.5 多次了。我知道Spring框架使用DI和AOP。我还知道 Spring Security
我收到错误 Unable to Location NamespaceHandler when using context:annotation-config running (java -jar) 由
在 Spring 应用程序中嵌入唯一版本号的策略是什么? 我有一个使用 Spring Boot 和 Spring Web 的应用程序。 它已经足够成熟,我想对其进行版本控制并在运行时看到它显示在屏幕上
我正在使用 spring data jpa 进行持久化。如果存在多个具有相同名称的实体,是否有一种方法可以将一个实体标记为默认值。类似@Primary注解的东西用来解决多个bean的依赖问题 @Ent
我阅读了 Spring 框架的 DAOSupport 类。但是我无法理解这些 DAOSuport 类的优点。在 DAOSupport 类中,我们调用 getXXXTemplate() 方法来获取特定的
我是一名优秀的程序员,十分优秀!