001/* 002 * Copyright 2002-2020 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.aop.framework.autoproxy; 018 019import java.util.List; 020 021import org.springframework.aop.Advisor; 022import org.springframework.aop.TargetSource; 023import org.springframework.aop.support.AopUtils; 024import org.springframework.beans.factory.BeanFactory; 025import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 026import org.springframework.core.annotation.AnnotationAwareOrderComparator; 027import org.springframework.lang.Nullable; 028import org.springframework.util.Assert; 029 030/** 031 * Generic auto proxy creator that builds AOP proxies for specific beans 032 * based on detected Advisors for each bean. 033 * 034 * <p>Subclasses may override the {@link #findCandidateAdvisors()} method to 035 * return a custom list of Advisors applying to any object. Subclasses can 036 * also override the inherited {@link #shouldSkip} method to exclude certain 037 * objects from auto-proxying. 038 * 039 * <p>Advisors or advices requiring ordering should be annotated with 040 * {@link org.springframework.core.annotation.Order @Order} or implement the 041 * {@link org.springframework.core.Ordered} interface. This class sorts 042 * advisors using the {@link AnnotationAwareOrderComparator}. Advisors that are 043 * not annotated with {@code @Order} or don't implement the {@code Ordered} 044 * interface will be considered as unordered; they will appear at the end of the 045 * advisor chain in an undefined order. 046 * 047 * @author Rod Johnson 048 * @author Juergen Hoeller 049 * @see #findCandidateAdvisors 050 */ 051@SuppressWarnings("serial") 052public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator { 053 054 @Nullable 055 private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper; 056 057 058 @Override 059 public void setBeanFactory(BeanFactory beanFactory) { 060 super.setBeanFactory(beanFactory); 061 if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { 062 throw new IllegalArgumentException( 063 "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory); 064 } 065 initBeanFactory((ConfigurableListableBeanFactory) beanFactory); 066 } 067 068 protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { 069 this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory); 070 } 071 072 073 @Override 074 @Nullable 075 protected Object[] getAdvicesAndAdvisorsForBean( 076 Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) { 077 078 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); 079 if (advisors.isEmpty()) { 080 return DO_NOT_PROXY; 081 } 082 return advisors.toArray(); 083 } 084 085 /** 086 * Find all eligible Advisors for auto-proxying this class. 087 * @param beanClass the clazz to find advisors for 088 * @param beanName the name of the currently proxied bean 089 * @return the empty List, not {@code null}, 090 * if there are no pointcuts or interceptors 091 * @see #findCandidateAdvisors 092 * @see #sortAdvisors 093 * @see #extendAdvisors 094 */ 095 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { 096 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 097 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); 098 extendAdvisors(eligibleAdvisors); 099 if (!eligibleAdvisors.isEmpty()) { 100 eligibleAdvisors = sortAdvisors(eligibleAdvisors); 101 } 102 return eligibleAdvisors; 103 } 104 105 /** 106 * Find all candidate Advisors to use in auto-proxying. 107 * @return the List of candidate Advisors 108 */ 109 protected List<Advisor> findCandidateAdvisors() { 110 Assert.state(this.advisorRetrievalHelper != null, "No BeanFactoryAdvisorRetrievalHelper available"); 111 return this.advisorRetrievalHelper.findAdvisorBeans(); 112 } 113 114 /** 115 * Search the given candidate Advisors to find all Advisors that 116 * can apply to the specified bean. 117 * @param candidateAdvisors the candidate Advisors 118 * @param beanClass the target's bean class 119 * @param beanName the target's bean name 120 * @return the List of applicable Advisors 121 * @see ProxyCreationContext#getCurrentProxiedBeanName() 122 */ 123 protected List<Advisor> findAdvisorsThatCanApply( 124 List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { 125 126 ProxyCreationContext.setCurrentProxiedBeanName(beanName); 127 try { 128 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); 129 } 130 finally { 131 ProxyCreationContext.setCurrentProxiedBeanName(null); 132 } 133 } 134 135 /** 136 * Return whether the Advisor bean with the given name is eligible 137 * for proxying in the first place. 138 * @param beanName the name of the Advisor bean 139 * @return whether the bean is eligible 140 */ 141 protected boolean isEligibleAdvisorBean(String beanName) { 142 return true; 143 } 144 145 /** 146 * Sort advisors based on ordering. Subclasses may choose to override this 147 * method to customize the sorting strategy. 148 * @param advisors the source List of Advisors 149 * @return the sorted List of Advisors 150 * @see org.springframework.core.Ordered 151 * @see org.springframework.core.annotation.Order 152 * @see org.springframework.core.annotation.AnnotationAwareOrderComparator 153 */ 154 protected List<Advisor> sortAdvisors(List<Advisor> advisors) { 155 AnnotationAwareOrderComparator.sort(advisors); 156 return advisors; 157 } 158 159 /** 160 * Extension hook that subclasses can override to register additional Advisors, 161 * given the sorted Advisors obtained to date. 162 * <p>The default implementation is empty. 163 * <p>Typically used to add Advisors that expose contextual information 164 * required by some of the later advisors. 165 * @param candidateAdvisors the Advisors that have already been identified as 166 * applying to a given bean 167 */ 168 protected void extendAdvisors(List<Advisor> candidateAdvisors) { 169 } 170 171 /** 172 * This auto-proxy creator always returns pre-filtered Advisors. 173 */ 174 @Override 175 protected boolean advisorsPreFiltered() { 176 return true; 177 } 178 179 180 /** 181 * Subclass of BeanFactoryAdvisorRetrievalHelper that delegates to 182 * surrounding AbstractAdvisorAutoProxyCreator facilities. 183 */ 184 private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper { 185 186 public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) { 187 super(beanFactory); 188 } 189 190 @Override 191 protected boolean isEligibleBean(String beanName) { 192 return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName); 193 } 194 } 195 196}