spring5.0源码解析 Aop 02
建立 AopProxy对象
设计原理
在spring 的 Aop模块中,是通过配置和调用Spring的ProxyFactoryBean来完成这个任务的,在 ProxyFactoryBean 中,封装了主要代理对象的生成过程,这个过程由JDK的Proxy和CGLibL两种方式实现
在这个 类继承关系中,可以看到完成 AOP应用的类,比如AspectJProxyFactory、TransactionProxyFactoryBean , 具体的对象的生成分别由 ProxyFactoryBean,AspectJProxyFactory和ProxyFactory来完成,**ProxyFactoryBean和ProxyFactory都提供了AOP功能的封装,只是使用ProxyFactoryBean可以在Ioc容器中完成声明式配置,而是用ProxyFactory 则需要编程式使用Aop的功能
ProxyConfig
用于创建代理的配置的方便超类,以确保所有代理创建者具有一致的属性
// 是否直接代理目标类,为不是代理特定的接口
private boolean proxyTargetClass = false;
// 标记是否对代理进行优化。启动优化通常意味着在代理对象被创建后,增强的修改将不会生效,因此默认值为false。
private boolean optimize = false;
//该属性用于空值生成的代理对象是否可以强制转型为Advised,默认值为false,表示任何生成的代理对象都可以强制转换成Advised,true是不可以,可以通过Adviced查询代理对象的一些状态
boolean opaque = false;
// 标记代理对象是否应该被aop框架通过AopContext以ThreadLocal的形式暴露出去。
// 当一个代理对象需要调用它自己的另外一个代理方法时,这个属性将非常有用。默认是是false,以避免不必要的拦截。
boolean exposeProxy = false;
// 标记该配置是否需要被冻结,如果被冻结,将不可以修改增强的配置。
// 如果该值为true,那么代理对象的生成的各项信息配置完成,则不容许更改,如果ProxyFactory设置完毕,该值为true,则不能对Advice进行改动,可以优化代理对象生成的性能。默认情况下该值为false
private boolean frozen = false;
AdvisedSupport
可以将他看成其子类创建Aop代理对象的一个辅助类。
配置当前代理的Adivsiors
配置当前代理的目标对象
配置当前代理的接口
提供getInterceptorsAndDynamicInterceptionAdvice方法用来获取对应代理方法对应有效的拦截器链
ProxyFactoryBean
getObject返回此工厂Aop代理实例
ProxyFactoryBean 实现了 FactoryBean getObject返回此工厂Aop代理实例
// 创建此工厂返回的AOP代理实例。
@Override
@Nullable
public Object getObject() throws BeansException {
// 初始化通知器链
initializeAdvisorChain();
// 这里对singleton和prititype类型进行了区分,生成对象的proxy
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();
}
}
proxyFactory
在专栏前面的文章介绍了 使用ProxyFactoryBean 实现获取Aop代理对象。 ProxyFactoryBean 与 proxyFactory 的实现原理是一样的 ,不过是对 拦截器、切入点进行整合,通过递归的形式生成代理对象的过程,只是他们两个在最外层的表现上有所不同。
proxyFactory 是 ProxyCreatorSupport 的子类,proxyFactory 获取代理对象也是通过 getProxy方法为入口,由 getAopProxyFactory 完成 , 而 ProxyCreatorSupport 也继承了 AdvisedSupport 具有了 通知和切入点的支持
public <T> T getProxy() {
return (T) createAopProxy().getProxy();
}
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
// getAopProxyFactory 获取的是 DefaultAopProxyFactory 对象
return getAopProxyFactory().createAopProxy(this);
}
AspectProxyFactory、 proxyFactory 、 ProxyFactoryBean 的区别
- proxyFactory 这种是硬编码的方式,可以脱离spring直接使用。
- AspectProxyFactory 实现了 @AspectJ 注解的形式 我们只需要配置切面、通知、切点表达式就能自动的实现切入的效果
- ProxyFactoryBean 是创建AOP的最基本的方式。是将我们的AOP和IOC融合起来,而ProxyFactory 则是只能通过代码硬编码进行编写 一般都是给spring自己使用。
initializeAdvisorChain 初始化通知链
// 初始化通知链
private synchronized void initializeAdvisorChain() throws AopConfigException, BeansException {
// 判断是否初始化过 , 通知链只出初始化一次
if (this.advisorChainInitialized) {
return;
}
if (!ObjectUtils.isEmpty(this.interceptorNames)) {
if (this.beanFactory == null) {
throw new IllegalStateException("No BeanFactory available anymore (probably due to serialization) " +
"- cannot resolve interceptor names " + Arrays.asList(this.interceptorNames));
}
// Globals can't be last unless we specified a targetSource using the property...
if (this.interceptorNames[this.interceptorNames.length - 1].endsWith(GLOBAL_SUFFIX) &&
this.targetName == null && this.targetSource == EMPTY_TARGET_SOURCE) {
throw new AopConfigException("Target required after globals");
}
// Materialize interceptor chain from bean names.
// 从bean名称具体化拦截器链。
for (String name : this.interceptorNames) {
// 如果拦截器name 以 * 号结尾
if (name.endsWith(GLOBAL_SUFFIX)) {
if (!(this.beanFactory instanceof ListableBeanFactory)) {
throw new AopConfigException(
"Can only use global advisors or interceptors with a ListableBeanFactory");
}
addGlobalAdvisors((ListableBeanFactory) this.beanFactory,
name.substring(0, name.length() - GLOBAL_SUFFIX.length()));
}
else {
// If we get here, we need to add a named interceptor.
// We must check if it's a singleton or prototype.
//需要添加一个命名拦截器。必须检查它是单体还是原型。
Object advice;
if (this.singleton || this.beanFactory.isSingleton(name)) {
// Add the real Advisor/Advice to the chain.
advice = this.beanFactory.getBean(name);
}
else {
// It's a prototype Advice or Advisor: replace with a prototype.
// Avoid unnecessary creation of prototype bean just for advisor chain initialization.
advice = new PrototypePlaceholderAdvisor(name);
}
//将给定的advice, advisor或对象添加到拦截器列表中。
addAdvisorOnChainCreation(advice);
}
}
}
this.advisorChainInitialized = true;
}
getSingletonInstance 生成单例的代理对象
getSingletonInstance 这个方法是 proxyFactoryBean生成AopProxy代理对象的调用接口。代理对象会封装对target目标对象的调用,也就是说针对target对象的调用行为会被这里生成的代理对象所拦截,
// 返回这个类的代理对象的单例实例,如果尚未创建,则延迟创建。
private synchronized Object getSingletonInstance() {
if (this.singletonInstance == null) {
// 被代理的目标对象
this.targetSource = freshTargetSource();
if (this.autodetectInterfaces && getProxiedInterfaces().length == 0 && !isProxyTargetClass()) {
// Rely on AOP infrastructure to tell us what interfaces to proxy.
// 依靠AOP基础设施告诉我们代理的接口。
Class<?> targetClass = getTargetClass();
if (targetClass == null) {
throw new FactoryBeanNotInitializedException("Cannot determine target class for proxy");
}
// 设置代理对象的接口
setInterfaces(ClassUtils.getAllInterfacesForClass(targetClass, this.proxyClassLoader));
}
// 初始化共享单例实例。
super.setFrozen(this.freezeProxy);
// 生成具体的代理对象
this.singletonInstance = getProxy(createAopProxy());
}
return this.singletonInstance;
}
// 获取代理对象
protected Object getProxy(AopProxy aopProxy) {
return aopProxy.getProxy(this.proxyClassLoader);
}
AopProxy
spring 利用 AopProxy 接口类把Aop代理对象的实现与框架其他部分有效的分开,他有两个子类 CglibAopProxy 和 JdkDynamicAopProxy 分别采用 CGLIB和 JDK来生成代理对象。
生成 AopProxy 是通过 AopProxyFactory来实现的,至于生成什么样的代理对象封装在 AdvisedSupport 中,也是 ProxyFactoryBean 的父类
// 通过 AopProxyFactory 生成 AopProxy
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory.createAopProxy 方法 根据 AdvisedSupport 生成AopProxy 这里决定了使用CGLIB还是Jdk的的方式
@Override
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
if (!NativeDetector.inNativeImage() &&
(config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config))) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果targetClass是接口类,使用Jdk 来生成
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 使用Cglib 生成
return new ObjenesisCglibAopProxy(config);
}
else {
return new JdkDynamicAopProxy(config);
}
}
在AopProxy代理对象生成过程中,首先要从AdvisedSupport对象中取得配置的目标对象,在完成目标对象的检查后,根据配置情况来决定使用什么方式来创建AopProxy代理对象。