天天看点

【源码】Spring AOP 11 ProxyFactoryBean ProxyFactory AspectJProxyFactory前言ProxyFactoryBeanProxyFactoryAspectJProxyFactory总结

【源码】Spring AOP 11 ProxyFactoryBean ProxyFactory AspectJProxyFactory

  • 前言
  • ProxyFactoryBean
    • demo
  • ProxyFactory
    • demo
  • AspectJProxyFactory
    • demo
  • 总结

前言

三大代理类

【源码】Spring AOP 11 ProxyFactoryBean ProxyFactory AspectJProxyFactory前言ProxyFactoryBeanProxyFactoryAspectJProxyFactory总结

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 原理解读一