Spring | 0.9 AOP
2020-05-12 本文已影响0人
不一样的卡梅利多
AOP
核心功能:将业务代码与非业务代码连接到一起,并且还需要集成到bean 容器中
核心类视图
AOP 核心类.pngAOP 与beans 集成
spring 创建ProxyFactoryBean 调用时序
1. spring读取配置 ,实例化ProxyFactoryBean,并且设置setProxyInterfaces(String[] interfaceNames)
-
ProxyFactoryBean 创建完成后,调用setBeanFactory(BeanFactory beanFactory),afterPropertiesSet()
-
由于ProxyFactoryBean 是一个FactoryBean ,还需要依据继续创建对象 FactoryBean.getObject()
FactoryBean.getObject 实现
public Object getObject() throws BeansException {
if (this.singleton) {
// Return singleton
return this.singletonInstance;
}
else {
// Create new interface
return createInstance();
}
}
private Object createInstance() {
refreshInterceptorChain();
AopProxy proxy = new AopProxy(this);
return AopProxy.getProxy(getClass().getClassLoader(), proxy);
}
refreshInterceptorChain: 实例化 MethodPointcut bean,并且创建InvokerInterceptor
AopProxy.getProxy:依据配置创建动态代理对象。生成的代理对象调方法调用逻辑走AopProxy.invoke 方法,委派给MethodInvocationImpl 实现,对方法调用添加配置的一系列拦截器。实现了代码动态链接功能。
public final Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Create a new invocation object
// TODO refactor into InvocationFactory?
MethodInvocationImpl invocation = new MethodInvocationImpl(proxy, config.getTarget(),
method.getDeclaringClass(), //?
method, args,
this.config.getMethodPointcuts(), // could customize here
this.config.getAttributeRegistry());
if (this.config.getExposeInvocation()) {
// Make invocation available if necessary
AopContext.setCurrentInvocation(invocation);
}
try {
if (EQUALS_METHOD.equals(invocation.getMethod())) {
// What if equals throws exception!?
logger.debug("Intercepting equals() method in proxy");
return invocation.getMethod().invoke(this, invocation.getArguments());
}
Object retVal = invocation.invokeNext();
if (retVal != null && retVal == invocation.getInvokedObject()) {
// Special case: it returned this
// Note that we can't help if the target sets
// a reference to itself in another returned object
logger.debug("Replacing 'this' with reference to proxy");
retVal = proxy;
}
return retVal;
}
finally {
if (this.config.getExposeInvocation()) {
AopContext.setCurrentInvocation(null);
}
//if (logger.isDebugEnabled()) {
// logger.debug("Processed invocation [" + invocation + "]");
//}
}
}