AOP 工厂对象之ScopedProxyFactoryBean 原理解析
J2EE开发者,对购物车这个概念太熟悉了。存在于Session周期中。今天就说说,如果用Spring管理购物车,怎么处理。
-
使用场景
1
2
3
|
< bean id = "cart" class = "com.hellojd.jpetstore.domain.model.Cart" scope = "session" >
< aop:scoped-proxy proxy-target-class = "true" />
</ bean >
|
必须要声明 <aop:scoped-proxy..>
或者 annotation配置
1
2
3
4
5
|
@Scope (value= "session" ,proxyMode= ScopedProxyMode.TARGET_CLASS)
@Component public class Cart implements Serializable {
... } |
经过上面的配置,就可以在controller中,注入使用了。
接下来,分析spring是如何管理购物车的.
2. 源码分析
2.1 ScopedProxyFactoryBean 类图
既然ScopedProxyFactoryBean,是个FactoryBean,就关注下getObject()
1
2
3
4
5
6
|
public Object getObject() {
if ( this .proxy == null ) {
throw new FactoryBeanNotInitializedException();
}
return this .proxy;
} |
重点是proxy属性的维护了。在BeanFactoryAware.setBeanFactory接口方法中初始化。
发生时机:普通属性注入之后,InitializingBean.afterPropertiesSet() 和 custom init-method之前
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
public void setBeanFactory(BeanFactory beanFactory) {
if (!(beanFactory instanceof ConfigurableBeanFactory)) {
throw new IllegalStateException( "Not running in a ConfigurableBeanFactory: " + beanFactory);
}
ConfigurableBeanFactory cbf = (ConfigurableBeanFactory) beanFactory;
this .scopedTargetSource.setBeanFactory(beanFactory);
ProxyFactory pf = new ProxyFactory();
pf.copyFrom( this );
pf.setTargetSource( this .scopedTargetSource);
Class beanType = beanFactory.getType( this .targetBeanName);
if (beanType == null ) {
throw new IllegalStateException( "Cannot create scoped proxy for bean '" + this .targetBeanName +
"': Target type could not be determined at the time of proxy creation." );
}
if (!isProxyTargetClass() || beanType.isInterface() || Modifier.isPrivate(beanType.getModifiers())) {
//设置源接口
pf.setInterfaces(ClassUtils.getAllInterfacesForClass(beanType, cbf.getBeanClassLoader()));
}
// 为增加DefaultScopedObject能力,增加introduction
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());
} |
TargetSource | 用于获取AOP调用的当前“目标” | Target |
AbstractBeanFactoryBasedTargetSource | 基于Spring BeanFactory的实现TargetSource的基类 | Target |
ProxyConfig | 方便的用于创建代理的超类配置 | AOP |
ProxyFactory | 编程式AOP代理工厂 | AOP |
ProxyCreatorSupport | 代理工厂的基类 |
AOP |
AdvisedSupport |
代理配置元信息管理基类AOP |
AOP |
AopProxyFactory | 创建AOP代理的工厂 | |
ScopedObject | 用于范围对象的AOP接口 | |
DefaultScopedObject |
完成从spring中获取 | |
DelegatingIntroductionInterceptor | 委托引入拦截器 | |
3.RequestScope VS SessionScope
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
public class SessionScope extends AbstractRequestAttributesScope {
public String getConversationId() {
return RequestContextHolder.currentRequestAttributes().getSessionId();
}
@Override
public Object get(String name, ObjectFactory objectFactory) {
Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();
synchronized (mutex) {
return super .get(name, objectFactory);
}
}
@Override
public Object remove(String name) {
Object mutex = RequestContextHolder.currentRequestAttributes().getSessionMutex();
synchronized (mutex) {
return super .remove(name);
}
}
...
} |
or
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
public abstract class AbstractRequestAttributesScope implements Scope {
public Object get(String name, ObjectFactory objectFactory) {
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
Object scopedObject = attributes.getAttribute(name, getScope());
if (scopedObject == null ) {
scopedObject = objectFactory.getObject();
attributes.setAttribute(name, scopedObject, getScope());
}
return scopedObject;
}
public Object remove(String name) {
RequestAttributes attributes = RequestContextHolder.currentRequestAttributes();
Object scopedObject = attributes.getAttribute(name, getScope());
if (scopedObject != null ) {
attributes.removeAttribute(name, getScope());
return scopedObject;
}
else {
return null ;
}
}
...
}
|
本文转自 randy_shandong 51CTO博客,原文链接:http://blog.51cto.com/dba10g/1929157,如需转载请自行联系原作者