001/* 002 * Copyright 2002-2019 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; 027 028/** 029 * Generic auto proxy creator that builds AOP proxies for specific beans 030 * based on detected Advisors for each bean. 031 * 032 * <p>Subclasses may override the {@link #findCandidateAdvisors()} method to 033 * return a custom list of Advisors applying to any object. Subclasses can 034 * also override the inherited {@link #shouldSkip} method to exclude certain 035 * objects from auto-proxying. 036 * 037 * <p>Advisors or advices requiring ordering should implement the 038 * {@link org.springframework.core.Ordered} interface. This class sorts 039 * Advisors by Ordered order value. Advisors that don't implement the 040 * Ordered interface will be considered as unordered; they will appear 041 * at the end of the advisor chain in undefined order. 042 * 043 * @author Rod Johnson 044 * @author Juergen Hoeller 045 * @see #findCandidateAdvisors 046 */ 047@SuppressWarnings("serial") 048public abstract class AbstractAdvisorAutoProxyCreator extends AbstractAutoProxyCreator { 049 050 private BeanFactoryAdvisorRetrievalHelper advisorRetrievalHelper; 051 052 053 @Override 054 public void setBeanFactory(BeanFactory beanFactory) { 055 super.setBeanFactory(beanFactory); 056 if (!(beanFactory instanceof ConfigurableListableBeanFactory)) { 057 throw new IllegalArgumentException( 058 "AdvisorAutoProxyCreator requires a ConfigurableListableBeanFactory: " + beanFactory); 059 } 060 initBeanFactory((ConfigurableListableBeanFactory) beanFactory); 061 } 062 063 protected void initBeanFactory(ConfigurableListableBeanFactory beanFactory) { 064 this.advisorRetrievalHelper = new BeanFactoryAdvisorRetrievalHelperAdapter(beanFactory); 065 } 066 067 068 @Override 069 protected Object[] getAdvicesAndAdvisorsForBean(Class<?> beanClass, String beanName, TargetSource targetSource) { 070 List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName); 071 if (advisors.isEmpty()) { 072 return DO_NOT_PROXY; 073 } 074 return advisors.toArray(); 075 } 076 077 /** 078 * Find all eligible Advisors for auto-proxying this class. 079 * @param beanClass the clazz to find advisors for 080 * @param beanName the name of the currently proxied bean 081 * @return the empty List, not {@code null}, 082 * if there are no pointcuts or interceptors 083 * @see #findCandidateAdvisors 084 * @see #sortAdvisors 085 * @see #extendAdvisors 086 */ 087 protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) { 088 List<Advisor> candidateAdvisors = findCandidateAdvisors(); 089 List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName); 090 extendAdvisors(eligibleAdvisors); 091 if (!eligibleAdvisors.isEmpty()) { 092 eligibleAdvisors = sortAdvisors(eligibleAdvisors); 093 } 094 return eligibleAdvisors; 095 } 096 097 /** 098 * Find all candidate Advisors to use in auto-proxying. 099 * @return the List of candidate Advisors 100 */ 101 protected List<Advisor> findCandidateAdvisors() { 102 return this.advisorRetrievalHelper.findAdvisorBeans(); 103 } 104 105 /** 106 * Search the given candidate Advisors to find all Advisors that 107 * can apply to the specified bean. 108 * @param candidateAdvisors the candidate Advisors 109 * @param beanClass the target's bean class 110 * @param beanName the target's bean name 111 * @return the List of applicable Advisors 112 * @see ProxyCreationContext#getCurrentProxiedBeanName() 113 */ 114 protected List<Advisor> findAdvisorsThatCanApply( 115 List<Advisor> candidateAdvisors, Class<?> beanClass, String beanName) { 116 117 ProxyCreationContext.setCurrentProxiedBeanName(beanName); 118 try { 119 return AopUtils.findAdvisorsThatCanApply(candidateAdvisors, beanClass); 120 } 121 finally { 122 ProxyCreationContext.setCurrentProxiedBeanName(null); 123 } 124 } 125 126 /** 127 * Return whether the Advisor bean with the given name is eligible 128 * for proxying in the first place. 129 * @param beanName the name of the Advisor bean 130 * @return whether the bean is eligible 131 */ 132 protected boolean isEligibleAdvisorBean(String beanName) { 133 return true; 134 } 135 136 /** 137 * Sort advisors based on ordering. Subclasses may choose to override this 138 * method to customize the sorting strategy. 139 * @param advisors the source List of Advisors 140 * @return the sorted List of Advisors 141 * @see org.springframework.core.Ordered 142 * @see org.springframework.core.annotation.Order 143 * @see org.springframework.core.annotation.AnnotationAwareOrderComparator 144 */ 145 protected List<Advisor> sortAdvisors(List<Advisor> advisors) { 146 AnnotationAwareOrderComparator.sort(advisors); 147 return advisors; 148 } 149 150 /** 151 * Extension hook that subclasses can override to register additional Advisors, 152 * given the sorted Advisors obtained to date. 153 * <p>The default implementation is empty. 154 * <p>Typically used to add Advisors that expose contextual information 155 * required by some of the later advisors. 156 * @param candidateAdvisors the Advisors that have already been identified as 157 * applying to a given bean 158 */ 159 protected void extendAdvisors(List<Advisor> candidateAdvisors) { 160 } 161 162 /** 163 * This auto-proxy creator always returns pre-filtered Advisors. 164 */ 165 @Override 166 protected boolean advisorsPreFiltered() { 167 return true; 168 } 169 170 171 /** 172 * Subclass of BeanFactoryAdvisorRetrievalHelper that delegates to 173 * surrounding AbstractAdvisorAutoProxyCreator facilities. 174 */ 175 private class BeanFactoryAdvisorRetrievalHelperAdapter extends BeanFactoryAdvisorRetrievalHelper { 176 177 public BeanFactoryAdvisorRetrievalHelperAdapter(ConfigurableListableBeanFactory beanFactory) { 178 super(beanFactory); 179 } 180 181 @Override 182 protected boolean isEligibleBean(String beanName) { 183 return AbstractAdvisorAutoProxyCreator.this.isEligibleAdvisorBean(beanName); 184 } 185 } 186 187}