一、前言
web.xml里面配置
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
component-bean.xml里面配置
<bean id="lavaPvgInfo" class="com.alibaba.lava.privilege.PrivilegeInfo"
scope="request">
<property name="aesKey" value="666" />
<aop:scoped-proxy />
</bean>
测试Rpc
@WebResource("/testService")public class TestRpc { @Autowired
private PrivilegeInfo pvgInfo; @ResourceMapping("test") public ActionResult test(ErrorContext context) {
ActionResult result = new ActionResult();
String aseKey = pvgInfo.getAesKey();
pvgInfo.setAesKey("888");
System.out.println("aseKey---" + aseKey); return result;
}
}
二、源码分析
2.1 使用装饰模式对Bean定义进行修改
先上时序图:
可知上面时序图完成了对RequestScope对象定义的修改创建了代理bean,具体修改内容是修改了beanClass为ScopedProxyFactoryBean,并且保存了原来的bean定义originatingBeanDefinition。
下面看下主要代码ScopedProxyUtils中的createScopedProxy
public static BeanDefinitionHolder createScopedProxy(BeanDefinitionHolder definition,
BeanDefinitionRegistry registry, boolean proxyTargetClass) {
String originalBeanName = definition.getBeanName();
BeanDefinition targetDefinition = definition.getBeanDefinition(); // 保持原来的beanName不变,但是基于原来的bean定义创建代理bean定义,
// 保存原来的bean定义到代理bean里面为后面创建代理类做准备.
RootBeanDefinition proxyDefinition = new RootBeanDefinition(ScopedProxyFactoryBean.class);
proxyDefinition.setOriginatingBeanDefinition(definition.getBeanDefinition());
proxyDefinition.setSource(definition.getSource());
proxyDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
String targetBeanName = getTargetBeanName(originalBeanName);
proxyDefinition.getPropertyValues().add("targetBeanName", targetBeanName); if (proxyTargetClass) {
targetDefinition.setAttribute(AutoProxyUtils.PRESERVE_TARGET_CLASS_ATTRIBUTE, Boolean.TRUE); // ScopedFactoryBean's "proxyTargetClass" default is TRUE, so we don't need to set it explicitly here.
} else {
proxyDefinition.getPropertyValues().add("proxyTargetClass", Boolean.FALSE);
} // Copy autowire settings from original bean definition.
proxyDefinition.setAutowireCandidate(targetDefinition.isAutowireCandidate());
proxyDefinition.setPrimary(targetDefinition.isPrimary()); if (targetDefinition instanceof AbstractBeanDefinition) {
proxyDefinition.copyQualifiersFrom((AbstractBeanDefinition) targetDefinition);
} // The target bean should be ignored in favor of the scoped proxy.
targetDefinition.setAutowireCandidate(false);
targetDefinition.setPrimary(false); // 注册代理前的bean到容器,在创建代理bean时候使用.targetBeanName=scopedTarget.lavaPvgInfo
registry.registerBeanDefinition(targetBeanName, targetDefinition); // 返回代理bean定义作为原来的bean定义
return new BeanDefinitionHolder(proxyDefinition, originalBeanName, definition.getAliases());
}
2.2 创建代理Bean
先上时序图
主要代码如下:
public void setBeanFactory(BeanFactory beanFactory) {
...
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory; this.scopedTargetSource.setBeanFactory(beanFactory); //创建代理工厂
ProxyFactory pf = new ProxyFactory();
pf.copyFrom(this);
pf.setTargetSource(this.scopedTargetSource);
... // Add an introduction that implements only the methods on ScopedObject.
ScopedObject scopedObject = new DefaultScopedObject(cbf, this.scopedTargetSource.getTargetBeanName());
pf.addAdvice(new DelegatingIntroductionInterceptor(scopedObject)); // Add the AopInfrastructureBean marker to indicate that the scoped proxy
// itself is not subject to auto-proxying! Only its target bean is.
pf.addInterface(AopInfrastructureBean.class); this.proxy = pf.getProxy(cbf.getBeanClassLoader());
}
public Object getProxy(ClassLoader classLoader) {
.... try {//获取目标类,也就是被代理的
Class rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class proxySuperClass = rootClass; if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class[] additionalInterfaces = rootClass.getInterfaces(); for (Class additionalInterface : additionalInterfaces) { this.advised.addInterface(additionalInterface);
}
} // Validate the class, writing log messages as necessary.
validateClassIfNecessary(proxySuperClass); // Configure CGLIB Enhancer...
Enhancer enhancer = createEnhancer(); if (classLoader != null) {
enhancer.setClassLoader(classLoader); if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
} //设置被代理类为超类,这样解释了为啥代理后的类能够赋值给被代理类不会发生错误
enhancer.setSuperclass(proxySuperClass);
enhancer.setStrategy(new UndeclaredThrowableStrategy(UndeclaredThrowableException.class));
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setInterceptDuringConstruction(false); //获取拦截器,其中就有DynamicAdvisedInterceptor
Callback[] callbacks = getCallbacks(rootClass);
enhancer.setCallbacks(callbacks);
enhancer.setCallbackFilter(new ProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
Class[] types = new Class[callbacks.length]; for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
enhancer.setCallbackTypes(types); // Generate the proxy class and create a proxy instance.
Object proxy; if (this.constructorArgs != null) {
proxy = enhancer.create(this.constructorArgTypes, this.constructorArgs);
} else {
proxy = enhancer.create();
} return proxy;
}
2.3 调用时序图
代码:
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
... public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null; boolean setProxyContext = false;
Class targetClass = null;
Object target = null; try { if (this.advised.exposeProxy) { // Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
} // 获取被代理类
target = getTarget(); if (target != null) {
targetClass = target.getClass();
}
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal; // Check whether we only have one InvokerInterceptor: that is,
// no real advice, but just reflective invocation of the target.
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
retVal = methodProxy.invoke(target, args);
} else { // We need to create a method invocation...
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = massageReturnTypeIfNecessary(proxy, target, method, retVal); return retVal;
} finally { if (target != null) {
releaseTarget(target);
} if (setProxyContext) { // Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
}
getTarget是关键方法,看下:
protected Object getTarget() throws Exception { return this.advised.getTargetSource().getTarget();
} public Object getTarget() throws Exception { return getBeanFactory().getBean(getTargetBeanName());
}
所以最后是从IOC获取目标类bean.下面看下getBean代码:
//获取RequestScope对象String scopeName = mbd.getScope();final Scope scope = this.scopes.get(scopeName);if (scope == null) { throw new IllegalStateException("No Scope registered for scope '" + scopeName + "'");
}try { //调用RequestScope对象对象的get方法
Object scopedInstance = scope.get(beanName, new ObjectFactory<Object>() { public Object getObject() throws BeansException {
beforePrototypeCreation(beanName); try { return createBean(beanName, mbd, args);
} finally {
afterPrototypeCreation(beanName);
}
}
});
bean = getObjectForBeanInstance(scopedInstance, name, beanName, mbd);
}catch (IllegalStateException ex) { throw new BeanCreationException(beanName, "Scope '" + scopeName + "' is not active for the current thread; " + "consider defining a scoped proxy for this bean if you intend to refer to it from a singleton",
ex);
}
requestscope的get方法:
public Object get(String name, ObjectFactory objectFactory) { //获取当前线程属性集合
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
Object scopedObject = attributes.getAttribute(name, getScope()); if (scopedObject == null) {//不在属性集则调用createBean创建,然后放入集合
scopedObject = objectFactory.getObject();
attributes.setAttribute(name, scopedObject, getScope());
} return scopedObject;
}
可知requestAttributesHolder属性是threadlocal
public abstract class RequestContextHolder { private static final boolean jsfPresent =
ClassUtils.isPresent("javax.faces.context.FacesContext", RequestContextHolder.class.getClassLoader()); private static final ThreadLocal<RequestAttributes> requestAttributesHolder = new NamedThreadLocal<RequestAttributes>("Request attributes"); private static final ThreadLocal<RequestAttributes> inheritableRequestAttributesHolder = new NamedInheritableThreadLocal<RequestAttributes>("Request context");
}
本文分享自微信公众号 - 技术原始积累(gh_805ebfd2deb0)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。