Spring BeanPostProcessor : AnnotationAwareAspectJAutoProxyCreator
BeanPostProcessor
AnnotationAwareAspectJAutoProxyCreator
의 역할 은 다음 과 같다.@AspectJ
주 해 를 가 져 오 는 절단면 류 의advice
방법 과 모든Spring Advisor
bean
advice
를 가 져 옵 니 다.모든
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
을 검사 하고 이에 따라 이AOP
에findCandidateAdvisors()
프 록 시 를 만 드 는 것 이다.이 종류의 하위 클래스 는 용기 에 있 는 모든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
대상 에서 프 록 시 대상 을 만 듭 니 다.이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
thymeleaf로 HTML 페이지를 동적으로 만듭니다 (spring + gradle)지난번에는 에서 화면에 HTML을 표시했습니다. 이번에는 화면을 동적으로 움직여보고 싶기 때문에 입력한 문자를 화면에 표시시키고 싶습니다. 초보자의 비망록이므로 이상한 점 등 있으면 지적 받을 수 있으면 기쁩니다! ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.