【源码】Spring AOP 11 ProxyFactoryBean ProxyFactory AspectJProxyFactory
- 前言
- ProxyFactoryBean
-
- demo
- ProxyFactory
-
- demo
- AspectJProxyFactory
-
- demo
- 总结
前言
三大代理类

ProxyFactoryBean
public class ProxyFactoryBean extends ProxyCreatorSupport
implements FactoryBean<Object>, BeanClassLoaderAware, BeanFactoryAware {
// ...
@Override
@Nullable
public Object getObject() throws BeansException {
// 初始化 Advisors Chain by interceptor names
initializeAdvisorChain();
// 单例
if (isSingleton()) {
return getSingletonInstance();
}
// 非单例
else {
if (this.targetName == null) {
logger.info("Using non-singleton proxies with singleton targets is often undesirable. " +
"Enable prototype proxies by setting the 'targetName' property.");
}
return newPrototypeInstance();
}
}
// ...
private synchronized Object getSingletonInstance() {
// 还未创建
if (this.singletonInstance == null) {
// 如果存在 targetName,则从 bean工厂 取出包装成 SingletonTargetSource 返回
this.targetSource = freshTargetSource();
// 允许自动检测接口 && 声明实现的接口为空 && 非直接代理目标类
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
// 则帮助搜索目标类的接口,如果还没有,那就只能 CGLIB 咯
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// 是否冻结
super.setFrozen(this.freezeProxy);
// 创建代理并缓存,实际是由父类 ProxyCreator 委托给代理创建器去创建
this.singletonInstance = getProxy(createAopProxy());
}
// 有则直接返回
return this.singletonInstance;
}
// 交给 AopProxy 创建
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
// ...
}
因为本身是个 FactoryBean 又实现了 BeanFactoryAware 接口,因此直接通过 interceptorNames 从 bean工厂 获取 advisor | advice (包装成 DefaultPointcutAdvisor),最终代理实例通过
getObject
方法获得,本质上是由父类 ProxyCreatorSuport 委托给 代理创建器 创建的
demo
@ComponentScan("com.xsn.spring.aop")
@Configuration
public class AopConfig {
@Bean
public PointcutAdvisor myPointcutAdvisor() {
// 正则匹配以 a 结尾的方法
return new RegexpMethodPointcutAdvisor(".*a$",
(AfterReturningAdvice) (r, m, a, t) -> {
System.out.println("be proxied after");
});
}
@Bean
public MethodInterceptor myMethodInterceptor() {
return (MethodInterceptor) (mi) -> {
System.out.println("be proxied before");
return mi.proceed();
};
}
@Bean
public ProxyFactoryBean myProxyFactoryBean(A a) throws ClassNotFoundException {
ProxyFactoryBean proxyFactoryBean = new ProxyFactoryBean();
proxyFactoryBean.setProxyInterfaces(new Class[]{A.class});
// 从 bean工厂 中找
proxyFactoryBean.setInterceptorNames("myPointcutAdvisor", "myMethodInterceptor");
// proxyFactoryBean.setTargetName("aService");
// 相比上面的方法注入 target 更“优雅”
proxyFactoryBean.setTarget(a);
return proxyFactoryBean;
}
}
@Service
public class AService implements A {
public void a() {
System.out.println("a");
}
@Override
public void b() {
System.out.println("b");
}
@Override
public void c() {
System.out.println("c");
}
}
@Test
public void test1() {
AnnotationConfigApplicationContext ac =
new AnnotationConfigApplicationContext(AopConfig.class);
A a = (A) ac.getBean("myProxyFactoryBean");
a.a();
a.b();
a.c();
}
结果:
be proxied before
a
be proxied after
be proxied before
b
be proxied before
c
显然, Spring 创建代理用的并不是这种方式。毕竟不可能给每个对象创建一个 工厂bean
ProxyFactory
public class ProxyFactory extends ProxyCreatorSupport {
// ...
@SuppressWarnings("unchecked")
public static <T> T getProxy(Class<T> proxyInterface, Interceptor interceptor) {
return (T) new ProxyFactory(proxyInterface, interceptor).getProxy();
}
@SuppressWarnings("unchecked")
public static <T> T getProxy(Class<T> proxyInterface, TargetSource targetSource) {
return (T) new ProxyFactory(proxyInterface, targetSource).getProxy();
}
public static Object getProxy(TargetSource targetSource) {
if (targetSource.getTargetClass() == null) {
throw new IllegalArgumentException("Cannot create class proxy for TargetSource with null target class");
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.setTargetSource(targetSource);
proxyFactory.setProxyTargetClass(true);
return proxyFactory.getProxy();
}
}
提供了几个静态方法供我们直接使用。实际上,Spring 就是用它为我们自动创建代理对象的
demo
@Service
public class AService implements A {
public void a() {
System.out.println("a");
}
@Override
public void b() {
System.out.println("b");
}
@Override
public void c() {
System.out.println("c");
}
}
@Aspect
//@Component(我们自己解析,所以不需要放进容器)
public class MyAspect {
@Pointcut("execution(* a())")
public void pt() {
}
@After("pt()")
public void after() {
System.out.println("after proxy");
}
}
@Test
public void test2() {
ProxyFactory proxyFactory = new ProxyFactory(new AService());
// 我们使用 MetadataAwareAspectInstanceFactory 去解析自定义的切面实例
MetadataAwareAspectInstanceFactory aspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(
new SingletonMetadataAwareAspectInstanceFactory(
new MyAspect(), "myAspect"
)
);
AspectJAdvisorFactory aspectJAdvisorFactory =
new ReflectiveAspectJAdvisorFactory();
// interceptors chain 的第一个必须是 ExposeInvocationInterceptor,将 MethodInvocation 暴露出去
proxyFactory.addAdvice(ExposeInvocationInterceptor.INSTANCE);
// 用 ReflectiveAspectJAdvisorFactory 获取切面对应的 advisors
proxyFactory.addAdvisors(aspectJAdvisorFactory.getAdvisors(aspectInstanceFactory));
A a = (A) proxyFactory.getProxy();
a.a();
a.b();
a.c();
}
结果:
a
after proxy
b
c
注意分清 ReflectiveAspectJAdvisorFactory 和 DefaultAdvisorChainFactory 的区别
前者借助 MetadataAwareAspectInstanceFactory 的 切面元数据 信息,筛选出要解析的方法。将切面方法上的 AspectJ Expression 解析成 AspectJExpressionPointcut ,然后包装成 InstantiationModelAwarePointcutAdvisorImpl 。同时还提供了 getAdvice 方法,根据 元数据信息 将 通知 包装成对应的 AbstractAspectJAdvice 返回。即 Aspect -> Advisors
后者则是从 Advised 获取 advisors,遍历与 method 匹配,对于匹配上的 advisor 则将其 advice 借助 DefaultAdvisorAdapterRegister 适配成 interceptors。即 Advisors -> Interceptors
AspectJProxyFactory
这个类就不贴源码了,提供了
addAspect
的方法,相当于在 ProxyFactory 的基础上允许我们增加切面,帮我们解析成 Advisors ,正如我们在上一个 demo 中做的一样
demo
@Service
public class AService implements A {
public void a() {
System.out.println("a");
}
@Override
public void b() {
System.out.println("b");
}
@Override
public void c() {
System.out.println("c");
}
}
@Aspect
//@Component(我们自己解析,所以不需要放进容器)
public class MyAspect {
@Pointcut("execution(* a())")
public void pt() {
}
@After("pt()")
public void after() {
System.out.println("after proxy");
}
}
@Test
public void test3() {
AspectJProxyFactory aspectJProxyFactory =
new AspectJProxyFactory(new AService());
aspectJProxyFactory.addAspect(MyAspect.class);
A a = (A) aspectJProxyFactory.getProxy();
a.a();
a.b();
a.c();
}
结果:
a
after proxy
b
c
总结
本章节总结了三大代理创建类,我们对代理的创建方式已经有了非常全面的了解了。那 Spring AOP 到底使用哪种方式来创建的代理呢?接下来的章节,我们分析 Spring AOP 的原理
上一篇:【源码】Spring AOP 10 AopProxyFactory AopProxy
下一篇:【源码】Spring AOP 12 原理解读一