天天看點

【源碼】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 原了解讀一