All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.aop.aspectj.annotation.AspectJProxyFactory Maven / Gradle / Ivy

There is a newer version: 5.3.34
Show newest version
/*
 * Copyright 2002-2007 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
 *
 *      http://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.HashMap;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.reflect.PerClauseKind;

import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJProxyUtils;
import org.springframework.aop.framework.AopConfigException;
import org.springframework.aop.framework.ProxyCreatorSupport;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;

/**
 * AspectJ-based proxy factory, allowing for programmatic building
 * of proxies which include AspectJ aspects (code style as well
 * Java 5 annotation style).
 *
 * @author Rob Harrop
 * @author Juergen Hoeller
 * @since 2.0
 * @see #addAspect(Object)
 * @see #addAspect(Class)
 * @see #getProxy()
 * @see #getProxy(ClassLoader)
 * @see org.springframework.aop.framework.ProxyFactory
 */
public class AspectJProxyFactory extends ProxyCreatorSupport {

	/** Cache for singleton aspect instances */
	private static final Map aspectCache = new HashMap();

	private final AspectJAdvisorFactory aspectFactory = new ReflectiveAspectJAdvisorFactory();


	/**
	 * Create a new AspectJProxyFactory.
	 */
	public AspectJProxyFactory() {
	}

	/**
	 * Create a new AspectJProxyFactory.
	 * 

Will proxy all interfaces that the given target implements. * @param target the target object to be proxied */ public AspectJProxyFactory(Object target) { Assert.notNull(target, "Target object must not be null"); setInterfaces(ClassUtils.getAllInterfaces(target)); setTarget(target); } /** * Create a new AspectJProxyFactory. * No target, only interfaces. Must add interceptors. */ public AspectJProxyFactory(Class[] interfaces) { setInterfaces(interfaces); } /** * Add the supplied aspect instance to the chain. The type of the aspect instance * supplied must be a singleton aspect. True singleton lifecycle is not honoured when * using this method - the caller is responsible for managing the lifecycle of any * aspects added in this way. * @param aspectInstance the AspectJ aspect instance */ public void addAspect(Object aspectInstance) { Class aspectClass = aspectInstance.getClass(); String aspectName = aspectClass.getName(); AspectMetadata am = createAspectMetadata(aspectClass, aspectName); if (am.getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON) { throw new IllegalArgumentException( "Aspect class [" + aspectClass.getName() + "] does not define a singleton aspect"); } addAdvisorsFromAspectInstanceFactory( new SingletonMetadataAwareAspectInstanceFactory(aspectInstance, aspectName)); } /** * Add an aspect of the supplied type to the end of the advice chain. * @param aspectClass the AspectJ aspect class */ public void addAspect(Class aspectClass) { String aspectName = aspectClass.getName(); AspectMetadata am = createAspectMetadata(aspectClass, aspectName); MetadataAwareAspectInstanceFactory instanceFactory = createAspectInstanceFactory(am, aspectClass, aspectName); addAdvisorsFromAspectInstanceFactory(instanceFactory); } /** * Add all {@link Advisor Advisors} from the supplied {@link MetadataAwareAspectInstanceFactory} * to the current chain. Exposes any special purpose {@link Advisor Advisors} if needed. * @see #makeAdvisorChainAspectJCapableIfNecessary() */ private void addAdvisorsFromAspectInstanceFactory(MetadataAwareAspectInstanceFactory instanceFactory) { List advisors = this.aspectFactory.getAdvisors(instanceFactory); this.addAllAdvisors((Advisor[]) advisors.toArray(new Advisor[advisors.size()])); makeAdvisorChainAspectJCapableIfNecessary(); } /** * Create an {@link AspectMetadata} instance for the supplied aspect type. */ private AspectMetadata createAspectMetadata(Class aspectClass, String aspectName) { AspectMetadata am = new AspectMetadata(aspectClass, aspectName); if (!am.getAjType().isAspect()) { throw new IllegalArgumentException("Class [" + aspectClass.getName() + "] is not a valid aspect type"); } return am; } /** * Create a {@link MetadataAwareAspectInstanceFactory} for the supplied aspect type. If the aspect type * has no per clause, then a {@link SingletonMetadataAwareAspectInstanceFactory} is returned, otherwise * a {@link PrototypeAspectInstanceFactory} is returned. */ private MetadataAwareAspectInstanceFactory createAspectInstanceFactory( AspectMetadata am, Class aspectClass, String aspectName) { MetadataAwareAspectInstanceFactory instanceFactory = null; if (am.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) { // Create a shared aspect instance. Object instance = getSingletonAspectInstance(aspectClass); instanceFactory = new SingletonMetadataAwareAspectInstanceFactory(instance, aspectName); } else { // Create a factory for independent aspect instances. instanceFactory = new SimpleMetadataAwareAspectInstanceFactory(aspectClass, aspectName); } return instanceFactory; } /** * Add any special-purpose {@link Advisor Advisors} needed for AspectJ support * to the chain. {@link #updateAdvisorArray() Updates} the {@link Advisor} array * and fires {@link #adviceChanged events}. */ private void makeAdvisorChainAspectJCapableIfNecessary() { if (AspectJProxyUtils.makeAdvisorChainAspectJCapableIfNecessary(getAdvisorsInternal())) { updateAdvisorArray(); adviceChanged(); } } /** * Get the singleton aspect instance for the supplied aspect type. An instance * is created if one cannot be found in the instance cache. */ private Object getSingletonAspectInstance(Class aspectClass) { synchronized (aspectCache) { Object instance = aspectCache.get(aspectClass); if (instance != null) { return instance; } try { instance = aspectClass.newInstance(); aspectCache.put(aspectClass, instance); return instance; } catch (InstantiationException ex) { throw new AopConfigException("Unable to instantiate aspect class [" + aspectClass.getName() + "]", ex); } catch (IllegalAccessException ex) { throw new AopConfigException("Cannot access aspect class [" + aspectClass.getName() + "]", ex); } } } /** * Create a new proxy according to the settings in this factory. *

Can be called repeatedly. Effect will vary if we've added * or removed interfaces. Can add and remove interceptors. *

Uses a default class loader: Usually, the thread context class loader * (if necessary for proxy creation). * @return the new proxy */ public T getProxy() { return (T) createAopProxy().getProxy(); } /** * Create a new proxy according to the settings in this factory. *

Can be called repeatedly. Effect will vary if we've added * or removed interfaces. Can add and remove interceptors. *

Uses the given class loader (if necessary for proxy creation). * @param classLoader the class loader to create the proxy with * @return the new proxy */ public T getProxy(ClassLoader classLoader) { return (T) createAopProxy().getProxy(classLoader); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy