Spring BeanPostProcessor : AnnotationAwareAspectJAutoProxyCreator

개술BeanPostProcessorAnnotationAwareAspectJAutoProxyCreator의 역할 은 다음 과 같다.
  • 현재 응용 문맥 에서 사용 하 는 모든@AspectJ주 해 를 가 져 오 는 절단면 류 의advice방법 과 모든Spring Advisorbeanadvice를 가 져 옵 니 다.
    모든advisor방법/AnnotationAwareAspectJAutoProxyCreator을 가 져 오 는 작업 은bean각각bean을 만 들 때 실 행 됩 니 다.그러나 내부 에 캐 시 체 제 를 사용 하기 때문에 실제 검색 과정 은 첫 번 째 호출 될 때 만 발생 합 니 다.
  • 각각bean을 만 들 때 이bean가 프 록 시 를 만 드 는 조건 에 부합 되 는 지 확인 하고 해당advise에 적용 할 수 있 는 모든bean을 가 져 와 현재AopUtils#findAdvisorsThatCanApply에 프 록 시 대상 을 생 성 합 니 다.
    조건 에 부합 되 는 지 의 주요 판단 논 리 는aop:include이다.
  • include를 사용 하면 이름 이 이@AspectJ조건 에 맞 는bean주해AnnotationAwareAspectJAutoProxyCreator만 절단면 을 정의 하 는 데 사용 된다.
    소스 코드 분석
    소스 코드 버 전:spring-aop-5.1.5.RELEASE
    클래스AnnotationAwareAspectJAutoProxyCreator소스 코드
    package org.springframework.aop.aspectj.annotation;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.regex.Pattern;
    
    import org.springframework.aop.Advisor;
    import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
    import org.springframework.beans.factory.ListableBeanFactory;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.lang.Nullable;
    import org.springframework.util.Assert;
    
    @SuppressWarnings("serial")
    public class AnnotationAwareAspectJAutoProxyCreator extends AspectJAwareAdvisorAutoProxyCreator {
    
    	@Nullable
    	private List<Pattern> includePatterns;
    
    	@Nullable
    	private AspectJAdvisorFactory aspectJAdvisorFactory;
    
    	@Nullable
    	private BeanFactoryAspectJAdvisorsBuilder aspectJAdvisorsBuilder;
    
    
    	/**
    	 * Set a list of regex patterns, matching eligible @AspectJ bean names.
    	 * Default is to consider all @AspectJ beans as eligible.
    	 */
    	public void setIncludePatterns(List<String> patterns) {
    		this.includePatterns = new ArrayList<>(patterns.size());
    		for (String patternText : patterns) {
    			this.includePatterns.add(Pattern.compile(patternText));
    		}
    	}
    
    	public void setAspectJAdvisorFactory(AspectJAdvisorFactory aspectJAdvisorFactory) {
    		Assert.notNull(aspectJAdvisorFactory, "AspectJAdvisorFactory must not be null");
    		this.aspectJAdvisorFactory = aspectJAdvisorFactory;
    	}
    
    	@Override
    	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    		//           beanFactory,                    
    		// Spring Advisor bean BeanFactoryAdvisorRetrievalHelper
    		super.initBeanFactory(beanFactory);
    
    		//          aspectJAdvisorsBuilder ,               
    		//     @AspectJ    beans
    		if (this.aspectJAdvisorFactory == null) {
    			this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory);
    		}
    		this.aspectJAdvisorsBuilder =
    				new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory);
    	}
    
    
    	//         Spring Advisor beans   @AspectJ     beans,    
    	// Advisor         
    	@Override
    	protected List<Advisor> findCandidateAdvisors() {
    		// Add all the Spring advisors found according to superclass rules.
    		//     Spring Advisor            Spring Advisor
    		//             BeanFactoryAdvisorRetrievalHelper 
    		//         Spring Advisor beans。
    		List<Advisor> advisors = super.findCandidateAdvisors();
    		// Build Advisors for all AspectJ aspects in the bean factory.
    		//   aspectJAdvisorsBuilder        @AspectJ    bean,    
    		//    Advisor
    		if (this.aspectJAdvisorsBuilder != null) {
    			advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());
    		}
    
    		//     advisors        Spring Advisor beans   @AspectJ     beans,
    		//        Advisor      
    		return advisors;
    	}
    
    	//                 :
    	// 1.       isInfrastructureClass            ,     ;
    	// 2.       @Aspect    ,            ;
    	//     bean          ,              	
    	@Override
    	protected boolean isInfrastructureClass(Class<?> beanClass) {
    		// Previously we setProxyTargetClass(true) in the constructor, but that has too
    		// broad an impact. Instead we now override isInfrastructureClass to avoid proxying
    		// aspects. I'm not entirely happy with that as there is no good reason not
    		// to advise aspects, except that it causes advice invocation to go through a
    		// proxy, and if the aspect implements e.g the Ordered interface it will be
    		// proxied by that interface and fail at runtime as the advice method is not
    		// defined on the interface. We could potentially relax the restriction about
    		// not advising aspects in the future.
    		return (super.isInfrastructureClass(beanClass) ||
    				(this.aspectJAdvisorFactory != null && this.aspectJAdvisorFactory.isAspect(beanClass)));
    	}
    
    	/**
    	 * Check whether the given aspect bean is eligible for auto-proxying.
    	 * If no aop:include elements were used then "includePatterns" will be
    	 * null and all beans are included. If "includePatterns" is non-null,
    	 * then one of the patterns must match.
    	 *        bean        Aspect bean。        includePatterns     ,
    	 *   includePatterns     null  ,     true。
    	 */
    	protected boolean isEligibleAspectBean(String beanName) {
    		if (this.includePatterns == null) {
    			return true;
    		}
    		else {
    			for (Pattern pattern : this.includePatterns) {
    				if (pattern.matcher(beanName).matches()) {
    					return true;
    				}
    			}
    			return false;
    		}
    	}
    
    
    	/**
    	 * Subclass of BeanFactoryAspectJAdvisorsBuilderAdapter that delegates to
    	 * surrounding AnnotationAwareAspectJAutoProxyCreator facilities.
    	 */
    	private class BeanFactoryAspectJAdvisorsBuilderAdapter extends BeanFactoryAspectJAdvisorsBuilder {
    
    		public BeanFactoryAspectJAdvisorsBuilderAdapter(
    				ListableBeanFactory beanFactory, AspectJAdvisorFactory advisorFactory) {
    
    			super(beanFactory, advisorFactory);
    		}
    
    		@Override
    		protected boolean isEligibleBean(String beanName) {
    			return AnnotationAwareAspectJAutoProxyCreator.this.isEligibleAspectBean(beanName);
    		}
    	}
    
    }
    
    

    상기@Aspect에서 알 수 있 듯 이 이것 은 주로 주해AspectJAwareAdvisorAutoProxyCreator에 대해 기본 적 인 강 화 를 했 고 자신 이 실시 하 는 기능 이 매우 적다.우 리 는 그 기본 적 인 유형AbstractAdvisorAutoProxyCreator/AbstractAutoProxyCreator/AspectJAwareAdvisorAutoProxyCreator을 계속 분석 했다.
    기본 클래스advice소스 코드
    package org.springframework.aop.aspectj.autoproxy;
    
    //    imports
    
    @SuppressWarnings("serial")
    public class AspectJAwareAdvisorAutoProxyCreator extends AbstractAdvisorAutoProxyCreator {
    
    	private static final Comparator<Advisor> DEFAULT_PRECEDENCE_COMPARATOR = new AspectJPrecedenceComparator();
    
    	/**
    	 * Sort the rest by AspectJ precedence. If two pieces of advice have
    	 * come from the same aspect they will have the same order.
    	 * Advice from the same aspect is then further ordered according to the
    	 * following rules:
    	 * 
    	 * 1. if either of the pair is after advice, then the advice declared
    	 * last gets highest precedence (runs last)
    	 * 2. otherwise the advice declared first gets highest precedence (runs first)
    	 * 
    	 * Important : Advisors are sorted in precedence order, from highest
    	 * precedence to lowest. "On the way in" to a join point, the highest precedence
    	 * advisor should run first. "On the way out" of a join point, the highest precedence
    	 * advisor should run last.
    	 */
    	@Override
    	@SuppressWarnings("unchecked")
    	protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
    		List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
    		for (Advisor element : advisors) {
    			partiallyComparableAdvisors.add(
    					new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
    		}
    		List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
    		if (sorted != null) {
    			List<Advisor> result = new ArrayList<>(advisors.size());
    			for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
    				result.add(pcAdvisor.getAdvisor());
    			}
    			return result;
    		}
    		else {
    			return super.sortAdvisors(advisors);
    		}
    	}
    
    	/**
    	 * Adds an ExposeInvocationInterceptor to the beginning of the advice chain.
    	 * These additional advices are needed when using AspectJ expression pointcuts
    	 * and when using AspectJ-style advice.
    	 *   advice chain,      candidateAdvisors       ExposeInvocationInterceptor  ,
    	 *     AspectJ pointcut       AspectJ   advice       Interceptor
    	 */
    	@Override
    	protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    		//             AspectJProxyUtils   
    		AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(candidateAdvisors);
    	}
    
    	@Override
    	protected boolean shouldSkip(Class<?> beanClass, String beanName) {
    		List<Advisor> candidateAdvisors = findCandidateAdvisors();
    		for (Advisor advisor : candidateAdvisors) {
    			if (advisor instanceof AspectJPointcutAdvisor &&
    					((AspectJPointcutAdvisor) advisor).getAspectName().equals(beanName)) {
    				return true;
    			}
    		}
    		return super.shouldSkip(beanClass, beanName);
    	}
    
    
    	/**
    	 * Implements AspectJ PartialComparable interface for defining partial orderings.
    	 */
    	private static class PartiallyComparableAdvisorHolder implements PartialComparable {
    
    		private final Advisor advisor;
    
    		private final Comparator<Advisor> comparator;
    
    		public PartiallyComparableAdvisorHolder(Advisor advisor, Comparator<Advisor> comparator) {
    			this.advisor = advisor;
    			this.comparator = comparator;
    		}
    
    		@Override
    		public int compareTo(Object obj) {
    			Advisor otherAdvisor = ((PartiallyComparableAdvisorHolder) obj).advisor;
    			return this.comparator.compare(this.advisor, otherAdvisor);
    		}
    
    		@Override
    		public int fallbackCompareTo(Object obj) {
    			return 0;
    		}
    
    		public Advisor getAdvisor() {
    			return this.advisor;
    		}
    
    		@Override
    		public String toString() {
    			StringBuilder sb = new StringBuilder();
    			Advice advice = this.advisor.getAdvice();
    			sb.append(ClassUtils.getShortName(advice.getClass()));
    			sb.append(": ");
    			if (this.advisor instanceof Ordered) {
    				sb.append("order ").append(((Ordered) this.advisor).getOrder()).append(", ");
    			}
    			if (advice instanceof AbstractAspectJAdvice) {
    				AbstractAspectJAdvice ajAdvice = (AbstractAspectJAdvice) advice;
    				sb.append(ajAdvice.getAspectName());
    				sb.append(", declaration order ");
    				sb.append(ajAdvice.getDeclarationOrder());
    			}
    			return sb.toString();
    		}
    	}
    
    }
    
    

    이 기본 클래스 는 주로ExposeInvocationInterceptor의 순 서 를 실 현 했 습 니 다.건 너 뛰 어야 하 는 지,확장 증가BeanPostProcessor의 도구 기능 을 실 현 했 습 니 다.진정한AbstractAdvisorAutoProxyCreator리 턴 기능 은 기 류 를 계속 분석 해 야 합 니 다.
    기본 클래스AbstractAdvisorAutoProxyCreator소스 코드bean는 통용 되 는 자동 프 록 시 생 성기 로 그 설계 목적 은 각각Advisor에 적용 되 는bean을 검사 하고 이에 따라 이AOPfindCandidateAdvisors()프 록 시 를 만 드 는 것 이다.이 종류의 하위 클래스 는 용기 에 있 는 모든Advisor을 찾 는 데 사용 할 수 있 습 니 다.이Advisor들 은 각각bean(진정 으로 적용 되 는 지 여 부 는 일치 조건 에 달 려 있 습 니 다.예 를 들 어 정 의 된pointcut표현 식 을 통 해 값 을 구 하 는 등 수단)에 사용 할 수 있 습 니 다.하위 클래스 도 재 작성 방법shouldSkip()으로 일부bean에 대한 대 리 를 제외 할 지 여 부 를 결정 할 수 있 습 니 다.
    package org.springframework.aop.framework.autoproxy;
    
    //    import  
    
    @SuppressWarnings("serial")
    public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator {
    
    	@Nullable
    	private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper;
    
    
    	//      setBeanFactory  
    	@Override
    	public void setBeanFactory(BeanFactory beanFactory) {
    		//        setBeanFactory  
    		super.setBeanFactory(beanFactory);
    
    		//        beanFactory    Spring bean         ConfigurableListableBeanFactory,
    		//       ,     AdvisorAutoProxyCreator        ConfigurableListableBeanFactory
    		//      
    		if (!(beanFactory instanceof ConfigurableListableBeanFactory)) {
    			throw new IllegalArgumentException(
    					"AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory);
    		}
    	
    		//      beanFactory       ,      beanFactory,      :
    		//        beanFactory BeanFactoryAdvisorRetrievalHelperAdapter   
    		// this.advisorRetrievalHelper,    beanFactory  Spring Advisor。
    		initBeanFactory((ConfigurableListableBeanFactory) beanFactory);
    	}
    
    	//     beanFactory,      :
    	//        beanFactory BeanFactoryAdvisorRetrievalHelperAdapter   
    	// this.advisorRetrievalHelper,    beanFactory  Spring Advisor。
    	protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) {
    		this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory);
    	}
    
    
    	//       bean        Advisor/Advice,     null,     bean    
    	@Override
    	@Nullable
    	protected Object[] getAdvicesAndAdvisorsForBean(
    			Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
    
    		List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
    		if (advisors.isEmpty()) {
    			// DO_NOT_PROXY        null    ,    :
    			//           Advisor,     bean    
    			return DO_NOT_PROXY;
    		}
    		return advisors.toArray();
    	}
    
    	/**
    	 * Find all eligible Advisors for auto-proxying this class.
    	 * @param beanClass the clazz to find advisors for
    	 * @param beanName the name of the currently proxied bean
    	 * @return the empty List, not null,
    	 * if there are no pointcuts or interceptors
    	 * @see #findCandidateAdvisors
    	 * @see #sortAdvisors
    	 * @see #extendAdvisors
    	 */
    	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
    		//    findCandidateAdvisors()          Advisor : 
    		//         findCandidateAdvisors()     :         Spring Advisors
    		//      AnnotationAwareAspectJAutoProxyCreator     :
    		//        Spring Advisors +        AspectJ       advice   Advisors
    		List<Advisor> candidateAdvisors = findCandidateAdvisors();
    
    		//        Advisor,       bean      
    		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
    		//         advisor list   ,      ,          extendAdvisors()     
    		//     extendAdvisors():      ,      
    		// AnnotationAwareAspectJAutoProxyCreator#extendAdvisors():    ExposeInvocationInterceptor
    		extendAdvisors(eligibleAdvisors);
    		
    		if (!eligibleAdvisors.isEmpty()) {
    			//     advisor   ,        sortAdvisors(),            
    			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
    		}
    		return eligibleAdvisors;
    	}
    
    	/**
    	 * Find all candidate Advisors to use in auto-proxying.
    	 *      advisorRetrievalHelper        Spring Advisor beans      ,
    	 *              。
    	 * @return the List of candidate Advisors
    	 */
    	protected List<Advisor> findCandidateAdvisors() {
    		Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available");
    		return this.advisorRetrievalHelper.findAdvisorBeans();
    	}
    
    	/**
    	 * Search the given candidate Advisors to find all Advisors that
    	 * can apply to the specified bean.
    	 * @param candidateAdvisors the candidate Advisors
    	 * @param beanClass the target's bean class
    	 * @param beanName the target's bean name
    	 * @return the List of applicable Advisors
    	 * @see ProxyCreationContext#getCurrentProxiedBeanName()
    	 */
    	protected List<Advisor> findAdvisorsThatCanApply(
    			List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) {
    
    		// ProxyCreationContext       ThreadLocal                bean,
    		//         ,   pointcut           ProxyCreationContext,
    		//     ,  bean                ,     
    		ProxyCreationContext.setCurrentProxiedBeanName(beanName);
    		try {
    			//       advisor        bean      AopUtils  ,        ,			
    			return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass);
    		}
    		finally {
    			//     advisor bean     ,  ProxyCreationContext
    			ProxyCreationContext.setCurrentProxiedBeanName(null);
    		}
    	}
    
    	/**
    	 * Return whether the Advisor bean with the given name is eligible
    	 * for proxying in the first place.
    	 *     bean       ,       ,    true,           
    	 *        
    	 * @param beanName the name of the Advisor bean
    	 * @return whether the bean is eligible
    	 */
    	protected boolean isEligibleAdvisorBean(String beanName) {
    		return true;
    	}
    
    	/**
    	 * Sort advisors based on ordering. Subclasses may choose to override this
    	 * method to customize the sorting strategy.
    	 * @param advisors the source List of Advisors
    	 * @return the sorted List of Advisors
    	 * @see org.springframework.core.Ordered
    	 * @see org.springframework.core.annotation.Order
    	 * @see org.springframework.core.annotation.AnnotationAwareOrderComparator
    	 */
    	protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
    		AnnotationAwareOrderComparator.sort(advisors);
    		return advisors;
    	}
    
    	/**
    	 * Extension hook that subclasses can override to register additional Advisors,
    	 * given the sorted Advisors obtained to date.
    	 * The default implementation is empty.
    	 * Typically used to add Advisors that expose contextual information
    	 * required by some of the later advisors.
    	 *          candidateAdvisors   ,      ,      
    	 * @param candidateAdvisors the Advisors that have already been identified as
    	 * applying to a given bean
    	 */
    	protected void extendAdvisors(List<Advisor> candidateAdvisors) {
    	}
    
    	/**
    	 * This auto-proxy creator always returns pre-filtered Advisors.
    	 */
    	@Override
    	protected boolean advisorsPreFiltered() {
    		return true;
    	}
    
    
    	/**
    	 * Subclass of BeanFactoryAdvisorRetrievalHelper that delegates to
    	 * surrounding AbstractAdvisorAutoProxyCreator facilities.
    	 *       BeanFactoryAdvisorRetrievalHelper,            Spring Advisor
    	 */
    	private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper {
    
    		public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) {
    			super(beanFactory);
    		}
    
    		@Override
    		protected boolean isEligibleBean(String beanName) {
    			return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName);
    		}
    	}
    
    }
    
    

    기본 클래스AbstractAutoProxyCreator소스 코드
    package org.springframework.aop.framework.autoproxy;
    
    //    imports
    
    @SuppressWarnings("serial")
    public abstract class AbstractAutoProxyCreator extends ProxyProcessorSupport
    		implements SmartInstantiationAwareBeanPostProcessor, BeanFactoryAware {
    
    	/**
    	 * Convenience constant for subclasses: Return value for "do not proxy".
    	 * @see #getAdvicesAndAdvisorsForBean
    	 */
    	@Nullable
    	protected static final Object[] DO_NOT_PROXY = null;
    
    	/**
    	 * Convenience constant for subclasses: Return value for
    	 * "proxy without additional interceptors, just the common ones".
    	 * @see #getAdvicesAndAdvisorsForBean
    	 */
    	protected static final Object[] PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS = new Object[0];
    
    
    	/** Logger available to subclasses. */
    	protected final Log logger = LogFactory.getLog(getClass());
    
    	/** Default is global AdvisorAdapterRegistry. */
    	private AdvisorAdapterRegistry advisorAdapterRegistry = GlobalAdvisorAdapterRegistry.getInstance();
    
    	/**
    	 * Indicates whether or not the proxy should be frozen. Overridden from super
    	 * to prevent the configuration from becoming frozen too early.
    	 */
    	private boolean freezeProxy = false;
    
    	/** Default is no common interceptors. */
    	private String[] interceptorNames = new String[0];
    
    	private boolean applyCommonInterceptorsFirst = true;
    
    	@Nullable
    	private TargetSourceCreator[] customTargetSourceCreators;
    
    	@Nullable
    	private BeanFactory beanFactory;
    
    	private final Set<String> targetSourcedBeans = Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    
    	private final Set<Object> earlyProxyReferences = 
    		Collections.newSetFromMap(new ConcurrentHashMap<>(16));
    
    	private final Map<Object, Class<?>> proxyTypes = new ConcurrentHashMap<>(16);
    
    	private final Map<Object, Boolean> advisedBeans = new ConcurrentHashMap<>(256);
    
    
    	/**
    	 * Set whether or not the proxy should be frozen, preventing advice
    	 * from being added to it once it is created.
    	 * 

    Overridden from the super class to prevent the proxy configuration * from being frozen before the proxy is created. */

    @Override public void setFrozen(boolean frozen) { this.freezeProxy = frozen; } @Override public boolean isFrozen() { return this.freezeProxy; } /** * Specify the AdvisorAdapterRegistry to use. *

    Default is the global AdvisorAdapterRegistry. * @see org.springframework.aop.framework.adapter.GlobalAdvisorAdapterRegistry */

    public void setAdvisorAdapterRegistry(AdvisorAdapterRegistry advisorAdapterRegistry) { this.advisorAdapterRegistry = advisorAdapterRegistry; } /** * Set custom TargetSourceCreators to be applied in this order. * If the list is empty, or they all return null, a SingletonTargetSource * will be created for each bean. * Note that TargetSourceCreators will kick in even for target beans * where no advices or advisors have been found. If a TargetSourceCreator * returns a TargetSource for a specific bean, that bean will be proxied * in any case. * TargetSourceCreators can only be invoked if this post processor is used * in a BeanFactory and its BeanFactoryAware callback is triggered. * @param targetSourceCreators the list of TargetSourceCreators. * Ordering is significant: The TargetSource returned from the first matching * TargetSourceCreator (that is, the first that returns non-null) will be used. */ public void setCustomTargetSourceCreators(TargetSourceCreator... targetSourceCreators) { this.customTargetSourceCreators = targetSourceCreators; } /** * Set the common interceptors. These must be bean names in the current factory. * They can be of any advice or advisor type Spring supports. *

    If this property isn't set, there will be zero common interceptors. * This is perfectly valid, if "specific" interceptors such as matching * Advisors are all we want. */

    public void setInterceptorNames(String... interceptorNames) { this.interceptorNames = interceptorNames; } /** * Set whether the common interceptors should be applied before bean-specific ones. * Default is "true"; else, bean-specific interceptors will get applied first. */ public void setApplyCommonInterceptorsFirst(boolean applyCommonInterceptorsFirst) { this.applyCommonInterceptorsFirst = applyCommonInterceptorsFirst; } @Override public void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } /** * Return the owning BeanFactory. * May be null, as this post-processor doesn't need to belong to a bean factory. */ @Nullable protected BeanFactory getBeanFactory() { return this.beanFactory; } @Override @Nullable public Class<?> predictBeanType(Class<?> beanClass, String beanName) { if (this.proxyTypes.isEmpty()) { return null; } Object cacheKey = getCacheKey(beanClass, beanName); return this.proxyTypes.get(cacheKey); } @Override @Nullable public Constructor<?>[] determineCandidateConstructors(Class<?> beanClass, String beanName) { return null; } @Override public Object getEarlyBeanReference(Object bean, String beanName) { // bean class bean Cache Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { this.earlyProxyReferences.add(cacheKey); } return wrapIfNecessary(bean, beanName, cacheKey); } // InstantiationAwareBeanPostProcessor (BeanPostProcessor ) , // bean , bean , bean , // TargetSource, TargetSource advice/advisor bean @Override public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) { // bean class bean Cache Object cacheKey = getCacheKey(beanClass, beanName); if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) { if (this.advisedBeans.containsKey(cacheKey)) { // InstantiationAwareBeanPostProcessor , return null; } if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) { // bean bean , // bean bean, , FALSE this.advisedBeans.put(cacheKey, Boolean.FALSE); return null; } } // Create proxy here if we have a custom TargetSource. // Suppresses unnecessary default instantiation of the target bean: // The TargetSource will handle target instances in a custom fashion. TargetSource targetSource = getCustomTargetSource(beanClass, beanName); if (targetSource != null) { if (StringUtils.hasLength(beanName)) { this.targetSourcedBeans.add(beanName); } // bean TargetSource, , Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource); Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource); this.proxyTypes.put(cacheKey, proxy.getClass()); // null proxy return proxy; } // null , bean , return null; } @Override public boolean postProcessAfterInstantiation(Object bean, String beanName) { return true; } @Override public PropertyValues postProcessProperties(PropertyValues pvs, Object bean, String beanName) { return pvs; } @Override public Object postProcessBeforeInitialization(Object bean, String beanName) { return bean; } /** * Create a proxy with the configured interceptors if the bean is * identified as one to proxy by the subclass. * @see #getAdvicesAndAdvisorsForBean */ @Override public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) { if (bean != null) { Object cacheKey = getCacheKey(bean.getClass(), beanName); if (!this.earlyProxyReferences.contains(cacheKey)) { return wrapIfNecessary(bean, beanName, cacheKey); } } return bean; } /** * Build a cache key for the given bean class and bean name. * Note: As of 4.2.3, this implementation does not return a concatenated * class/name String anymore but rather the most efficient cache key possible: * a plain bean name, prepended with BeanFactory#FACTORY_BEAN_PREFIX * in case of a FactoryBean or if no bean name specified, then the * given bean Class as-is. * bean class bean Cache * @param beanClass the bean class * @param beanName the bean name * @return the cache key for the given class and name */ protected Object getCacheKey(Class<?> beanClass, @Nullable String beanName) { if (StringUtils.hasLength(beanName)) { return (FactoryBean.class.isAssignableFrom(beanClass) ? BeanFactory.FACTORY_BEAN_PREFIX + beanName : beanName); } else { return beanClass; } } /** * Wrap the given bean if necessary, i.e. if it is eligible for being proxied. * @param bean the raw bean instance * @param beanName the name of the bean * @param cacheKey the cache key for metadata access * @return a proxy wrapping the bean, or the raw bean instance as-is */ protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { // bean , : #postProcessBeforeInstantiation return bean; } if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { // bean , : #postProcessBeforeInstantiation 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 advice, Advisor , Advisor // advice , Interceptor Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); if (specificInterceptors != DO_NOT_PROXY) { // bean advice, , this.advisedBeans.put(cacheKey, Boolean.TRUE); // bean proxy Object proxy = createProxy( bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); this.proxyTypes.put(cacheKey, proxy.getClass()); return proxy; } // bean advice, this.advisedBeans.put(cacheKey, Boolean.FALSE); return bean; } /** * Return whether the given bean class represents an infrastructure class * that should never be proxied. * The default implementation considers Advices, Advisors and * AopInfrastructureBeans as infrastructure classes. * @param beanClass the class of the bean * @return whether the bean represents an infrastructure class * @see org.aopalliance.aop.Advice * @see org.springframework.aop.Advisor * @see org.springframework.aop.framework.AopInfrastructureBean * @see #shouldSkip */ protected boolean isInfrastructureClass(Class<?> beanClass) { boolean retVal = Advice.class.isAssignableFrom(beanClass) || Pointcut.class.isAssignableFrom(beanClass) || Advisor.class.isAssignableFrom(beanClass) || AopInfrastructureBean.class.isAssignableFrom(beanClass); if (retVal && logger.isTraceEnabled()) { logger.trace("Did not attempt to auto-proxy infrastructure class [" + beanClass.getName() + "]"); } return retVal; } /** * Subclasses should override this method to return true if the * given bean should not be considered for auto-proxying by this post-processor. * Sometimes we need to be able to avoid this happening, e.g. if it will lead to * a circular reference or if the existing target instance needs to be preserved. * This implementation returns false unless the bean name indicates an * "original instance" according to AutowireCapableBeanFactory conventions. * @param beanClass the class of the bean * @param beanName the name of the bean * @return whether to skip the given bean * @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#ORIGINAL_INSTANCE_SUFFIX */ protected boolean shouldSkip(Class<?> beanClass, String beanName) { return AutoProxyUtils.isOriginalInstance(beanName, beanClass); } /** * Create a target source for bean instances. Uses any TargetSourceCreators if set. * Returns null if no custom TargetSource should be used. * This implementation uses the "customTargetSourceCreators" property. * Subclasses can override this method to use a different mechanism. * @param beanClass the class of the bean to create a TargetSource for * @param beanName the name of the bean * @return a TargetSource for this bean * @see #setCustomTargetSourceCreators */ @Nullable protected TargetSource getCustomTargetSource(Class<?> beanClass, String beanName) { // We can't create fancy target sources for directly registered singletons. if (this.customTargetSourceCreators != null && this.beanFactory != null && this.beanFactory.containsBean(beanName)) { for (TargetSourceCreator tsc : this.customTargetSourceCreators) { TargetSource ts = tsc.getTargetSource(beanClass, beanName); if (ts != null) { // Found a matching TargetSource. if (logger.isTraceEnabled()) { logger.trace("TargetSourceCreator [" + tsc + "] found custom TargetSource for bean with name '" + beanName + "'"); } return ts; } } } // No custom TargetSource found. return null; } /** * Create an AOP proxy for the given bean. * @param beanClass the class of the bean * @param beanName the name of the bean * @param specificInterceptors the set of interceptors that is * specific to this bean (may be empty, but not null) * @param targetSource the TargetSource for the proxy, already pre-configured to access the bean * @return the AOP proxy for the bean * @see #buildAdvisors */ 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); } // AOP ProxyFactory proxyFactory = new ProxyFactory(); // ProxyConfig proxyFactory.copyFrom(this); if (!proxyFactory.isProxyTargetClass()) { if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } // bean Advisor : // 1. // 2. bean : specificInterceptors Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); proxyFactory.addAdvisors(advisors); proxyFactory.setTargetSource(targetSource); customizeProxyFactory(proxyFactory); // this.freezeProxy false proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } return proxyFactory.getProxy(getProxyClassLoader()); } /** * Determine whether the given bean should be proxied with its target class rather than its interfaces. * Checks the AutoProxyUtils#PRESERVE_TARGET_CLASS_ATTRIBUTE "preserveTargetClass" attribute * of the corresponding bean definition. * @param beanClass the class of the bean * @param beanName the name of the bean * @return whether the given bean should be proxied with its target class * @see AutoProxyUtils#shouldProxyTargetClass */ protected boolean shouldProxyTargetClass(Class<?> beanClass, @Nullable String beanName) { return (this.beanFactory instanceof ConfigurableListableBeanFactory && AutoProxyUtils.shouldProxyTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName)); } /** * Return whether the Advisors returned by the subclass are pre-filtered * to match the bean's target class already, allowing the ClassFilter check * to be skipped when building advisors chains for AOP invocations. * Default is false. Subclasses may override this if they * will always return pre-filtered Advisors. * @return whether the Advisors are pre-filtered * @see #getAdvicesAndAdvisorsForBean * @see org.springframework.aop.framework.Advised#setPreFiltered */ protected boolean advisorsPreFiltered() { return false; } /** * Determine the advisors for the given bean, including the specific interceptors * as well as the common interceptor, all adapted to the Advisor interface. * @param beanName the name of the bean * @param specificInterceptors the set of interceptors that is * specific to this bean (may be empty, but not null) * @return the list of Advisors for the given bean */ protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) { // Handle prototypes correctly... // #setInterceptorNames() Advisors commonInterceptors Advisor[] commonInterceptors = resolveInterceptorNames(); // commonInterceptors specificInterceptors ( bean ) List<Object> allInterceptors = new ArrayList<>(); if (specificInterceptors != null) { 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; } /** * Resolves the specified interceptor names to Advisor objects. * @see #setInterceptorNames */ private Advisor[] resolveInterceptorNames() { BeanFactory bf = this.beanFactory; ConfigurableBeanFactory cbf = (bf instanceof ConfigurableBeanFactory ? (ConfigurableBeanFactory) bf : null); List<Advisor> advisors = new ArrayList<>(); for (String beanName : this.interceptorNames) { if (cbf == null || !cbf.isCurrentlyInCreation(beanName)) { Assert.state(bf != null, "BeanFactory required for resolving interceptor names"); Object next = bf.getBean(beanName); advisors.add(this.advisorAdapterRegistry.wrap(next)); } } return advisors.toArray(new Advisor[0]); } /** * Subclasses may choose to implement this: for example, * to change the interfaces exposed. * The default implementation is empty. * @param proxyFactory a ProxyFactory that is already configured with * TargetSource and interfaces and will be used to create the proxy * immediately after this method returns */ protected void customizeProxyFactory(ProxyFactory proxyFactory) { } /** * Return whether the given bean is to be proxied, what additional * advices (e.g. AOP Alliance interceptors) and advisors to apply. * * bean advice, Advisor , Advisor * advice , Interceptor 。 。 * * @param beanClass the class of the bean to advise * @param beanName the name of the bean * @param customTargetSource the TargetSource returned by the * #getCustomTargetSource method: may be ignored. * Will be null if no custom target source is in use. * @return an array of additional interceptors for the particular bean; * or an empty array if no additional interceptors but just the common ones; * or null if no proxy at all, not even with the common interceptors. * See constants DO_NOT_PROXY and PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS. * @throws BeansException in case of errors * @see #DO_NOT_PROXY * @see #PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS */ @Nullable protected abstract Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, @Nullable TargetSource customTargetSource) throws BeansException; }

    총결산
    상기 코드 를 통 해 알 수 있 듯 이AnnotationAwareAspectJAutoProxyCreator설정 한 임무 에 대한 완성 은 이런 자체 가 아니 라 각 차원 의 기본 클래스,특히 기본 클래스AbstractAutoProxyCreator에 분산 되 어 이 루어 진 것 이다.종합 적 으로 보면AnnotationAwareAspectJAutoProxyCreator다음 과 같은 인터페이스 정의 방법 을 실현 했다.
  • SmartInstantiationAwareBeanPostProcessor–방법 을 정의 했다getEarlyBeanReference
  • InstantiationAwareBeanPostProcessor–방법 을 정의 했다postProcessBeforeInstantiation
  • BeanPostProcessor–방법 을 정의 했다postProcessAfterInitialization
  • 위의 인터페이스 에서 정 의 된 방법 은Spring에 규정된 리 셋 시기 에bean에 따라 실행 되 고AnnotationAwareAspectJAutoProxyCreator또는 그 기본 클래스 는 이러한 방법 에 실현 된다.이러한 방법 이 실현 하 는 주요 논 리 는 하나의 목적 을 대상 으로 한다.만약 에 이bean가 용기 중의 일부advise와 일치 하면 이bean에 해당 하 는 대리 대상 을 만 들 고 이 대리 대상 은 한 그룹advice이 원시 적 인bean대상 을 감 싸 고 있 는 것 으로 이해 할 수 있다.프 록 시 대상 을 만 드 는 주요 논 리 는 기본 클래스AbstractAutoProxyCreator에서 다음 과 같은 두 가지 방법 입 니 다.
  • Object wrapIfNecessary(Object bean, String beanName, Object cacheKey)
    주요 논리:프 록 시 를 만 들 필요 가 있 지만 프 록 시 를 만 들 지 않 으 면 적용 되 는advices,호출createProxy프 록 시 를 만 듭 니 다.
  • Object createProxy(Class> beanClass, String beanName,Object[] specificInterceptors, TargetSource targetSource)
    주요 논리:구축ProxyFactory대상 을 설정ProxyConfig프 록 시 설정 매개 변 수 를 설정 한 다음 이ProxyFactory대상 에서 프 록 시 대상 을 만 듭 니 다.
  • 좋은 웹페이지 즐겨찾기