AopContext获取动态代理对象
package org.springframework.aop.framework;
import org.springframework.core.NamedThreadLocal;
/**
* Class containing static methods used to obtain information about the current AOP invocation.
* 类中包含的静态方法被用来获取当前AOP调用信息
* <p>The {@code currentProxy()} method is usable if the AOP framework is configured to
* expose the current proxy (not the default). It returns the AOP proxy in use. Target objects
* or advice can use this to make advised calls, in the same way as {@code getEJBObject()}
* can be used in EJBs. They can also use it to find advice configuration.
* 通过currentProxy()方法获取暴漏的代理对象
*
* <p>Spring's AOP framework does not expose proxies by default, as there is a performance cost
* in doing so.
* Spring AOP默认不会暴漏代理对象,因为会存在性能消耗
*
* <p>The functionality in this class might be used by a target object that needed access
* to resources on the invocation. However, this approach should not be used when there is
* a reasonable alternative, as it makes application code dependent on usage under AOP and
* the Spring AOP framework in particular.
*
* @author Rod Johnson
* @author Juergen Hoeller
* @since 13.03.2003
*/
public abstract class AopContext {
/**
* ThreadLocal holder for AOP proxy associated with this thread.
* Will contain {@code null} unless the "exposeProxy" property on
* the controlling proxy configuration has been set to "true".
* @see ProxyConfig#setExposeProxy
*/
private static final ThreadLocal<Object> currentProxy = new NamedThreadLocal<Object>("Current AOP proxy");
/**
* Try to return the current AOP proxy. This method is usable only if the
* calling method has been invoked via AOP, and the AOP framework has been set
* to expose proxies. Otherwise, this method will throw an IllegalStateException.
* @return Object the current AOP proxy (never returns {@code null})
* @throws IllegalStateException if the proxy cannot be found, because the
* method was invoked outside an AOP invocation context, or because the
* AOP framework has not been configured to expose the proxy
*/
public static Object currentProxy() throws IllegalStateException {
Object proxy = currentProxy.get();
if (proxy == null) {
throw new IllegalStateException(
"Cannot find current proxy: Set 'exposeProxy' property on Advised to 'true' to make it available.");
}
return proxy;
}
/**
* Make the given proxy available via the {@code currentProxy()} method.
* <p>Note that the caller should be careful to keep the old value as appropriate.
* @param proxy the proxy to expose (or {@code null} to reset it)
* @return the old proxy, which may be {@code null} if none was bound
* @see #currentProxy()
*/
static Object setCurrentProxy(Object proxy) {
Object old = currentProxy.get();
if (proxy != null) {
currentProxy.set(proxy);
}else {
currentProxy.remove();
}
return old;
}
}
@EnableAspectJAutoProxy注解
/**
*
*org.springframework.context.annotation
Annotation Type EnableAspectJAutoProxy
@Target(value=TYPE)
@Retention(value=RUNTIME)
@Documented
@Import(value=org.springframework.context.annotation.AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy
Enables support for handling components marked with AspectJ's @Aspect annotation, similar to functionality found in Spring's <aop:aspectj-autoproxy> XML element. To be used on @Configuration classes as follows:
@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
@Bean
public FooService fooService() {
return new FooService();
}
@Bean
public MyAspect myAspect() {
return new MyAspect();
}
}
Where FooService is a typical POJO component and MyAspect is an @Aspect-style aspect:
public class FooService {
// various methods
}
@Aspect
public class MyAspect {
@Before("execution(* FooService+.*(..))")
public void advice() {
// advise FooService methods as appropriate
}
}
In the scenario above, @EnableAspectJAutoProxy ensures that MyAspect will be properly processed and that FooService will be proxied mixing in the advice that it contributes.
Users can control the type of proxy that gets created for FooService using the proxyTargetClass() attribute. The following enables CGLIB-style 'subclass' proxies as opposed to the default interface-based JDK proxy approach.
@Configuration
@EnableAspectJAutoProxy(proxyTargetClass=true)
public class AppConfig {
// ...
}
Note that @Aspect beans may be component-scanned like any other. Simply mark the aspect with both @Aspect and @Component:
package com.foo;
@Component
public class FooService { ... }
@Aspect
@Component
public class MyAspect { ... }
Then use the @ComponentScan annotation to pick both up:
@Configuration
@ComponentScan("com.foo")
@EnableAspectJAutoProxy
public class AppConfig {
// no explicit @Bean definitions required
}
Note: @EnableAspectJAutoProxy applies to its local application context only, allowing for selective proxying of beans at different levels. Please redeclare @EnableAspectJAutoProxy in each individual context, e.g. the common root web application context and any separate DispatcherServlet application contexts, if you need to apply its behavior at multiple levels.
This feature requires the presence of aspectjweaver on the classpath. While that dependency is optional for spring-aop in general, it is required for @EnableAspectJAutoProxy and its underlying facilities.
Since:
3.1
Author:
Chris Beams, Juergen Hoeller
See Also:
Aspect
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(AspectJAutoProxyRegistrar.class)
public @interface EnableAspectJAutoProxy {
/**
* Indicate whether subclass-based (CGLIB) proxies are to be created as opposed
* to standard Java interface-based proxies. The default is {@code false}.
* 指示是否创建基于子类的CGLIB代理,而不是基于java接口的代理,默认为false
*/
boolean proxyTargetClass() default false;
/**
* Indicate that the proxy should be exposed by the AOP framework as a {@code ThreadLocal}
* for retrieval via the {@link org.springframework.aop.framework.AopContext} class.
* Off by default, i.e. no guarantees that {@code AopContext} access will work.
* @since 4.3.1
*/
boolean exposeProxy() default false;
}