001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright notice. All rights reserved.
003: */
004: package com.tcspring;
005:
006: import org.apache.commons.logging.Log;
007: import org.apache.commons.logging.LogFactory;
008: import org.springframework.beans.BeanWrapper;
009: import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
010: import org.springframework.beans.factory.support.AbstractBeanFactory;
011: import org.springframework.beans.factory.support.RootBeanDefinition;
012:
013: import com.tc.aspectwerkz.joinpoint.StaticJoinPoint;
014: import com.tc.object.bytecode.Manager;
015: import com.tc.object.bytecode.ManagerUtil;
016:
017: /**
018: * Virtualize <code>AbstractBeanFactory.getBean()</code>.
019: *
020: * @author Eugene Kuleshov
021: */
022: public class GetBeanProtocol {
023:
024: private final transient Log logger = LogFactory.getLog(getClass());
025:
026: private final transient ThreadLocal beanNameCflow = new ThreadLocal() {
027: protected Object initialValue() {
028: return new String[1];
029: }
030: };
031:
032: /**
033: * Invoked after constructor of the <code>AbstractBeanFactory</code>
034: *
035: * @see org.springframework.beans.factory.support.AbstractBeanFactory#AbstractBeanFactory()
036: *
037: * @deprecated This approach does not work because of Spring's handling of the circular dependencies
038: */
039: public void registerBeanPostProcessor(StaticJoinPoint jp,
040: AbstractBeanFactory factory) {
041: if (factory instanceof DistributableBeanFactory) {
042: factory
043: .addBeanPostProcessor(new DistributableBeanPostProcessor(
044: (DistributableBeanFactory) factory));
045: }
046: }
047:
048: /**
049: * Captures the name of the bean being created and makes it accessible to virtualizeSingletonBean()
050: * It also maintain the locking for distributed bean initialization.
051: *
052: * Invoked around <code>AbstractAutowireCapableBeanFactory.createBean(String, ..)</code> method.
053: *
054: * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(String, ...)
055: */
056: public Object beanNameCflow(StaticJoinPoint jp, String beanName,
057: AutowireCapableBeanFactory factory) throws Throwable {
058: String[] beanNameHolder = (String[]) beanNameCflow.get();
059: String previousBeanName = beanNameHolder[0];
060: beanNameHolder[0] = beanName;
061: try {
062: if (factory instanceof DistributableBeanFactory) {
063: DistributableBeanFactory distributableBeanFactory = (DistributableBeanFactory) factory;
064: if (distributableBeanFactory
065: .isDistributedSingleton(beanName)) {
066: logger.info(distributableBeanFactory.getId()
067: + " distributed lock for bean " + beanName);
068: String lockId = "@spring_context_"
069: + ((DistributableBeanFactory) factory)
070: .getId() + "_" + beanName;
071: ManagerUtil.beginLock(lockId,
072: Manager.LOCK_TYPE_WRITE);
073: try {
074: return jp.proceed();
075: } finally {
076: ManagerUtil.commitLock(lockId);
077: }
078: }
079: }
080: return jp.proceed();
081:
082: } finally {
083: beanNameHolder[0] = previousBeanName;
084: }
085: }
086:
087: /**
088: * Virtualize singleton bean.
089: *
090: * Invoked around call to <code>BeanWrapper.getWrappedInstance()</code> method within
091: * <code>AbstractAutowireCapableBeanFactory.createBean(String, ..)</code> method execution.
092: *
093: * @see GetBeanProtocol#beanNameCflow(StaticJoinPoint, String, AutowireCapableBeanFactory)
094: * @see org.springframework.beans.BeanWrapper#getWrappedInstance()
095: * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(String, ..)
096: */
097: public Object virtualizeSingletonBean(StaticJoinPoint jp,
098: AutowireCapableBeanFactory beanFactory) throws Throwable {
099: Object localBean = jp.proceed();
100:
101: if (beanFactory instanceof DistributableBeanFactory) {
102: DistributableBeanFactory distributableBeanFactory = (DistributableBeanFactory) beanFactory;
103: String beanName = ((String[]) beanNameCflow.get())[0];
104: if (distributableBeanFactory
105: .isDistributedSingleton(beanName)) {
106: ComplexBeanId beanId = new ComplexBeanId(beanName);
107: BeanContainer container = distributableBeanFactory
108: .getBeanContainer(beanId);
109: if (container != null) {
110: logger
111: .info(distributableBeanFactory.getId()
112: + " virtualizing existing bean "
113: + beanName);
114: return container.getBean();
115: }
116: logger.info(distributableBeanFactory.getId()
117: + " virtualizing new bean " + beanName);
118: distributableBeanFactory.putBeanContainer(beanId,
119: new BeanContainer(localBean, true));
120: }
121: }
122:
123: return localBean;
124: }
125:
126: /**
127: * Initialize singleton bean.
128: *
129: * Invoked after call to <code>AbstractAutowireCapableBeanFactory.populateBean(..)</code> method
130: * within execution of <code>AbstractAutowireCapableBeanFactory.createBean(String, ..))</code>
131: *
132: * @see GetBeanProtocol#beanNameCflow(StaticJoinPoint, String, AutowireCapableBeanFactory)
133: * @see GetBeanProtocol#virtualizeSingletonBean(StaticJoinPoint, AutowireCapableBeanFactory)
134: * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#createBean(String, ..)
135: * @see org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean(..)
136: */
137: public void initializeSingletonBean(String beanName,
138: RootBeanDefinition mergedBeanDefinition,
139: BeanWrapper instanceWrapper,
140: AutowireCapableBeanFactory beanFactory) {
141: if (beanFactory instanceof DistributableBeanFactory) {
142: DistributableBeanFactory distributableBeanFactory = (DistributableBeanFactory) beanFactory;
143: if (distributableBeanFactory
144: .isDistributedSingleton(beanName)) {
145: ComplexBeanId beanId = new ComplexBeanId(beanName);
146: BeanContainer container = distributableBeanFactory
147: .getBeanContainer(beanId);
148: if (container != null && !container.isInitialized()) {
149: Object localInstance = instanceWrapper
150: .getWrappedInstance();
151: distributableBeanFactory.initializeBean(beanId,
152: localInstance, container);
153: }
154: }
155: }
156: }
157:
158: }
|