001/* 002 * Copyright 2002-2018 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.config; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.springframework.aop.aspectj.annotation.AnnotationAwareAspectJAutoProxyCreator; 023import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator; 024import org.springframework.aop.framework.autoproxy.InfrastructureAdvisorAutoProxyCreator; 025import org.springframework.beans.factory.config.BeanDefinition; 026import org.springframework.beans.factory.support.BeanDefinitionRegistry; 027import org.springframework.beans.factory.support.RootBeanDefinition; 028import org.springframework.core.Ordered; 029import org.springframework.lang.Nullable; 030import org.springframework.util.Assert; 031 032/** 033 * Utility class for handling registration of AOP auto-proxy creators. 034 * 035 * <p>Only a single auto-proxy creator should be registered yet multiple concrete 036 * implementations are available. This class provides a simple escalation protocol, 037 * allowing a caller to request a particular auto-proxy creator and know that creator, 038 * <i>or a more capable variant thereof</i>, will be registered as a post-processor. 039 * 040 * @author Rob Harrop 041 * @author Juergen Hoeller 042 * @author Mark Fisher 043 * @since 2.5 044 * @see AopNamespaceUtils 045 */ 046public abstract class AopConfigUtils { 047 048 /** 049 * The bean name of the internally managed auto-proxy creator. 050 */ 051 public static final String AUTO_PROXY_CREATOR_BEAN_NAME = 052 "org.springframework.aop.config.internalAutoProxyCreator"; 053 054 /** 055 * Stores the auto proxy creator classes in escalation order. 056 */ 057 private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3); 058 059 static { 060 // Set up the escalation list... 061 APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class); 062 APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); 063 APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); 064 } 065 066 067 @Nullable 068 public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { 069 return registerAutoProxyCreatorIfNecessary(registry, null); 070 } 071 072 @Nullable 073 public static BeanDefinition registerAutoProxyCreatorIfNecessary( 074 BeanDefinitionRegistry registry, @Nullable Object source) { 075 076 return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source); 077 } 078 079 @Nullable 080 public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { 081 return registerAspectJAutoProxyCreatorIfNecessary(registry, null); 082 } 083 084 @Nullable 085 public static BeanDefinition registerAspectJAutoProxyCreatorIfNecessary( 086 BeanDefinitionRegistry registry, @Nullable Object source) { 087 088 return registerOrEscalateApcAsRequired(AspectJAwareAdvisorAutoProxyCreator.class, registry, source); 089 } 090 091 @Nullable 092 public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) { 093 return registerAspectJAnnotationAutoProxyCreatorIfNecessary(registry, null); 094 } 095 096 @Nullable 097 public static BeanDefinition registerAspectJAnnotationAutoProxyCreatorIfNecessary( 098 BeanDefinitionRegistry registry, @Nullable Object source) { 099 100 return registerOrEscalateApcAsRequired(AnnotationAwareAspectJAutoProxyCreator.class, registry, source); 101 } 102 103 public static void forceAutoProxyCreatorToUseClassProxying(BeanDefinitionRegistry registry) { 104 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { 105 BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); 106 definition.getPropertyValues().add("proxyTargetClass", Boolean.TRUE); 107 } 108 } 109 110 public static void forceAutoProxyCreatorToExposeProxy(BeanDefinitionRegistry registry) { 111 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { 112 BeanDefinition definition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); 113 definition.getPropertyValues().add("exposeProxy", Boolean.TRUE); 114 } 115 } 116 117 @Nullable 118 private static BeanDefinition registerOrEscalateApcAsRequired( 119 Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) { 120 121 Assert.notNull(registry, "BeanDefinitionRegistry must not be null"); 122 123 if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) { 124 BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME); 125 if (!cls.getName().equals(apcDefinition.getBeanClassName())) { 126 int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName()); 127 int requiredPriority = findPriorityForClass(cls); 128 if (currentPriority < requiredPriority) { 129 apcDefinition.setBeanClassName(cls.getName()); 130 } 131 } 132 return null; 133 } 134 135 RootBeanDefinition beanDefinition = new RootBeanDefinition(cls); 136 beanDefinition.setSource(source); 137 beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE); 138 beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE); 139 registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition); 140 return beanDefinition; 141 } 142 143 private static int findPriorityForClass(Class<?> clazz) { 144 return APC_PRIORITY_LIST.indexOf(clazz); 145 } 146 147 private static int findPriorityForClass(@Nullable String className) { 148 for (int i = 0; i < APC_PRIORITY_LIST.size(); i++) { 149 Class<?> clazz = APC_PRIORITY_LIST.get(i); 150 if (clazz.getName().equals(className)) { 151 return i; 152 } 153 } 154 throw new IllegalArgumentException( 155 "Class name [" + className + "] is not a known auto-proxy creator class"); 156 } 157 158}