/*
 * Copyright 2002-2017 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

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;

AspectJAwareAdvisorAutoProxyCreator subclass that processes all AspectJ annotation aspects in the current application context, as well as Spring Advisors.

Any AspectJ annotated classes will automatically be recognized, and their advice applied if Spring AOP's proxy-based model is capable of applying it. This covers method execution joinpoints.

If the <aop:include> element is used, only @AspectJ beans with names matched by an include pattern will be considered as defining aspects to use for Spring auto-proxying.

Processing of Spring Advisors follows the rules established in AbstractAdvisorAutoProxyCreator.

Author:Rod Johnson, Juergen Hoeller
See Also:
Since:2.0
/** * {@link AspectJAwareAdvisorAutoProxyCreator} subclass that processes all AspectJ * annotation aspects in the current application context, as well as Spring Advisors. * * <p>Any AspectJ annotated classes will automatically be recognized, and their * advice applied if Spring AOP's proxy-based model is capable of applying it. * This covers method execution joinpoints. * * <p>If the &lt;aop:include&gt; element is used, only @AspectJ beans with names matched by * an include pattern will be considered as defining aspects to use for Spring auto-proxying. * * <p>Processing of Spring Advisors follows the rules established in * {@link org.springframework.aop.framework.autoproxy.AbstractAdvisorAutoProxyCreator}. * * @author Rod Johnson * @author Juergen Hoeller * @since 2.0 * @see org.springframework.aop.aspectj.annotation.AspectJAdvisorFactory */
@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.

/** * Set a list of regex patterns, matching eligible @AspectJ bean names. * <p>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) { super.initBeanFactory(beanFactory); if (this.aspectJAdvisorFactory == null) { this.aspectJAdvisorFactory = new ReflectiveAspectJAdvisorFactory(beanFactory); } this.aspectJAdvisorsBuilder = new BeanFactoryAspectJAdvisorsBuilderAdapter(beanFactory, this.aspectJAdvisorFactory); } @Override protected List<Advisor> findCandidateAdvisors() { // Add all the Spring advisors found according to superclass rules. List<Advisor> advisors = super.findCandidateAdvisors(); // Build Advisors for all AspectJ aspects in the bean factory. if (this.aspectJAdvisorsBuilder != null) { advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors()); } return advisors; } @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.

/** * Check whether the given aspect bean is eligible for auto-proxying. * <p>If no &lt;aop:include&gt; elements were used then "includePatterns" will be * {@code null} and all beans are included. If "includePatterns" is non-null, * then one of the patterns must match. */
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.
/** * 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); } } }