为什么需要自动代理生成器
在 spring 中,提供了 org.springframework.aop.framework.ProxyFactoryBean 来实现对目标 bean 的增强,但此工具类存在以下缺点:
- 目标 bean 被增强后,获取实例对象时,使用的是配置的代理 bean 的 id,而非配置的目标 bean 的 id。
- 配置繁琐,不利于规模使用,一个代理对象只能代理一个 bean,如果有多个 bean 需要代理增强时,需要配置多个代理对象。
基于此,在 spring 中提供了自动代理生成器,来解决 ProxyFactoryBean 存在的问题,常用的自动代理生成器有两个:
- org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator
- org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator
通过类关系可以知道,这两个类都是 AbstractAutoProxyCreator 子类,AbstractAutoProxyCreator 实现了 BeanPostProcessor,前面的文章介绍过 spring 中 BeanPostProcessor 的调用时机,在创建实例对象时,调用实现了 BeanPostProcessor 接口中的方法,完成对目标 bean 的增强,这样,使用时直接使用目标 bean 的 id 即可。
下面来看看这两个自动代理生成器具体是怎么实现的,先来看看他们共同的父类 AbstractAutoProxyCreator。
AbstractAutoProxyCreator
在 AbstractAutoProxyCreator 中,实现了 BeanPostProcessor 中的接口方法。
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);
if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
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);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
return null;
}
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
Object cacheKey = getCacheKey(bean.getClass(), beanName);
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// Create proxy if we have advice.
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
在实例化之前,对一些不需要增强的类进行标记,这样在初始化时,当执行到 wrapIfNecessary ,对不需要增强的类就直接返回了。在方法 wrapIfNecessary 中,调用了一个抽象方法,AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean,留作子类来实现,根据名称可知,对获取 Advice 和 Advisor 的不同,就是这两个自动代理生成器实现的主要不同。
DefaultAdvisorAutoProxyCreator
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
List<Advisor> advisors = findEligibleAdvisors(beanClass, beanName);
if (advisors.isEmpty()) {
return DO_NOT_PROXY;
}
return advisors.toArray();
}
对于 DefaultAdvisorAutoProxyCreator,其实现方法位于父类 AbstractAdvisorAutoProxyCreator,继承 AbstractAutoProxyCreator。
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
List<Advisor> candidateAdvisors = findCandidateAdvisors();
List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
extendAdvisors(eligibleAdvisors);
if (!eligibleAdvisors.isEmpty()) {
eligibleAdvisors = sortAdvisors(eligibleAdvisors);
}
return eligibleAdvisors;
}
找到合适的 Advisor,其实现逻辑如下:
- 找到所有的 Advisor 候选者
- 对 Advisor 候选者进行过滤
- 扩展 Advisor,针对 DefaultAdvisorAutoProxyCreator,并未扩展
- 排序,默认采用 AnnotationAwareOrderComparator 比较器实现排序
下面来详细介绍:
public List<Advisor> findAdvisorBeans() {
// 先看下是否已缓存
String[] advisorNames = this.cachedAdvisorBeanNames;
if (advisorNames == null) {
advisorNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
this.beanFactory, Advisor.class, true, false);
this.cachedAdvisorBeanNames = advisorNames;
}
if (advisorNames.length == 0) {
return new ArrayList<>();
}
List<Advisor> advisors = new ArrayList<>();
for (String name : advisorNames) {
if (isEligibleBean(name)) {
if (this.beanFactory.isCurrentlyInCreation(name)) {
...
}
else {
try {
advisors.add(this.beanFactory.getBean(name, Advisor.class));
}
catch (BeanCreationException ex) {
...
}
}
}
}
return advisors;
}
借助工具类 BeanFactoryAdvisorRetrievalHelper,此时会遍历系统中注册的所有 beanName, 根据 beanName 得到 RootBeanDefinition,包含配置 bean 的所有信息,解析出 bean 对应的 Class,判断是要匹配的 Advisor 类型,将 beanName 加入 advisorNames,最后将 advisorNames 赋值给 cachedAdvisorBeanNames 缓存起来。接着遍历 advisorNames,对未创建的 advisor 调用 beanFactory.getBean 进行创建。
public static boolean canApply(Advisor advisor, Class<?> targetClass, boolean hasIntroductions) {
if (advisor instanceof IntroductionAdvisor) {
return ((IntroductionAdvisor) advisor).getClassFilter().matches(targetClass);
}
else if (advisor instanceof PointcutAdvisor) {
PointcutAdvisor pca = (PointcutAdvisor) advisor;
return canApply(pca.getPointcut(), targetClass, hasIntroductions);
}
else {
return true;
}
}
// AopUtils
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
}
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
// No need to iterate the methods if we're matching any method anyway...
return true;
}
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher) methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
对 Advisor 候选者进行过滤。我们知道增强是针对某个类中的某个方法进行增强,所以只有目标类和类中的方法都能匹配到给定的过滤规则,才算是一个合格的 Advisor。类的匹配通过 ClassFilter 完成,方法的匹配通过 MethodMatcher 来完成,这两个类都是接口,实际使用时,既可以使用 spring 中已经实现的实现类,也可以自定义实现来进行扩展,满足自己的匹配需求。spring 中常用的方法匹配器有以下几个:
- NameMatchMethodPointcut:NameMatchMethodPointcutAdvisor 使用,对应属性 mappedName 和 mappedNames,支持通配符匹配。
- JdkRegexpMethodPointcut:RegexpMethodPointcutAdvisor 使用,通过配置的正则表达式进行匹配,对应属性 pattern 和 patterns。
BeanNameAutoProxyCreator
BeanNameAutoProxyCreator 会通过属性 beanNames 来设置要匹配的 bean 名称。在调用 BeanNameAutoProxyCreator#getAdvicesAndAdvisorsForBean 来获取指定拦截器时,会遍历配置的 beanNames,来判断是否和正在创建的 bean 名称相匹配,符合条件返回 true,支持名称通配符匹配,*xxx、xxx*、*xxx*。
@Override
@Nullable
protected Object[] getAdvicesAndAdvisorsForBean(
Class<?> beanClass, String beanName, @Nullable TargetSource targetSource) {
return (isSupportedBeanName(beanClass, beanName) ?
PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS : DO_NOT_PROXY);
}
private boolean isSupportedBeanName(Class<?> beanClass, String beanName) {
if (this.beanNames != null) {
boolean isFactoryBean = FactoryBean.class.isAssignableFrom(beanClass);
for (String mappedName : this.beanNames) {
if (isFactoryBean) {
if (!mappedName.startsWith(BeanFactory.FACTORY_BEAN_PREFIX)) {
continue;
}
mappedName = mappedName.substring(BeanFactory.FACTORY_BEAN_PREFIX.length());
}
if (isMatch(beanName, mappedName)) {
return true;
}
}
BeanFactory beanFactory = getBeanFactory();
String[] aliases = (beanFactory != null ? beanFactory.getAliases(beanName) : NO_ALIASES);
for (String alias : aliases) {
for (String mappedName : this.beanNames) {
if (isMatch(alias, mappedName)) {
return true;
}
}
}
}
return false;
}
这样,匹配的话会返回 PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS,其实是一个 Object[0],返回赋值给 specificInterceptors。可以看到此时并不像 DefaultAdvisorAutoProxyCreator 那样,已经获取到了匹配的 Advisor,那么具体的 Advisor 到底是在什么时候获取的呢?
代理的创建
在 AbstractAutoProxyCreator#wrapIfNecessary 中,调用完 getAdvicesAndAdvisorsForBean 返回 specificInterceptors 之后,对 specificInterceptors 进行判断,不为 DO_NOT_PROXY,进行代理的创建。
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);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (proxyFactory.isProxyTargetClass()) {
// Explicit handling of JDK proxy targets and lambdas (for introduction advice scenarios)
if (Proxy.isProxyClass(beanClass) || ClassUtils.isLambdaClass(beanClass)) {
// Must allow for introductions; can't just set interfaces to the proxy's interfaces only.
for (Class<?> ifc : beanClass.getInterfaces()) {
proxyFactory.addInterface(ifc);
}
}
}
else {
// No proxyTargetClass flag enforced, let's apply our default checks...
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
proxyFactory.addAdvisors(advisors);
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
// Use original ClassLoader if bean class not locally loaded in overriding class loader
ClassLoader classLoader = getProxyClassLoader();
if (classLoader instanceof SmartClassLoader && classLoader != beanClass.getClassLoader()) {
classLoader = ((SmartClassLoader) classLoader).getOriginalClassLoader();
}
return proxyFactory.getProxy(classLoader);
}
在这段代码中,核心思想就是封装一个 ProxyFactory,设置完相关属性后,利用 ProxyFactory 创建代理。
有一点需注意,advisorsPreFiltered 方法。继承 AbstractAdvisorAutoProxyCreator 的子类,由于在获取 Advisor 时在方法 AbstractAdvisorAutoProxyCreator#findEligibleAdvisor 中调用了 AbstractAdvisorAutoProxyCreator#findAdvisorsThatCanApply,即对获取的 candidateAdvisors进行了过滤,所以在 AbstractAdvisorAutoProxyCreator 中对 advisorsPreFiltered 方法进行了重写。
@Override
protected boolean advisorsPreFiltered() {
return true;
}
即采用 AbstractAdvisorAutoProxyCreator 子类的自动代理生成器,创建代理时 AdvisedSupport 中 preFiltered 恒为 true。这一点后面方法调用创建拦截器链时会用到。
下面我们主要看下其中的 buildAdvisors 方法。
protected Advisor[] buildAdvisors(@Nullable String beanName, @Nullable Object[] specificInterceptors) {
// Handle prototypes correctly...
Advisor[] commonInterceptors = resolveInterceptorNames();
List<Object> allInterceptors = new ArrayList<>();
if (specificInterceptors != null) {
if (specificInterceptors.length > 0) {
// specificInterceptors may equal PROXY_WITHOUT_ADDITIONAL_INTERCEPTORS
allInterceptors.addAll(Arrays.asList(specificInterceptors));
}
if (commonInterceptors.length > 0) {
if (this.applyCommonInterceptorsFirst) {
allInterceptors.addAll(0, Arrays.asList(commonInterceptors));
}
else {
allInterceptors.addAll(Arrays.asList(commonInterceptors));
}
}
}
Advisor[] advisors = new Advisor[allInterceptors.size()];
for (int i = 0; i < allInterceptors.size(); i++) {
// 适配器适配
advisors[i] = this.advisorAdapterRegistry.wrap(allInterceptors.get(i));
}
return advisors;
}
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]);
}
这个方法位于 AbstractAutoProxyCreator,遍历配置的 interceptorNames,利用 bf.getBean 根据 beanName 获取对象,接着利用 advisorAdapterRegistry 适配为 Advisor,加入 advisors,最后转换为数组,赋值给 commonInterceptors。接着会将 specificInterceptors 和 commonInterceptors 合并,默认将 commonInterceptors 放在 specificInterceptors 之前。
由此也可以看出,两个自动代理生成器获取 Advisor 的不同:
- DefaultAdvisorAutoProxyCreator:主要是通过调用 getAdvicesAndAdvisorsForBean 方法来获取,如果获取不到,返回 DO_NOT_PROXY,就不会创建代理,只有获取到 Advisor,才会创建代理,此时如果也配置的 interceptorNames 属性,在创建代理调用 buildAdvisors 时会将配置的 interceptorNames 解析为 commonInterceptors,作为 specificInterceptors 的补充。
- BeanNameAutoProxyCreator:调用 getAdvicesAndAdvisorForBean 方法时,只会拿当前 beanName 和配置的 interceptorNames 匹配,并不会创建实际的 Advisor,只有在 beanName 符合,创建代理调用 buildAdvisors 时,才会根据配置的 interceptorsNames 创建具体的 Advisor。
至此,就完成了创建代理前的所有准备工作,接着创建代理,此处只有一处需要注意,就是:对于不存在接口的目标类,默认采用 ObjenesisCglibAopProxy 生成代理;对于存在接口的目标类,默认采用 JdkDynamicAopProxy 生成代理。如果对存在接口的目标类也想使用 ObjenesisCglibAopProxy,可在配置自动代理生成器时配置属性,optimize、proxyTargetClass,两个属性配置一个即可。
// DefaultAopProxyFactory
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass) || ClassUtils.isLambdaClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
下面来看看这两种生成代理的方式具体是如何创建代理的。
ObjenesisCglibAopProxy
这个类继承 CglibAopProxy,是对 CglibAopProxy 创建代理的一种扩展,采用 CglibAopProxy 创建代理类,然后采用 Objenesis 实现实例化。Objenesis 的原理,前面的文章已经介绍过了,Objenesis 底层探究。
下面来看看 CglibAopProxy 创建代理的过程。
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
...
try {
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (rootClass.getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
// Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass, classLoader);
// Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareGeneratorStrategy(classLoader));
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// fixedInterceptorMap only populated at this point, after getCallbacks call above
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance.
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException | IllegalArgumentException ex) {
...
}
catch (Throwable ex) {
...
}
}
@Override
protected Object createProxyClassAndInstance(Enhancer enhancer, Callback[] callbacks) {
// cglib 创建代理类
Class<?> proxyClass = enhancer.createClass();
Object proxyInstance = null;
if (objenesis.isWorthTrying()) {
try {
// Objenesis 针对这个代理类进行实例化
proxyInstance = objenesis.newInstance(proxyClass, enhancer.getUseCache());
}
catch (Throwable ex) {
...
}
}
if (proxyInstance == null) {
// Regular instantiation via default constructor...
try {
Constructor<?> ctor = (this.constructorArgs != null ?
proxyClass.getDeclaredConstructor(this.constructorArgTypes) :
proxyClass.getDeclaredConstructor());
ReflectionUtils.makeAccessible(ctor);
proxyInstance = (this.constructorArgs != null ?
ctor.newInstance(this.constructorArgs) : ctor.newInstance());
}
catch (Throwable ex) {
...
}
}
((Factory) proxyInstance).setCallbacks(callbacks);
return proxyInstance;
}
代码很好理解,封装 enhancer,调用方法,有一点注意,getCallbacks。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimization choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
// SingletonTargetSource 中 isStatic 恒为 true
boolean isStatic = this.advised.getTargetSource().isStatic();
// Choose an "aop" interceptor (used for AOP calls).
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are
// unadvised but can return this). May be required to expose the proxy.
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = (isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource()));
}
else {
targetInterceptor = (isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource()));
}
// Choose a "direct to target" dispatcher (used for
// unadvised calls to static targets that cannot return this).
Callback targetDispatcher = (isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp());
Callback[] mainCallbacks = new Callback[] {
aopInterceptor, // for normal advice
targetInterceptor, // invoke target without considering advice, if optimized
new SerializableNoOp(), // no override for methods mapped to this
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen,
// then we can make some optimizations by sending the AOP calls
// direct to the target using the fixed chain for that method.
// TargetSource isStatic 返回 true 且自动代理生成器设置了 frozen 属性
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = CollectionUtils.newHashMap(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice)
for (int x = 0; x < methods.length; x++) {
Method method = methods[x];
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(method, x);
}
// Now copy both the callbacks from mainCallbacks
// and fixedCallbacks into the callbacks array.
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
// 复制 mainCallbacks 到 callbacks
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
// 复制 fixedCallbacks 到 callbacks
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
此处主要关注 CglibAopProxy.DynamicAdvisedInterceptor 这个内部类,作为 aopIntercprtor,会在后续方法调用时使用到。
JdkDynamicAopProxy
此种方式相对于 CglibAopProxy,能简单一点。
@Override
public Object getProxy(@Nullable ClassLoader classLoader) {
...
// JdkDynamicAopProxy 也实现了 InvocationHnadler 接口
return Proxy.newProxyInstance(classLoader, this.proxiedInterfaces, this);
}
这样代理对象的创建也就完成了,接着就到了对方法的调用。
方法调用,拦截器链的创建
获取到返回的代理对象后,对方法的调用便由代理对象发起,不同的代理方式生成的代理对象,发起方法调用时也有不同。
ObjenesisCglibAopProxy
对于 Cglib 这种方式,我们知道,这是底层操作 ASM 重新创建了一个类,我们称之为 newClass,在这个 newClass 中,对需要拦截增强的方法,通过 org.springframework.cglib.proxy.MethodInterceptor#interceptor 发起调用。
// 这是某个 newClass 中的增强方法
public final void doSome() {
MethodInterceptor var10000 = this.CGLIB$CALLBACK_0;
if (var10000 == null) {
CGLIB$BIND_CALLBACKS(this);
var10000 = this.CGLIB$CALLBACK_0;
}
if (var10000 != null) {
var10000.intercept(this, CGLIB$doSome$1$Method, CGLIB$emptyArgs, CGLIB$doSome$1$Proxy);
} else {
super.doSome();
}
}
对于 Aop,此处的 var10000 就是前面创建的 aopInterceptor,即 CglibAopProxy.DynamicAdvisedInterceptor。
@Override
@Nullable
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Object target = null;
TargetSource targetSource = this.advised.getTargetSource();
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target, in case it comes from a pool...
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && CglibMethodInvocation.isMethodProxyCompatible(method)) {
// We can skip creating a MethodInvocation: just invoke the target directly.
// Note that the final invoker must be an InvokerInterceptor, so we know
// it does nothing but a reflective operation on the target, and no hot
// swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = invokeMethod(target, method, argsToUse, methodProxy);
}
else {
// We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
核心思想就是调用 getInterceptorsAndDynamicInterceptionAdvice 获取针对 targetClass 中 method 方法的拦截器链,然后封装 CglibMethodInvocation 发起调用。
// AdvisedSupport
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable Class<?> targetClass) {
// method 和 method.hashCode() 创建缓存,提高效率
MethodCacheKey cacheKey = new MethodCacheKey(method);
List<Object> cached = this.methodCache.get(cacheKey);
if (cached == null) {
cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
this, method, targetClass);
this.methodCache.put(cacheKey, cached);
}
return cached;
}
// DefaultAdvisorChainFactory
@Override
public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
Advised config, Method method, @Nullable Class<?> targetClass) {
// This is somewhat tricky... We have to process introductions first,
// but we need to preserve order in the ultimate list.
AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
// 获取 advisors
Advisor[] advisors = config.getAdvisors();
List<Object> interceptorList = new ArrayList<>(advisors.length);
Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass());
Boolean hasIntroductions = null;
for (Advisor advisor : advisors) {
if (advisor instanceof PointcutAdvisor) {
// Add it conditionally.
PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) {
MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
boolean match;
if (mm instanceof IntroductionAwareMethodMatcher) {
if (hasIntroductions == null) {
hasIntroductions = hasMatchingIntroductions(advisors, actualClass);
}
match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions);
}
else {
match = mm.matches(method, actualClass);
}
if (match) {
MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
if (mm.isRuntime()) {
// Creating a new object instance in the getInterceptors() method
// isn't a problem as we normally cache created chains.
for (MethodInterceptor interceptor : interceptors) {
interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
}
}
else {
interceptorList.addAll(Arrays.asList(interceptors));
}
}
}
}
else if (advisor instanceof IntroductionAdvisor) {
IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
else {
Interceptor[] interceptors = registry.getInterceptors(advisor);
interceptorList.addAll(Arrays.asList(interceptors));
}
}
return interceptorList;
}
核心思想就是,将创建代理时 ProxyFactory 中设置的 advisors 转换成 org.aopalliance.intercept.MethodInterceptor,封装 interceptorList。
可以看到,在创建拦截器链时,对 advisor 进行了过滤。
当自动代理生成器是 AbstractAdvisorAutoProxyCreator 的子类时,config.isPreFiltered() 恒为 true,所以为 Advisor 配置的 ClassFilter 在此处不会生效,只会进行下面的 MethodMatcher 匹配。
当自动代理生成器是 BeanNameAutoProxyCreator 时,此时 config.isPreFiltered() 为 false,为 Advisor 配置的 ClassFilter 匹配会生效。
封装 interceptorList 时会通过适配器将 Advisor 适配成 MethodInterceptor。
// DefaultAdvisorAdapterRegistry
@Override
public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
List<MethodInterceptor> interceptors = new ArrayList<>(3);
Advice advice = advisor.getAdvice();
if (advice instanceof MethodInterceptor) {
interceptors.add((MethodInterceptor) advice);
}
for (AdvisorAdapter adapter : this.adapters) {
if (adapter.supportsAdvice(advice)) {
interceptors.add(adapter.getInterceptor(advisor));
}
}
if (interceptors.isEmpty()) {
throw new UnknownAdviceTypeException(advisor.getAdvice());
}
return interceptors.toArray(new MethodInterceptor[0]);
}
我们知道,在 spring 中,定义了四种通知类型:
- 前置通知 MethodBeforeAdvice
- 后置通知 AfterReturningAdvice
- 环绕通知 org.aopalliance.intercept.MethodInterceptor
- 异常通知 ThrowsAdvice
实际使用时,实现对应的接口即可。 此处获取拦截器时,可以看到,先从 Advisor 中获取 Advice,如果是 org.aopalliance.intercept.MethodInterceptor 类型,直接加入 interceptors 集合,如果不是,遍历 adapters 适配器集合,逐个适配。在 DefaultAdvisorAdapterRegistry 中,添加了三个适配器,分别对应前置通知、后置通知、异常通知。
public DefaultAdvisorAdapterRegistry() {
registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
registerAdvisorAdapter(new AfterReturningAdviceAdapter());
registerAdvisorAdapter(new ThrowsAdviceAdapter());
}
以 MethodBeforeAdviceAdapter 为例,看下具体是如何适配的。
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {
@Override
public boolean supportsAdvice(Advice advice) {
return (advice instanceof MethodBeforeAdvice);
}
@Override
public MethodInterceptor getInterceptor(Advisor advisor) {
MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
return new MethodBeforeAdviceInterceptor(advice);
}
}
可以看到整个类很简单,就两个方法,一个用来判断是否是支持的 Advice 类型,另一个用于返回相应的拦截器,这个拦截器持有这个支持的 Advice。
这样,就完成了从 Advisor 到 org.aopalliance.intercept.MethodInterceptor 的转换。
得到拦截器链 chain 后,封装 CglibMethodInvocation,发起方法调用,调用很简单,委托给父类 ReflectiveMethodInvocation 执行。
// CglibMethodInvocation
@Override
@Nullable
public Object proceed() throws Throwable {
try {
return super.proceed();
}
catch (RuntimeException ex) {
throw ex;
}
catch (Exception ex) {
...
}
}
// ReflectiveMethodInvocation
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// currentInterceptorIndex 初始值 -1
// interceptorsAndDynamicMethodMatchers 封装的拦截器链,是一个 list 集合
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
ReflectiveMethodInvocation,这是一个 CglibAopProxy 和 JdkDynamicAopProxy 共用的类,也是spring Aop 中方法调用的核心。
每次一进入方法,拿 currentInterceptorIndex 与 拦截器链 chain 的最大索引做比较,相等时,表示已经执行完了最后一个拦截器,此时会发起 invokeJoinPoint,调用连接点,其实就是调用目标方法。不相等时,获取当前拦截器,由于 currentInterceptorIndex 从 -1 开始,每次先进行自增,这样下一次进入时就表示已经执行了第 currentInterceptorIndex 对应的拦截器,然后根据索引获取当前拦截器,调用 invoke 方法。
以前置顾问为例,来看下拦截器的执行,通过前面的适配器可知,前置顾问被适配成了 MethodBeforeAdviceInterceptor。
@Override
@Nullable
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
通过调用自实现的顾问方法,完成方法的增强,接着 mi.proceed() 继续向前执行,此时又会执行到 CglibMethodInvocation,接着父类 ReflectiveMethodInvocation,进行下一轮判断。当执行了最后一个拦截器后,再次进入 ReflectiveMethodInvocation#proceed 方法进行判断后,会调用连接点方法。
@Override
protected Object invokeJoinpoint() throws Throwable {
if (this.methodProxy != null) {
try {
return this.methodProxy.invoke(this.target, this.arguments);
}
catch (CodeGenerationException ex) {
logFastClassGenerationFailure(this.method);
}
}
return super.invokeJoinpoint();
}
CglibMethodInvocation 重写了 invokeJoinPoint 方法,methodProxy 由发起拦截调用 org.springframework.cglib.proxy.MethodInterceptor#intercept 时通过参数传入,最后通过原始对象调用目标方法。
关于 MethodProxy 的创建及生成原理,参考 cglib 代理的生成过程。
接着沿着拦截器链相反的方向,一步步退出返回。类似于入栈出栈。连接点方法就位于栈的最底端。
下面来看看 JdkDynamicAopProxy 中方法调用时是怎么操作的。
JdkDynamicAopProxy
JdkDynamicAopProxy 实现了java.lang.reflect.InvocationHandler 接口,方法调用时直接进入 invoke 方法执行。
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// The target does not implement the hashCode() method itself.
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// Get as late as possible to minimize the time we "own" the target,
// in case it comes from a pool.
target = targetSource.getTarget();
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// Check whether we have any advice. If we don't, we can fall back on direct
// reflective invocation of the target, and avoid creating a MethodInvocation.
if (chain.isEmpty()) {
// We can skip creating a MethodInvocation: just invoke the target directly
// Note that the final invoker must be an InvokerInterceptor so we know it does
// nothing but a reflective operation on the target, and no hot swapping or fancy proxying.
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// We need to create a method invocation...
MethodInvocation invocation =
new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// Proceed to the joinpoint through the interceptor chain.
retVal = invocation.proceed();
}
// Massage return value if necessary.
Class<?> returnType = method.getReturnType();
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
// Special case: it returned "this" and the return type of the method
// is type-compatible. Note that we can't help if the target sets
// a reference to itself in another returned object.
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
// Must have come from TargetSource.
targetSource.releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
核心逻辑,获取 method 对应的拦截器链,封装 MethodInvocation,发起调用。
其中获取拦截器链的操作与 CglibAopProxy 一致,spring 将这一功能的实现委托给了 AdvisorChainFactory,AdvisedSupport 中的 advisorChainFactory 属性默认赋值 DefaultAdvisorChainFactory 实例对象。符合 java 设计模式中的单一职责模式。
封装 MethodInvocation,此处为 ReflectiveMethodInvocation,接着调用 ReflectiveMethodInvocation#proceed,过程与 CglibMethodInvocation 一致,不同点就在于 invokeJoinpoint 方法。
// ReflectiveMethodInvocation
@Nullable
protected Object invokeJoinpoint() throws Throwable {
return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments);
}
// AopUtils
@Nullable
public static Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args)
throws Throwable {
// Use reflection to invoke the method.
try {
ReflectionUtils.makeAccessible(method);
return method.invoke(target, args);
}
catch (InvocationTargetException ex) {
...
}
catch (IllegalArgumentException ex) {
...
catch (IllegalAccessException ex) {
...
}
}
即通过反射调用目标方法。
总结
通过前面的介绍,我们明白了 spring 中对自动代理生成器的实现。从 AbstractAutoProxyCreator#postProcessAfterInitialization 开始,对需要代理的 bean 创建代理。此处采用了模板方法设计模式,AbstractAutoProxyCreator#wrapIfNecessary 定义了代理的基本逻辑,调用了留作子类扩展实现的抽象方法 AbstractAutoProxyCreator#getAdvicesAndAdvisorsForBean,而对这个抽象方法的实现,就是各个代理生成器的最大区别。
获取到 Advisor 后,开始创建代理,根据有无接口,及代理生成器中配置的 optimize/proxyTargetClass 属性来决定采用哪种方式的代理。
代理创建完成,利用返回的代理对象发起方法调用,针对目标方法,获取拦截器链,封装 MethodInvocation,执行 proceed 方法,这些逻辑实现基本一致,此处最大的不同就在于对连接点方法的调用。cglib 为减少反射开销,生成了一个父类为 FastClass 的工具类,通过原始目标 bean 对象调用目标方法,而 Jdk 动态代理则采用反射的方式。