简介

ThreadLocal 是JDK包提供的,它提供线程本地变量,如果创建一个ThreadLocal变量,那么访问这个变量的每个线程都会有这个变量的副本,在实际多线程操作的时候,操作的都是自己本地内存中的变量,从而规避了线程安全问题。

使用

1
2
3
4
5

ThreadLocal tl = new ThreadLocal();
tl.set(k);
tl.get();
tl.remove();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}

ThreadLocalMap getMap(Thread t) {
return t.threadLocals;
}

void createMap(Thread t, T firstValue) {
t.threadLocals = new ThreadLocalMap(this, firstValue);
}

Thread.java

1
2
3
4
5
6
7
8
9
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;

/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

实现原理

Thread 类中有两个变量,一个threadLocals, 一个inheritableThreadLocals。

不支持继承性

InheritableThreadLocal

内存泄漏问题

refresh()

AbstractApplicationContext#refresh()

该方法是线程安全的方法,在startupShutdownMonitor的锁同步块中。

prepareRefresh()

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
33
34
35
36
37
38
39
40
/**
* Prepare this context for refreshing, setting its startup date and
* active flag as well as performing any initialization of property sources.
*/
protected void prepareRefresh() {
// Switch to active.
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);

if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}

// Initialize any placeholder property sources in the context environment.
initPropertySources();

// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();

// Store pre-refresh ApplicationListeners...
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}

// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
this.earlyApplicationEvents = new LinkedHashSet<>();
}

obtainFreshBeanFactory()

This implementation performs an actual refresh of this context’s underlying bean factory, shutting down the previous bean factory (if any) and initializing a fresh bean factory for the next phase of the context’s lifecycle.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
protected final void refreshBeanFactory() throws BeansException {
if (hasBeanFactory()) { //如果存在beanfactory, 则关闭
destroyBeans();
closeBeanFactory();
}
try {
//为上下文生命周期的下个阶段初始化一个新的beanfactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
//指定ID
beanFactory.setSerializationId(getId());
//设置是否允许被覆盖,是否允许循环引用
customizeBeanFactory(beanFactory);
//从Xml、Annotation、Groovy中读取Bean信息并注册。
loadBeanDefinitions(beanFactory);
//set the refrences to this.beanFactory.
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

prepareBeanFactory(beanFactory)

Prepare the bean facotry for use in this context.

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
/**
* Configure the factory's standard context characteristics,
* such as the context's ClassLoader and post-processors.
* @param beanFactory the BeanFactory to configure
*/
protected void prepareBeanFactory(ConfigurableListableBeanFactory beanFactory) {
// Tell the internal bean factory to use the context's class loader etc.
beanFactory.setBeanClassLoader(getClassLoader());
beanFactory.setBeanExpressionResolver(new StandardBeanExpressionResolver(beanFactory.getBeanClassLoader()));
beanFactory.addPropertyEditorRegistrar(new ResourceEditorRegistrar(this, getEnvironment()));

// Configure the bean factory with context callbacks.
beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));
beanFactory.ignoreDependencyInterface(EnvironmentAware.class);
beanFactory.ignoreDependencyInterface(EmbeddedValueResolverAware.class);
beanFactory.ignoreDependencyInterface(ResourceLoaderAware.class);
beanFactory.ignoreDependencyInterface(ApplicationEventPublisherAware.class);
beanFactory.ignoreDependencyInterface(MessageSourceAware.class);
beanFactory.ignoreDependencyInterface(ApplicationContextAware.class);

// BeanFactory interface not registered as resolvable type in a plain factory.
// MessageSource registered (and found for autowiring) as a bean.
beanFactory.registerResolvableDependency(BeanFactory.class, beanFactory);
beanFactory.registerResolvableDependency(ResourceLoader.class, this);
beanFactory.registerResolvableDependency(ApplicationEventPublisher.class, this);
beanFactory.registerResolvableDependency(ApplicationContext.class, this);

// Register early post-processor for detecting inner beans as ApplicationListeners.
beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));

// Detect a LoadTimeWeaver and prepare for weaving, if found.
if (beanFactory.containsBean(LOAD_TIME_WEAVER_BEAN_NAME)) {
beanFactory.addBeanPostProcessor(new LoadTimeWeaverAwareProcessor(beanFactory));
// Set a temporary ClassLoader for type matching.
beanFactory.setTempClassLoader(new ContextTypeMatchClassLoader(beanFactory.getBeanClassLoader()));
}

// Register default environment beans.
if (!beanFactory.containsLocalBean(ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(ENVIRONMENT_BEAN_NAME, getEnvironment());
}
if (!beanFactory.containsLocalBean(SYSTEM_PROPERTIES_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_PROPERTIES_BEAN_NAME, getEnvironment().getSystemProperties());
}
if (!beanFactory.containsLocalBean(SYSTEM_ENVIRONMENT_BEAN_NAME)) {
beanFactory.registerSingleton(SYSTEM_ENVIRONMENT_BEAN_NAME, getEnvironment().getSystemEnvironment());
}
}

postProcessBeanFactory(beanFactory)

Allows post-processing of the bean factory in context subclasses.

Modify the application context’s internal bean factory after its standard initialization.
All bean definitions will have bean loaded, but no beans have been instantiated yet.
This alllows for registering special BeanPostProcessors etc in certain Applicationcontext implementations.

invokeBeanFactoryPostProcessors(beanFactory);

invoke factory processors registered as beans in the creation.

Instantiate and invoke all registered BeanFactoryPostProcessor beans,
respecting explicit order if given. Must be called before singleton instantiation.

IOC 简史

  • 1983年,Richard E.Sweet 在<>提出好莱坞原则(“不要打电话给我,我会打电话给你”)。
  • 1988年,Rolph E.Johnson 和Brian Foote在《Designing Reusable Classes》中提出控制反转。
  • 1996年,Michael Mattson在《Object-Oriented Frameworks, A survey of methodological issues》将控制反转命名为好莱坞原则。
  • 2004,Martin Fowler在《Inversion Of Control Containers and the Dependency Injection pattern》提出自己对和IOC和DI的理解
  • 2005年,Martin Folower在《Inversion Of Control》中对IOC进一步说明。
  • Martin 大爷关于IOC的说明

IOC 的实现策略

WIKI:

In object-oriented programming, there are several basic techniques to implement inversion of control. there are:

  • Using a service locator pattern
  • Using dependency injection
    • constructor injection
    • parameter injection
    • setter injection
    • interface injection
  • Using a contextualized lookup.
  • Using template method design pattern
  • Using Strategy design pattern.

EXPERT ONE-ON-ONE J2EE DEVELOPMENT without EJB提到的策略: