spring(十五)---------BeanPostProcessor之spring中各种现象的解释

1、现象一:实现了BeanFactoryPostProcessor的类无法解析@Autowired、@PostConstruct,但可以执行InitializingBean接口的实现方法afterPropertiesSet。

@Component
public class TestBeanFactoryPostProcessor implements BeanFactoryPostProcessor, InitializingBean {

//无法注入
	@Autowired
	BeanPostProcessorService beanPostProcessorService;

//无法执行
	@PostConstruct
	public void postConstruct(){
		log.debug("TestBeanFactoryPostProcessor PostConstruct init");
	}

//可以执行
	@Override
	public void afterPropertiesSet() throws Exception {
		log.debug("TestBeanFactoryPostProcessor InitializingBean init");
	}

//可以执行
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
		log.debug("TestBeanFactoryPostProcessor beanPostProcessorService[{}]",beanPostProcessorService);
	}


}

2、现象二:两个类都实现了BeanPostProcessor,一个在其中注入一个普通bean,一个在后置处理器中获取该bean并修改其属性值,此时后者的后置方法无法获取到这个bean。(@Autowired、@PostConstruct可以生效,且可以执行InitializingBean接口的实现方法afterPropertiesSet)

普通bean:

@Component("a")
public class BeanPostProcessorService {

	String str;
	Integer i;
	public BeanPostProcessorService(){
		log.debug("==BeanPostProcessorService create");
	}
	public Integer getI() {
		return i;
	}
	public String getStr() {
		return str;
	}
	public void testAop(){
		log.debug("--------BeanPostProcessorService logic-----");

	}

}

第一个实现了BeanPostProcessor的类,注入了这个bean(能够成功注入进来),且    @PostConstruct可以生效,InitializingBean 的after方法也可以生效

@Component
public class TestBeanPostProcessorNormal implements BeanPostProcessor, InitializingBean {

	@PostConstruct
	public void postConstruct(){
		log.debug("TestBeanPostProcessorNormal PostConstruct init");
	}

	@Autowired
	BeanPostProcessorService beanPostProcessorService;

	public TestBeanPostProcessorNormal(){
		log.debug("==TestBeanPostProcessorNormal create");
	}

	public void printfInfo(){
		log.debug("TestBeanPostProcessorNormal beanPostProcessorService[{}]",beanPostProcessorService);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		log.debug("TestBeanPostProcessorNormal InitializingBean init");
	}
}

第二个类实现了BeanPostProcessor,并在后置方法中获取该bean,此时后置方法无法执行

@Component
public class TestBeanPostProcessorNormalUpdatePorperties implements BeanPostProcessor {

	public TestBeanPostProcessorNormalUpdatePorperties(){
		log.debug("==TestBeanPostProcessorNormalUpdatePorperties create");
	}

	@SneakyThrows
	@Override
	public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException{
		if(beanName.equals("a")) {
			Class<?> aClass = bean.getClass();
			Field[] fs = aClass.getDeclaredFields();
			for (Field f : fs) {
				if(f.getName().equals("str")){
					f.setAccessible(true);
					f.set(bean,"spring");
				}
			}
			return bean;
		}
		return null;
	}
}

此时发现第二个类的后置方法无法执行

3、现象三:在现象二的基础上,将类一的注入注释掉,此时第二个类的后置方法则可以获取到该bean

@Component
public class TestBeanPostProcessorNormal implements BeanPostProcessor, InitializingBean {

	@PostConstruct
	public void postConstruct(){
		log.debug("TestBeanPostProcessorNormal PostConstruct init");
	}

	//@Autowired
	//BeanPostProcessorService beanPostProcessorService;

	public TestBeanPostProcessorNormal(){
		log.debug("==TestBeanPostProcessorNormal create");
	}

	public void printfInfo(){
		log.debug("TestBeanPostProcessorNormal beanPostProcessorService[{}]",beanPostProcessorService);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		log.debug("TestBeanPostProcessorNormal InitializingBean init");
	}
}

4、现象四:一个类实现了BeanPostProcessor和Ordered接口,此时@Autowired、@PostConstruct,InitializingBean都可以生效

但如果实现了BeanPostProcessor和PriorityOrdered,此时@Autowired、@PostConstruct无法生效,InitializingBean可以生效

5、现象5:一个类实现了BeanPostProcessor,或者实现了BeanPostProcessor+Ordered,

此时如果注入了一个bean,该bean是需要进行aop代理,此时会打印一个警告信息-------该bean是一个校验不合格的bean,也就是该bean没有执行完所有的BeanPostProcessor。

(我们知道bena的生命周期初始化前后会执行自己实现的BeanPostProcessor接口的前后置方法,而每个bean的生命周期可以执行多个BeanPostProcessor(spring容器中会有一个List存放所有BeanPostProcessor))

具体看:Bean生命周期和九次调用BeanPostProcessor都做了什么事情_bean的生命周期每个阶段都可以调用beanpostprocessor吗_小小程序猿ccc的博客-CSDN博客

我们自己实现了的BeanPostProcessor只是在bean初始化前后调用,而其他spring中存在的BeanPostProcessor会在不同时期进行调用。

这里的警告就是该bean没有执行完所有的BeanPostProcessor,可能不是一个程序员想要的bean。

6、现象6:在现象5的基础上,实现了BeanPostProcessor+Ordered的类注入一个需要被aop代理的bean,此时不仅会打印警告信息,这个bean的aop还会失效

7、现象7:实现了BeanPostProcessor的类中注入需要aop代理的bean,此时该bean的aop不会失效

8:现象8:实现了BeanPostProcessor+PriorityOrdered的类注入需要aop代理的bean,此时该bean的aop不会失效。

==============================================

一、

registerBeanPostProcessors方法

refresh方法中,我们讲了invokeBeanFactoryPostProcessors方法(具体什么作用看前面的文章),现在我们要解释上面说得的哪些现象,需要看refresh方法里面的registerBeanPostProcessors方法:

顾名思义,这个方法的大概作用是注册BeanPostProcessors。

其实早在invokeBeanFactoryPostProcessors方法之前,

prepareBeanFactory就先添加了一个BeanPostProcessor:
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.
		//添加一个回调实现了ApplicationContextAwareaware的BeanPostProcessor
		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);

        //省略部分代码。。。。。。。。。。。。
        //添加一个处理事件的BeanPostProcessor
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(this));
}

在bean生命周期的某步,就会去调用这个BeanPostProcessor进行回调aware接口:

 而spring用一个List来存储这些BeanPostProcessor。(spring自身或第三方的BeanPostProcessor都会放到这个list中)

在执行invokeBeanFactoryPostProcessors方法时,在执行ConfigurationClassPostProcessor的方法postProcessBeanFactory时,也添加了一个:

 这个BeanPostProcessor为了在加了@Confuration注解时,cglib会进行代理时使用的(可以去看前面的文章,这个就是给cglib代理时的创建的BeanFactory赋值的)

容器实例化时也会注册一些BeanPostProcessor:

容器构造方法--》AnnotatedBeanDefinitionReader构造方法--》

AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
//注册AutowiredAnnotationBeanPostProcessor,用来处理@Autowired注解
		if (!registry.containsBeanDefinition(AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME)) {
//将BeanPostProcessor转为BeanDefinition,然后put到BeanDefinitionMap中			
RootBeanDefinition def = new RootBeanDefinition(AutowiredAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, AUTOWIRED_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		//注册CommonAnnotationBeanPostProcessor,用来处理@Resource注解+@Postcustrud注解
		// Check for JSR-250 support, and if present add the CommonAnnotationBeanPostProcessor.
		if (jsr250Present && !registry.containsBeanDefinition(COMMON_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition(CommonAnnotationBeanPostProcessor.class);
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, COMMON_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

		//注册了一个用来处理JPA的
		// Check for JPA support, and if present add the PersistenceAnnotationBeanPostProcessor.
		if (jpaPresent && !registry.containsBeanDefinition(PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME)) {
			RootBeanDefinition def = new RootBeanDefinition();
			try {
				def.setBeanClass(ClassUtils.forName(PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME,
						AnnotationConfigUtils.class.getClassLoader()));
			}
			catch (ClassNotFoundException ex) {
				throw new IllegalStateException(
						"Cannot load optional framework class: " + PERSISTENCE_ANNOTATION_PROCESSOR_CLASS_NAME, ex);
			}
			def.setSource(source);
			beanDefs.add(registerPostProcessor(registry, def, PERSISTENCE_ANNOTATION_PROCESSOR_BEAN_NAME));
		}

这里又注册了三个。

我们可以看看这个registerPostProcessor方法怎么注册的:

private static BeanDefinitionHolder registerPostProcessor(
			BeanDefinitionRegistry registry, RootBeanDefinition definition, String beanName) {

		definition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
		//注册这个BeanPostProcessor到BeanDefinitionMap中
		registry.registerBeanDefinition(beanName, definition);
		return new BeanDefinitionHolder(definition, beanName);
	}

(注意:注册和add不一样,注册是将BeanPostProcessor转化为BeanDefinition然后put到BeanDefinitionMap中,而我们上面讲的add是直接实例化后放进容器的List中)

注意:这个List<BeanPostProcessor> 的BeanPostProcessor对象来源主要有两个:

1)、spring中自己将BeanPostProcessor add进行(就是我们上面说的)

2)、通过getBean方法,将BeanDefinitionMap中的BeanPostProcessor类型的BeanDefinition实例化为Bean放进来(就是讲上面注册的BeanPostProcessor实例化为bean后放进来)

最后bean的生命周期中会去调用这个list中的BeanPostProcessor。

由于我们要演示上面的aop失效问题,所以会使用到@EnableAspectJAutoProxy开启aop

这里也会注册一个BeanPostProcessor

其他我们先不看了,这里的7个有3个进行了add到list中,却没有调用去调registerBeanPostProcessor方法进行注册。

此时的BeanDefinitionMap大概是由这么几个BeanPostProcessor(我们只讨论这7个,其他都不讨论)(由于我们这里没有JPA环境,所以第三个JPA相关的BeanPostProcessor也不存在,所以就只讨论6个)



所以在refresh-》 registerBeanPostProcessors(beanFactory);则是将容器中还没注册的BeanPostProcessor进行注册(即将List中的BeanPostProcessor进行注册)

此时我们开始进入registerBeanPostProcessors方法看是怎么进行注册的,注册流程是怎么样的?

入口:refresh--》registerBeanPostProcessors--》

PostProcessorRegistrationDelegate.registerBeanPostProcessors()

(注意:这个方法是将BeanDefinitionMap中的BeanPostProcessor实例化为bean并放进List<BeanPostProcessor>中去)

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		//从BeanDefinitionMap中获取所有的BeanPostProcessor
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		//beanProcessorTargetCount--->spring期望一个bean要执行几个BeanPostProcessor
		//beanFactory.getBeanPostProcessorCount()--->获取容器中List<BeanPostProcessor>的元素个数
		//beanProcessorTargetCount = list.size() + 1 + map.size()
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		//又往list中放进一个BeanPostProcessor(检查list中BeanPostProcessor的个数和预期的是否相等,上面的1就是指这个BeanPostProcessorChecker)
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

//省略部分代码。。。。。
}

这里可以看到,又往List中加入一个BeanPostProcessor,这个BeanPostProcessor很重要,可以解释我们,之前的一些现象。

我们进入这个BeanPostProcessorChecker:

	public BeanPostProcessorChecker(ConfigurableListableBeanFactory beanFactory, int beanPostProcessorTargetCount) {
			this.beanFactory = beanFactory;
			this.beanPostProcessorTargetCount = beanPostProcessorTargetCount;
		}

		@Override
		public Object postProcessBeforeInitialization(Object bean, String beanName) {
			return bean;
		}

		@Override
		public Object postProcessAfterInitialization(Object bean, String beanName) {
			//如果预期值和真实在List中的数量不一致则打印这个警告信息
			if (!(bean instanceof BeanPostProcessor) && !isInfrastructureBean(beanName) &&
					this.beanFactory.getBeanPostProcessorCount() < this.beanPostProcessorTargetCount) {
				if (logger.isInfoEnabled()) {
					logger.info("Bean '" + beanName + "' of type [" + bean.getClass().getName() +
							"] is not eligible for getting processed by all BeanPostProcessors " +
							"(for example: not eligible for auto-proxying)");
				}
			}
			return bean;
		}

可以看到这里在被调用时,会对预期值与真实的List中的进行对比,如果不同则打印警告信息。

我们现在开始解释下现象二:

第一个类中注入了一个普通bean,第二个类则无法调用到后置方法。

我们知道spring扫描的时候会将这两个类先放到BeanDefinitionMap中,所以在执行registerBeanPostProcessors方法时预期值为2+1(我们此时假设只有这两个类+List中的BeanPostProcessorChecker),我们知道refresh---》finishBeanFactoryInitialization中每个bean的生命周期都会去调用所有List中的BeanPostProcessor。

1)、此时第一个类的因为注入了一个普通bean-》BeanPostProcessorService ,bean的生命周期中需要先进行属性注入后才会初始化为bean,这样才能将其放进List<BeanPostProcessor>中,而此时因为注入了一个普通bean,所以需要先让BeanPostProcessorService 走完生命周期。

2)、BeanPostProcessorService 开始走他自己的生命周期,走到finishBeanFactoryInitialization中会去调用所有List中的BeanPostProcessor,此时就会调用到BeanPostProcessorChecker的后置方法,这是就开始检查预期值2+1是不是等于List中的数量,因为此时第一个类还在BeanDefinitionMap中,还卡在属性注入的过程,所以还没实例化成bean放进List中(此时的List中只有BeanPostProcessorChecker),所以导致打印警告信息+后续的BeanPostProcess的后置处方法不会执行。

总结下就是,本来普通bean BeanPostProcessorService的生命周期应该refresh-》finishBeanFactoryInitialization方法中完成的,可是因为被实现了BeanPostProcessor的类依赖(需要注入),导致其生命周期提前需要完成(在没完全完执行registerBeanPostProcessors方法(有些BeanPostProcessor还在Map中,还没被实例化为bean放进list中)就开始执行list中的所有BeanPostProcessor),所以会打印警告+有些BeanPostProcessor的后置方法无法执行

这里有个疑问,这里的第二个类TestBeanPostProcessorNormalUpdatePorperties,为什么不能先于第一个类实例化为bean,先放进list中?这样第一个类卡住的时候,BeanPostProcessorService走生命周期虽然还会打印警告,但不是还可以执行第二个类的后置处理方法?

---------------------------------------

第一现象:实现了BeanFactoryPostProcessor的类无法解析@Autowired、@PostConstruct,但可以执行InitializingBean接口的实现方法afterPropertiesSet。

我们在前面就提及,在执行registerBeanPostProcessors方法前(也是invokeBeanFactoryPostProcessors方法之前),解析@Autowired、@Postconstrct的BeanPostProcessor就已经被放到BeanDefinitionMap中了,但还没有实例化为Bean放进List中。而BeanFactoryPostProcessor被实例化为bean是在invokeBeanFactoryPostProcessors方法中就执行的,此时在走实现了BeanFactoryPostProcessor生命周期的时候,就不会执行到解析@Autowired、@Postconstrct的BeanPostProcessor,所以就导致了无法注入的效果(也就是实例化的时候解析@Autowired、@Postconstrct的BeanPostProcessor还没实例化为bean放进list中)

这里提个问题,为什么上面现象二的第一个类在实例化的时候就具备有了@Autowired的能力?

(因为解析@Autowired的BeanPostProcessor先于我们自定义的BeanPostProcessor被实例化,所以就有了@Autowired的能力)

--------------------------------------------------------

第三现象:即第二种现象不注入普通bean了,此时后置处理方法可以生效了

普通bean-》BeanPostProcessorService不被BeanPostProcessor依赖注入了,此时就会等到所以BeanPostProcessor都实例化完放进list才会进行自己的生命周期,所以就不会部分后置处理器无法执行的情况了。

--------------------------------------------------------------

现象四:一个类实现了BeanPostProcessor和Ordered接口,此时@Autowired、@PostConstruct,InitializingBean都可以生效

---因为解析@Autowired等的BeanPostProcessor先于我们自定义的BeanPostProcessor+实现了Ordered接口被实例化,所以就有了@Autowired等的能力

但如果实现了BeanPostProcessor和PriorityOrdered,此时@Autowired、@PostConstruct无法生效,InitializingBean可以生效

---因为解析@Autowired等的BeanPostProcessor慢于我们自定义的BeanPostProcessor+实现了PriorityOrdered接口被实例化,所以就无法具备@Autowired等的能力

现象四基本就是BeanPostProcessor实例化优先级的问题

-----------------------------------------------------------

现象五:一个类实现了BeanPostProcessor,或者实现了BeanPostProcessor+Ordered,

此时如果注入了一个bean,该bean是需要进行aop代理,此时会打印一个警告信息-------该bean是一个校验不合格的bean,也就是该bean没有执行完所有的BeanPostProcessor。

------aop对应的BeanPostProcessor实例化优先级低于实现了BeanPostProcessor+Ordered,所以就会打印警告

----------------------------------------------------------

6、现象6:实现了BeanPostProcessor+Ordered的类注入一个需要被aop代理的bean,此时不仅会打印警告信息,这个bean的aop还会失效

-----------原因和现象五一样,aop对应的BeanPostProcessor实例化优先级低于实现了BeanPostProcessor+Ordered,所以被注入的bean(进行了aop代理)就会出现在aop对应的beanPostProcessor没实例化时就执行生命周期的回调BeanPostProcessor流程,所以最好导致bean的aop失效的情况

------------------------------

7、现象7:实现了BeanPostProcessor的类中注入需要aop代理的bean,此时该bean的aop不会失效

-----aop对应的BeanPostProcessor实例化优先级快于没有实现Ordered的

-------------------------------

8:现象8:实现了BeanPostProcessor+PriorityOrdered的类注入需要aop代理的bean,此时该bean的aop不会失效。

-----aop对应的BeanPostProcessor实例化优先级快于实现PriorityOrdered的

所以我们可以总结下各个种类的BeanPostProcessor的实例化时机:

spring内置添加的》自定义的BeanPostProcessor+实现了PriorityOrdered接口》解析@Autowired等的BeanPostProcessor》自定义的BeanPostProcessor+实现了Ordered接口》aop对应的BeanPostProcessor》自定义的BeanPostProcessor

(其中解析@Autowired的又优先于解析@Resource、@Postconstrct的)

所以可以知道PriorityOrdered、Ordered可以提升BeanPostProcessor被实例化的优先级。我们从源码也可以看到:

	public static void registerBeanPostProcessors(
			ConfigurableListableBeanFactory beanFactory, AbstractApplicationContext applicationContext) {

		//从BeanDefinitionMap中获取所有的BeanPostProcessor
		String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class, true, false);

		// Register BeanPostProcessorChecker that logs an info message when
		// a bean is created during BeanPostProcessor instantiation, i.e. when
		// a bean is not eligible for getting processed by all BeanPostProcessors.
		//beanProcessorTargetCount--->spring期望一个bean要执行几个BeanPostProcessor
		//beanFactory.getBeanPostProcessorCount()--->获取容器中List<BeanPostProcessor>的元素个数
		//beanProcessorTargetCount = list.size() + 1 + map.size()
		int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
		//又往list中放进一个BeanPostProcessor(检查list中BeanPostProcessor的个数和预期的是否相等,上面的1就是指这个BeanPostProcessorChecker)
		beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));

		// Separate between BeanPostProcessors that implement PriorityOrdered,
		// Ordered, and the rest.
		//存放实现了priorityOrdered接口的BeanPostProcessor
		List<BeanPostProcessor> priorityOrderedPostProcessors = new ArrayList<>();
		//存放了内部的BeanPostProcessor
		List<BeanPostProcessor> internalPostProcessors = new ArrayList<>();
		//存放实现了Ordered接口的BeanPostProcessor
		List<String> orderedPostProcessorNames = new ArrayList<>();
		//其他普通的BeanPostProcessor
		List<String> nonOrderedPostProcessorNames = new ArrayList<>();
		for (String ppName : postProcessorNames) {
			if (beanFactory.isTypeMatch(ppName, PriorityOrdered.class)) {
				//如果实现了priorityOrdered接口,则进行实例化为bean,
				// (这里不会调用CheckBeanPostProcessor,因为checkBeanPostProcessor只用于非BeanPostProcessor类型的bean
				//然后加入到priorityOrderedPostProcessors集合中
				BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
				priorityOrderedPostProcessors.add(pp);
				if (pp instanceof MergedBeanDefinitionPostProcessor) {
					internalPostProcessors.add(pp);
				}
			}
			else if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
				//如果实现了Ordered接口,先不进行实例化,放进orderedPostProcessorNames集合
				orderedPostProcessorNames.add(ppName);
			}
			else {
				//其他的也放进集合
				nonOrderedPostProcessorNames.add(ppName);
			}
		}

		// First, register the BeanPostProcessors that implement PriorityOrdered.
		//注册实现了PriorityOrdered的BeanPostProcessors到容器的List<BeanPostProcessor>中去
		sortPostProcessors(priorityOrderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);

		// Next, register the BeanPostProcessors that implement Ordered.
		List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>(orderedPostProcessorNames.size());
		for (String ppName : orderedPostProcessorNames) {
			//实例化实现了Ordered接口BeanPostProcessor
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			orderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		//注册实现了Ordered的BeanPostProcessors到容器的List<BeanPostProcessor>中去
		sortPostProcessors(orderedPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, orderedPostProcessors);

		// Now, register all regular BeanPostProcessors.
		List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>(nonOrderedPostProcessorNames.size());
		for (String ppName : nonOrderedPostProcessorNames) {
			//实例化其他普通的BeanPostProcessor
			BeanPostProcessor pp = beanFactory.getBean(ppName, BeanPostProcessor.class);
			nonOrderedPostProcessors.add(pp);
			if (pp instanceof MergedBeanDefinitionPostProcessor) {
				internalPostProcessors.add(pp);
			}
		}
		registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);

		//注册到List中
		// Finally, re-register all internal BeanPostProcessors.
		sortPostProcessors(internalPostProcessors, beanFactory);
		registerBeanPostProcessors(beanFactory, internalPostProcessors);

		// Re-register post-processor for detecting inner beans as ApplicationListeners,
		// moving it to the end of the processor chain (for picking up proxies etc).
		beanFactory.addBeanPostProcessor(new ApplicationListenerDetector(applicationContext));
	}

aaa

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1. 简介 1.1. 概览 1.2. 使用场景 2. Spring 2.0 的新特性 2.1. 简介 2.2. 控制反转(IoC)容器 2.2.1. 更简单的XML配置 2.2.2. 新的bean作用域 2.2.3. 可扩展的XML编写 2.3. 面向切面编程(AOP) 2.3.1. 更加简单的AOP XML配置 2.3.2. 对@AspectJ 切面的支持 2.4. 间层 2.4.1. 在XML里更为简单的声明性事务配置 2.4.2. JPA 2.4.3. 异步的JMS 2.4.4. JDBC 2.5. Web层 2.5.1. Spring MVC的表单标签库 2.5.2. Spring MVC合理的默认值 2.5.3. Portlet 框架 2.6. 其他特性 2.6.1. 动态语言支持 2.6.2. JMX 2.6 .3. 任务规划 2.6.4. 对Java 5(Tiger)的支持 2.7. 移植到Spring 2.0 2.7.1. 一些变化 2.7.1.1. Jar包 2.7.1.2. XML配置 2.7.1.3. Deprecated的类和方法 2.7.1.4. Apache OJB 2.7.1.5. iBatis 2.8. 更新的样例应用 2.9. 改进的文档 I. 核心技术 3. 控制反转容器 3.1. 简介 3.2. 容器和bean的基本原理 3.2.1. 容器 3.2.1.1. 配置元数据 3.2.2. 实例化容器 3.2.2.1. 组成基于XML配置元数据 3.2.3. 多种bean 3.2.3.1. 命名bean 3.2.3.2. 实例化bean 3.2.4. 使用容器 3.3. 依赖 3.3.1. 注入依赖 3.3.1.1. Setter注入 3.3.1.2. 构造器注入 3.3.1.3. 一些例子 3.3.2. 构造器参数的解析 3.3.2.1. 构造器参数类型匹配 3.3.2.2. 构造器参数的索引 3.3.3. bean属性及构造器参数详解 3.3.3.1. 直接量(基本类型、Strings类型等。) 3.3.3.2. 引用其它的bean(协作者) 3.3.3.3. 内部bean 3.3.3.4. 集合 3.3.3.5. Nulls 3.3.3.6. XML-based configuration metadata shortcuts 3.3.3.7. 组合属性名称 3.3.4. 使用depends-on 3.3.5. 延迟初始化bean 3.3.6. 自动装配(autowire)协作者 3.3.6.1. 设置Bean使自动装配失效 3.3.7. 依赖检查 3.3.8. 方法注入 3.3.8.1. Lookup方法注入 3.3.8.2. 自定义方法的替代方案 3.4. bean的作用域 3.4.1. Singleton作用域 3.4.2. Prototype作用域 3.4.3. 其他作用域 3.4.3.1. 初始化web配置 3.4.3.2. Request作用域 3.4.3.3. Session作用域 3.4.3.4. global session作用域 3.4.3.5. 作用域bean与依赖 3.4.4. 自定义作用域 3.5. 定制bean特性 3.5.1. Lifecycle接口 3.5.1.1. 初始化回调 3.5.1.2. 析构回调 3.5.2. 了解自己 3.5.2.1. BeanFactoryAware 3.5.2.2. BeanNameAware 3.6. bean定义的继承 3.7. 容器扩展点 3.7.1. 用BeanPostProcessor定制bean 3.7.1.1. 使用BeanPostProcessor的Hello World示例 3.7.1.2. RequiredAnnotationBeanPostProcessor示例 3.7.2. 用BeanFactoryPostProcessor定制配置元数据 3.7.2.1. PropertyPlaceholderConfigurer示例 3.7.2.2. PropertyOverrideConfigurer示例 3.7.3. 使用FactoryBean定制实例化逻辑 3.8. ApplicationContext 3.8.1. 利用MessageSource实现国际化 3.8.2. 事件 3.8.3. 底层资源的访问 3.8.4. ApplicationContext在WEB应用的实例化 3.9. 粘合代码和可怕的singleton 3.9.1. 使用Singleton-helper类 4. 资源 4.1. 简介 4.2. Resource 接口 4.3. 内置 Resource 实现 4.3.1. UrlResource 4.3.2. ClassPathResource 4.3.3. FileSystemResource 4.3.4. ServletContextResource 4.3.5. InputStreamResource 4.3.6. ByteArrayResource 4.4. ResourceLoader 4.5. ResourceLoaderAware 接口 4.6. 把Resource作为属性来配置 4.7. Application context 和Resource 路径 4.7.1. 构造application context 4.7.1.1. 创建 ClassPathXmlApplicationContext 实例 - 简介 4.7.2. Application context构造器资源路径的通配符 4.7.2.1. Ant风格的pattern 4.7.2.2. classpath*: 前缀 4.7.2.3. 其他关于通配符的说明 4.7.3. FileSystemResource 提示 5. 校验,数据绑定,BeanWrapper,与属性编辑器 5.1. 简介 5.2. 使用Spring的Validator接口进行校验 5.3. 从错误代码到错误信息 5.4. Bean处理和BeanWrapper 5.4.1. 设置和获取属性值以及嵌套属性 5.4.2. 内建的PropertyEditor实现 5.4.2.1. 注册用户自定义的PropertyEditor 6. 使用Spring进行面向切面编程(AOP) 6.1. 简介 6.1.1. AOP概念 6.1.2. Spring AOP的功能和目标 6.1.3. Spring的AOP代理 6.2. @AspectJ支持 6.2.1. 启用@AspectJ支持 6.2.2. 声明一个切面 6.2.3. 声明一个切入点(pointcut) 6.2.3.1. 切入点指定者的支持 6.2.3.2. 合并切入点表达式 6.2.3.3. 共享常见的切入点(pointcut)定义 6.2.3.4. 示例 6.2.4. 声明通知 6.2.4.1. 前置通知(Before advice) 6.2.4.2. 返回后通知(After returning advice) 6.2.4.3. 抛出后通知(After throwing advice) 6.2.4.4. 后通知(After (finally) advice) 6.2.4.5. 环绕通知(Around Advice) 6.2.4.6. 通知参数(Advice parameters) 6.2.4.7. 通知(Advice)顺序 6.2.5. 引入(Introductions) 6.2.6. 切面实例化模型 6.2.7. 例子 6.3. Schema-based AOP support 6.3.1. 声明一个切面 6.3.2. 声明一个切入点 6.3.3. 声明通知 6.3.3.1. 通知(Advice) 6.3.3.2. 返回后通知(After returning advice) 6.3.3.3. 抛出异常后通知(After throwing advice) 6.3.3.4. 后通知(After (finally) advice) 6.3.3.5. 通知 6.3.3.6. 通知参数 6.3.3.7. 通知顺序 6.3.4. 引入 6.3.5. 切面实例化模型 6.3.6. Advisors 6.3.7. 例子 6.4. AOP声明风格的选择 6.4.1. Spring AOP还是完全用AspectJ? 6.4.2. Spring AOP使用@AspectJ还是XML? 6.5. 混合切面类型 6.6. 代理机制 6.7. 编程方式创建@AspectJ代理 6.8. 在Spring应用使用AspectJ 6.8.1. 在Spring使用AspectJ来为domain object进行依赖注入 6.8.1.1. @Configurable object的单元测试 6.8.1.2. 多application context情况下的处理 6.8.2. Spring其他的AspectJ切面 6.8.3. 使用Spring IoC来配置AspectJ的切面 6.8.4. 在Spring应用使用AspectJ Load-time weaving(LTW) 6.9. 其它资源 7. Spring AOP APIs 7.1. 简介 7.2. Spring的切入点API 7.2.1. 概念 7.2.2. 切入点实施 7.2.3. AspectJ切入点表达式 7.2.4. 便利的切入点实现 7.2.4.1. 静态切入点 7.2.4.2. 动态切入点 7.2.5. 切入点的基类 7.2.6. 自定义切入点 7.3. Spring的通知API 7.3.1. 通知的生命周期 7.3.2. Spring里的通知类型 7.3.2.1. 拦截around通知 7.3.2.2. 前置通知 7.3.2.3. 异常通知 7.3.2.4. 后置通知 7.3.2.5. 引入通知 7.4. Spring里的advisor(Advisor) API 7.5. 使用ProxyFactoryBean创建AOP代理 7.5.1. 基础 7.5.2. JavaBean属性 7.5.3. 基于JDK和CGLIB的代理 7.5.4. 对接口进行代理 7.5.5. 对类进行代理 7.5.6. 使用“全局”advisor 7.6. 简化代理定义 7.7. 使用ProxyFactory通过编程创建AOP代理 7.8. 操作被通知对象 7.9. 使用“自动代理(autoproxy)”功能 7.9.1. 自动代理bean定义 7.9.1.1. BeanNameAutoProxyCreator 7.9.1.2. DefaultAdvisorAutoProxyCreator 7.9.1.3. AbstractAdvisorAutoProxyCreator 7.9.2. 使用元数据驱动的自动代理 7.10. 使用TargetSources 7.10.1. 热交换目标源 7.10.2. 池化目标源 7.10.3. 原型目标源 7.10.4. ThreadLocal目标源 7.11. 定义新的通知类型 7.12. 更多资源 8. 测试 8.1. 简介 8.2. 单元测试 8.3. 集成测试 8.3.1. Context管理和缓存 8.3.2. 测试fixture的依赖注入 8.3.3. 事务管理 8.3.4. 方便的变量 8.3.5. 示例 8.3.6. 运行集成测试 8.4. 更多资源 II. 间层数据访问 9. 事务管理 9.1. 简介 9.2. 动机 9.3. 关键抽象 9.4. 使用资源同步的事务 9.4.1. 高层次方案 9.4.2. 低层次方案 9.4.3. TransactionAwareDataSourceProxy 9.5. 声明式事务管理 9.5.1. 理解Spring的声明式事务管理实现 9.5.2. 第一个例子 9.5.3. 回滚 9.5.4. 为不同的bean配置不同的事务语义 9.5.5. <tx:advice/> 有关的设置 9.5.6. 使用 @Transactional 9.5.6.1. @Transactional 有关的设置 9.5.7. 插入事务操作 9.5.8. 结合AspectJ使用 @Transactional 9.6. 编程式事务管理 9.6.1. 使用 TransactionTemplate 9.6.2. 使用 PlatformTransactionManager 9.7. 选择编程式事务管理还是声明式事务管理 9.8. 与特定应用服务器集成 9.8.1. BEA WebLogic 9.8.2. IBM WebSphere 9.9. 公共问题的解决方案 9.9.1. 对一个特定的 DataSource 使用错误的事务管理器 9.10. 更多的资源 10. DAO支持 10.1. 简介 10.2. 一致的异常层次 10.3. 一致的DAO支持抽象类 11. 使用JDBC进行数据访问 11.1. 简介 11.1.1. Spring JDBC包结构 11.2. 利用JDBC核心类实现JDBC的基本操作和错误处理 11.2.1. JdbcTemplate类 11.2.2. NamedParameterJdbcTemplate类 11.2.3. SimpleJdbcTemplate类 11.2.4. DataSource接口 11.2.5. SQLExceptionTranslator接口 11.2.6. 执行SQL语句 11.2.7. 执行查询 11.2.8. 更新数据库 11.3. 控制数据库连接 11.3.1. DataSourceUtils类 11.3.2. SmartDataSource接口 11.3.3. AbstractDataSource类 11.3.4. SingleConnectionDataSource类 11.3.5. DriverManagerDataSource类 11.3.6. TransactionAwareDataSourceProxy类 11.3.7. DataSourceTransactionManager类 11.4. 用Java对象来表达JDBC操作 11.4.1. SqlQuery类 11.4.2. MappingSqlQuery类 11.4.3. SqlUpdate类 11.4.4. StoredProcedure类 11.4.5. SqlFunction类 12. 使用ORM工具进行数据访问 12.1. 简介 12.2. Hibernate 12.2.1. 资源管理 12.2.2. 在Spring的application context创建 SessionFactory 12.2.3. HibernateTemplate 12.2.4. 不使用回调的基于Spring的DAO实现 12.2.5. 基于Hibernate3的原生API实现DAO 12.2.6. 编程式的事务划分 12.2.7. 声明式的事务划分 12.2.8. 事务管理策略 12.2.9. 容器资源 vs 本地资源 12.2.10. 在应用服务器使用Hibernate的注意点 12.3. JDO 12.3.1. 建立PersistenceManagerFactory 12.3.2. JdoTemplate和JdoDaoSupport 12.3.3. 基于原生的JDO API实现DAO 12.3.4. 事务管理 12.3.5. JdoDialect 12.4. Oracle TopLink 12.4.1. SessionFactory 抽象层 12.4.2. TopLinkTemplate 和 TopLinkDaoSupport 12.4.3. 基于原生的TopLink API的DAO实现 12.4.4. 事务管理 12.5. iBATIS SQL Maps 12.5.1. iBATIS 1.x和2.x的概览与区别 12.5.2. iBATIS SQL Maps 1.x 12.5.2.1. 创建SqlMap 12.5.2.2. 使用 SqlMapTemplate 和 SqlMapDaoSupport 12.5.3. iBATIS SQL Maps 2.x 12.5.3.1. 创建SqlMapClient 12.5.3.2. 使用 SqlMapClientTemplate 和 SqlMapClientDaoSupport 12.5.3.3. 基于原生的iBATIS API的DAO实现 12.6. JPA 12.6.1. 在Spring环境建立JPA 12.6.1.1. LocalEntityManagerFactoryBean 12.6.1.2. LocalContainerEntityManagerFactoryBean 12.6.1.3. 处理多个持久化单元 12.6.2. JpaTemplate 和 JpaDaoSupport 12.6.3. 基于原生的JPA实现DAO 12.6.4. 异常转化 12.6.5. 事务管理 12.6.6. JpaDialect III. Web 13. Web框架 13.1. 介绍 13.1.1. 与其他web框架的集成 13.1.2. Spring Web MVC框架的特点 13.2. DispatcherServlet 13.3. 控制器 13.3.1. AbstractController 和 WebContentGenerator 13.3.2. 其它的简单控制器 13.3.3. MultiActionController 13.3.4. 命令控制器 13.4. 处理器映射(handler mapping) 13.4.1. BeanNameUrlHandlerMapping 13.4.2. SimpleUrlHandlerMapping 13.4.3. 拦截器(HandlerInterceptor) 13.5. 视图与视图解析 13.5.1. 视图解析器 13.5.2. 视图解析链 13.5.3. 重定向(Rediret)到另一个视图 13.5.3.1. RedirectView 13.5.3.2. redirect:前缀 13.5.3.3. forward:前缀 13.6. 本地化解析器 13.6.1. AcceptHeaderLocaleResolver 13.6.2. CookieLocaleResolver 13.6.3. SessionLocaleResolver 13.6.4. LocaleChangeInterceptor 13.7. 使用主题 13.7.1. 简介 13.7.2. 如何定义主题 13.7.3. 主题解析器 13.8. Spring对分段文件上传(multipart file upload)的支持 13.8.1. 介绍 13.8.2. 使用MultipartResolver 13.8.3. 在表单处理分段文件上传 13.9. 使用Spring的表单标签库 13.9.1. 配置标签库 13.9.2. form标签 13.9.3. input标签 13.9.4. checkbox标签 13.9.5. radiobutton标签 13.9.6. password标签 13.9.7. select标签 13.9.8. option标签 13.9.9. options标签 13.9.10. textarea标签 13.9.11. hidden标签 13.9.12. errors标签 13.10. 处理异常 13.11. 惯例优先原则(convention over configuration) 13.11.1. 对控制器的支持: ControllerClassNameHandlerMapping 13.11.2. 对模型的支持:ModelMap (ModelAndView) 13.11.3. 对视图的支持: RequestToViewNameTranslator 13.12. 其它资源 14. 集成视图技术 14.1. 简介 14.2. JSP和JSTL 14.2.1. 视图解析器 14.2.2. 'Plain-old' JSPs versus JSTL 'Plain-old' JSP与JSTL 14.2.3. 帮助简化开发的额外的标签 14.3. Tiles 14.3.1. 需要的资源 14.3.2. 如何集成Tiles 14.3.2.1. InternalResourceViewResolver 14.3.2.2. ResourceBundleViewResolver 14.4. Velocity和FreeMarker 14.4.1. 需要的资源 14.4.2. Context 配置 14.4.3. 创建模板 14.4.4. 高级配置 14.4.4.1. velocity.properties 14.4.4.2. FreeMarker 14.4.5. 绑定支持和表单处理 14.4.5.1. 用于绑定的宏 14.4.5.2. 简单绑定 14.4.5.3. 表单输入生成宏 14.4.5.4. 重载HTML转码行为并使你的标签符合XHTML 14.5. XSLT 14.5.1. 写在段首 14.5.1.1. Bean 定义 14.5.1.2. 标准MVC控制器代码 14.5.1.3. 把模型数据转化为XML 14.5.1.4. 定义视图属性 14.5.1.5. 文档转换 14.5.2. 小结 14.6. 文档视图(PDF/Excel) 14.6.1. 简介 14.6.2. 配置和安装 14.6.2.1. 文档视图定义 14.6.2.2. Controller 代码 14.6.2.3. Excel视图子类 14.6.2.4. PDF视图子类 14.7. JasperReports 14.7.1. 依赖的资源 14.7.2. 配置 14.7.2.1. 配置ViewResolver 14.7.2.2. 配置View 14.7.2.3. 关于报表文件 14.7.2.4. 使用 JasperReportsMultiFormatView 14.7.3. 构造ModelAndView 14.7.4. 使用子报表 14.7.4.1. 配置子报表文件 14.7.4.2. 配置子报表数据源 14.7.5. 配置Exporter的参数 15. 集成其它Web框架 15.1. 简介 15.2. 通用配置 15.3. JavaServer Faces 15.3.1. DelegatingVariableResolver 15.3.2. FacesContextUtils 15.4. Struts 15.4.1. ContextLoaderPlugin 15.4.1.1. DelegatingRequestProcessor 15.4.1.2. DelegatingActionProxy 15.4.2. ActionSupport 类 15.5. Tapestry 15.5.1. 注入 Spring 托管的 beans 15.5.1.1. 将 Spring Beans 注入到 Tapestry 页面 15.5.1.2. 组件定义文件 15.5.1.3. 添加抽象访问方法 15.5.1.4. 将 Spring Beans 注入到 Tapestry 页面 - Tapestry 4.0+ 风格 15.6. WebWork 15.7. 更多资源 16. Portlet MVC框架 16.1. 介绍 16.1.1. 控制器 - MVC的C 16.1.2. 视图 - MVC的V 16.1.3. Web作用范围的Bean 16.2. DispatcherPortlet 16.3. ViewRendererServlet 16.4. 控制器 16.4.1. AbstractController和PortletContentGenerator 16.4.2. 其它简单的控制器 16.4.3. Command控制器 16.4.4. PortletWrappingController 16.5. 处理器映射 16.5.1. PortletModeHandlerMapping 16.5.2. ParameterHandlerMapping 16.5.3. PortletModeParameterHandlerMapping 16.5.4. 增加 HandlerInterceptor 16.5.5. HandlerInterceptorAdapter 16.5.6. ParameterMappingInterceptor 16.6. 视图和它们的解析 16.7. Multipart文件上传支持 16.7.1. 使用PortletMultipartResolver 16.7.2. 处理表单里的文件上传 16.8. 异常处理 16.9. Portlet应用的部署 IV. 整合 17. 使用Spring进行远程访问与Web服务 17.1. 简介 17.2. 使用RMI暴露服务 17.2.1. 使用 RmiServiceExporter 暴露服务 17.2.2. 在客户端链接服务 17.3. 使用Hessian或者Burlap通过HTTP远程调用服务 17.3.1. 为Hessian配置DispatcherServlet 17.3.2. 使用HessianServiceExporter暴露你的bean 17.3.3. 客户端连接服务 17.3.4. 使用Burlap 17.3.5. 对通过Hessian或Burlap暴露的服务使用HTTP基础认证 17.4. 使用HTTP调用器暴露服务 17.4.1. 暴露服务对象 17.4.2. 在客户端连接服务 17.5. Web服务 17.5.1. 使用JAXI-RPC暴露服务 17.5.2. 访问Web服务 17.5.3. 注册bean映射 17.5.4. 注册自己的处理方法 17.5.5. 使用XFire来暴露Web服务 17.6. 对远程接口不提供自动探测 17.7. 在选择这些技术时的一些考虑 18. Enterprise Java Bean(EJB)集成 18.1. 简介 18.2. 访问EJB 18.2.1. 概念 18.2.2. 访问本地的无状态Session Bean(SLSB) 18.2.3. 访问远程SLSB 18.3. 使用Spring提供的辅助类实现EJB组件 19. JMS 19.1. 简介 19.2. 使用Spring JMS 19.2.1. JmsTemplate 19.2.2. 连接工厂 19.2.3. (消息)目的地管理 19.2.4. 消息侦听容器 19.2.4.1. SimpleMessageListenerContainer 19.2.4.2. DefaultMessageListenerContainer 19.2.4.3. ServerSessionMessageListenerContainer 19.2.5. 事务管理 19.3. 发送一条消息 19.3.1. 使用消息转换器 19.3.2. SessionCallback 和ProducerCallback 19.4. 接收消息 19.4.1. 同步接收 19.4.2. 异步接收 - 消息驱动的POJOs 19.4.3. SessionAwareMessageListener 接口 19.4.4. MessageListenerAdapter 19.4.5. 事务的多方参与 20. JMX 20.1. 介绍 20.2. 输出bean到JMX 20.2.1. 创建一个MBeanServer 20.2.2. 复用现有的MBeanServer 20.2.3. MBean的惰性初始化 20.2.4. MBean的自动注册 20.2.5. 控制注册行为 20.3. 控制bean的管理接口 20.3.1. MBeanInfoAssembler 接口 20.3.2. 使用源码级元数据 20.3.3. 使用JDK 5.0注解 20.3.4. 源代码级的元数据类型 20.3.5. 接口AutodetectCapableMBeanInfoAssembler 20.3.6. 用Java接口定义管理接口 20.3.7. 使用MethodNameBasedMBeanInfoAssembler 20.4. 控制bean的 ObjectName 20.4.1. 从Properties读取ObjectName 20.4.2. 使用 MetadataNamingStrategy 20.5. JSR-160连接器 20.5.1. 服务器端连接器 20.5.2. 客户端连接器 20.5.3. 基于Burlap/Hessian/SOAP的JMX 20.6. 通过代理访问MBeans 20.7. 通知 20.7.1. 为通知注册监听器 20.7.2. 发布通知 20.8. 更多资源 21. JCA CCI 21.1. 介绍 21.2. 配置CCI 21.2.1. 连接器配置 21.2.2. 在Spring配置ConnectionFactory 21.2.3. 配置CCI连接 21.2.4. 使用一个 CCI 单连接 21.3. 使用Spring的 CCI访问支持 21.3.1. 记录转换 21.3.2. CciTemplate 类 21.3.3. DAO支持 21.3.4. 自动输出记录生成 21.3.5. 总结 21.3.6. 直接使用一个 CCI Connection 接口和Interaction接口 21.3.7. CciTemplate 使用示例 21.4. 建模CCI访问为操作对象 21.4.1. MappingRecordOperation 21.4.2. MappingCommAreaOperation 21.4.3. 自动输出记录生成 21.4.4. 总结 21.4.5. MappingRecordOperation 使用示例 21.4.6. MappingCommAreaOperation 使用示例 21.5. 事务 22. Spring邮件抽象层 22.1. 简介 22.2. Spring邮件抽象结构 22.3. 使用Spring邮件抽象 22.3.1. 可插拔的MailSender实现 22.4. 使用 JavaMail MimeMessageHelper 22.4.1. 创建一条简单的MimeMessage,并且发送出去 22.4.2. 发送附件和嵌入式资源(inline resources) 23. Spring的定时调度(Scheduling)和线程池(Thread Pooling) 23.1. 简介 23.2. 使用OpenSymphony Quartz 调度器 23.2.1. 使用JobDetailBean 23.2.2. 使用 MethodInvokingJobDetailFactoryBean 23.2.3. 使用triggers和SchedulerFactoryBean来包装任务 23.3. 使用JDK Timer支持类 23.3.1. 创建定制的timers 23.3.2. 使用 MethodInvokingTimerTaskFactoryBean类 23.3.3. 打包:使用TimerFactoryBean来设置任务 23.4. SpringTaskExecutor抽象 23.4.1. TaskExecutor接口 23.4.2. 何时使用TaskExecutor接口 23.4.3. TaskExecutor类型 23.4.4. 使用TaskExecutor接口 24. 动态语言支持 24.1. 介绍 24.2. 第一个例子 24.3. 定义动态语言支持的bean 24.3.1. 公共概念 24.3.1.1. <lang:language/> 元素 24.3.1.2. Refreshable bean 24.3.1.3. 内置动态语言源文件 24.3.1.4. 理解dynamic-language-backed bean context的构造器注入 24.3.2. JRuby beans 24.3.3. Groovy beans 24.3.4. BeanShell beans 24.4. 场景 24.4.1. Spring MVC控制器脚本化 24.4.2. Validator脚本化 24.5. 更多的资源 25. 注解和源代码级的元数据支持 25.1. 简介 25.2. Spring的元数据支持 25.3. 注解 25.3.1. @Required 25.3.2. Spring的其它@Annotations 25.4. 集成Jakarta Commons Attributes 25.5. 元数据和Spring AOP自动代理 25.5.1. 基本原理 25.5.2. 声明式事务管理 25.5.3. 缓冲 25.5.4. 自定义元数据 25.6. 使用属性来减少MVC web层配置 25.7. 元数据属性的其它用法 25.8. 增加对额外元数据API的支持 A. XML Schema-based configuration A.1. Introduction A.2. XML Schema-based configuration A.2.1. Referencing the schemas A.2.2. The util schema A.2.2.1. <util:constant/> A.2.2.2. <util:property-path/> A.2.2.3. <util:properties/> A.2.2.4. <util:list/> A.2.2.5. <util:map/> A.2.2.6. <util:set/> A.2.3. The jee schema A.2.3.1. <jee:jndi-lookup/> (simple) A.2.3.2. <jee:jndi-lookup/> (with single JNDI environment setting) A.2.3.3. <jee:jndi-lookup/> (with multiple JNDI environment settings) A.2.3.4. <jee:jndi-lookup/> (complex) A.2.3.5. <jee:local-slsb/> (simple) A.2.3.6. <jee:local-slsb/> (complex) A.2.3.7. <jee:remote-slsb/> A.2.4. The lang schema A.2.5. The tx (transaction) schema A.2.6. The aop schema A.2.7. The tool schema A.2.8. The beans schema A.3. Setting up your IDE A.3.1. Setting up Eclipse A.3.2. Setting up IntelliJ IDEA A.3.3. Integration issues A.3.3.1. XML parsing errors in the Resin v.3 application server B. Extensible XML authoring B.1. Introduction B.2. Authoring the schema B.3. Coding a NamespaceHandler B.4. Coding a BeanDefinitionParser B.5. Registering the handler and the schema B.5.1. META-INF/spring.handlers B.5.2. META-INF/spring.schemas C. spring-beans-2.0.dtd D. spring.tld D.1. Introduction D.2. The bind tag D.3. The escapeBody tag D.4. The hasBindErrors tag D.5. The htmlEscape tag D.6. The message tag D.7. The nestedPath tag D.8. The theme tag D.9. The transform tag E. spring-form.tld E.1. Introduction E.2. The checkbox tag E.3. The errors tag E.4. The form tag E.5. The hidden tag E.6. The input tag E.7. The label tag E.8. The option tag E.9. The options tag E.10. The password tag E.11. The radiobutton tag E.12. The select tag E.13. The textarea tag F. Spring 2.0 开发手册文化项目 F.1. 声明 F.2. 致谢 F.3. 参与人员及任务分配 F.4. Spring 2.0 正式版开发手册翻译说明 F.5. 项目历程 F.5.1. Spring 2.0 RC2 开发手册翻译项目 F.5.2. Spring 2.0 正式版开发手册翻译项目
org.springframework spring-context包是Spring框架的核心包之一,主要提供了Spring应用程序上下文的支持,包括BeanFactory、ApplicationContext和其他相关的类和接口。 Spring应用程序上下文是Spring框架的一个关键概念,它是一个容器,负责管理应用程序的所有Bean对象。Spring应用程序上下文通过读取配置文件或注解来创建和管理Bean对象,同时还提供了依赖注入、AOP、事件传播等功能。 在spring-context包BeanFactory是Spring框架最基础的容器,它可以从配置文件或其他来源加载Bean定义,并实例化和管理Bean对象。ApplicationContext是BeanFactory的子接口,它扩展了BeanFactory的功能,提供了更多的企业级功能,比如国际化、消息、Web应用程序上下文等。 除了BeanFactory和ApplicationContext外,spring-context包还提供了其他一些核心类和接口,例如: 1. Resource:用于加载和访问资源,例如文件、类路径等。 2. BeanDefinition:用于定义Bean的元数据,包括Bean的类型、属性、依赖关系等。 3. BeanPostProcessor:用于在Bean实例化、初始化、销毁等阶段添加自定义逻辑。 4. ApplicationEventPublisher:用于发布和监听应用程序事件。 总体来说,org.springframework spring-context包提供了Spring框架的核心功能,是开发Spring应用程序必不可少的一个包。通过使用spring-context包的类和接口,开发者可以轻松地构建和管理Spring应用程序的所有Bean对象,并实现各种企业级功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值