转自:http://blog.csdn.net/caihaijiang/article/details/35552859
BeanFactoryPostProcessor和BeanPostProcessor,这两个接口,都是spring初始化bean时对外暴露的扩展点。两个接口名称看起来很相似,但作用及使用场景却不同,分析如下:
1、BeanFactoryPostProcessor接口
该接口的定义如下:
- public interface BeanFactoryPostProcessor {
- /**
- * Modify the application context's internal bean factory after its standard
- * initialization. All bean definitions will have been loaded, but no beans
- * will have been instantiated yet. This allows for overriding or adding
- * properties even to eager-initializing beans.
- * @param beanFactory the bean factory used by the application context
- * @throws org.springframework.beans.BeansException in case of errors
- */
- void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException;
- }
实现该接口,可以在spring的bean创建之前,修改bean的定义属性。也就是说,Spring允许BeanFactoryPostProcessor在容器实例化任何其它bean之前读取配置元数据,并可以根据需要进行修改,例如可以把bean的scope从singleton改为prototype,也可以把property的值给修改掉。可以同时配置多个BeanFactoryPostProcessor,并通过设置'order'属性来控制各个BeanFactoryPostProcessor的执行次序。
注意:BeanFactoryPostProcessor是在spring容器加载了bean的定义文件之后,在bean实例化之前执行的。接口方法的入参是ConfigurrableListableBeanFactory,使用该参数,可以获取到相关bean的定义信息,例子:
1)spring bean的定义:
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
- default-autowire="byName">
- <bean id="myJavaBean" class="com.ali.caihj.postprocessor.MyJavaBean">
- <property name="desc" value="测试一下啦" />
- <property name="remark" value="这是备注信息啦啦啦" />
- </bean>
- <bean id="myBeanFactoryPostProcessor" class="com.ali.caihj.postprocessor.MyBeanFactoryPostProcessor" />
- </beans>
2)自定义的BeanFactoryPostProcessor:
- public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- System.out.println("调用MyBeanFactoryPostProcessor的postProcessBeanFactory");
- BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");
- System.out.println("属性值============" + bd.getPropertyValues().toString());
- MutablePropertyValues pv = bd.getPropertyValues();
- if (pv.contains("remark")) {
- pv.addPropertyValue("remark", "把备注信息修改一下");
- }
- bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
- }
- }
spring中,有内置的一些BeanFactoryPostProcessor实现类,常用的有:
- org.springframework.beans.factory.config.PropertyPlaceholderConfigurer
- org.springframework.beans.factory.config.PropertyOverrideConfigurer
- org.springframework.beans.factory.config.CustomEditorConfigurer:用来注册自定义的属性编辑器
2、BeanPostProcessor接口
该接口的定义如下:
- public interface BeanPostProcessor {
- /**
- * Apply this BeanPostProcessor to the given new bean instance <i>before</i> any bean
- * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code>
- * or a custom init-method). The bean will already be populated with property values.
- * The returned bean instance may be a wrapper around the original.
- * @param bean the new bean instance
- * @param beanName the name of the bean
- * @return the bean instance to use, either the original or a wrapped one
- * @throws org.springframework.beans.BeansException in case of errors
- * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
- */
- Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException;
- /**
- * Apply this BeanPostProcessor to the given new bean instance <i>after</i> any bean
- * initialization callbacks (like InitializingBean's <code>afterPropertiesSet</code>
- * or a custom init-method). The bean will already be populated with property values.
- * The returned bean instance may be a wrapper around the original.
- * <p>In case of a FactoryBean, this callback will be invoked for both the FactoryBean
- * instance and the objects created by the FactoryBean (as of Spring 2.0). The
- * post-processor can decide whether to apply to either the FactoryBean or created
- * objects or both through corresponding <code>bean instanceof FactoryBean</code> checks.
- * <p>This callback will also be invoked after a short-circuiting triggered by a
- * {@link InstantiationAwareBeanPostProcessor#postProcessBeforeInstantiation} method,
- * in contrast to all other BeanPostProcessor callbacks.
- * @param bean the new bean instance
- * @param beanName the name of the bean
- * @return the bean instance to use, either the original or a wrapped one
- * @throws org.springframework.beans.BeansException in case of errors
- * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet
- * @see org.springframework.beans.factory.FactoryBean
- */
- Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException;
- }
BeanPostProcessor,可以在spring容器实例化bean之后,在执行bean的初始化方法前后,添加一些自己的处理逻辑。这里说的初始化方法,指的是下面两种:
1)bean实现了InitializingBean接口,对应的方法为afterPropertiesSet
2)在bean定义的时候,通过init-method设置的方法
注意:BeanPostProcessor是在spring容器加载了bean的定义文件并且实例化bean之后执行的。BeanPostProcessor的执行顺序是在BeanFactoryPostProcessor之后。
spring中,有内置的一些BeanPostProcessor实现类,例如:
- org.springframework.context.annotation.CommonAnnotationBeanPostProcessor:支持@Resource注解的注入
- org.springframework.beans.factory.annotation.RequiredAnnotationBeanPostProcessor:支持@Required注解的注入
- org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor:支持@Autowired注解的注入
- org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor:支持@PersistenceUnit和@PersistenceContext注解的注入
- org.springframework.context.support.ApplicationContextAwareProcessor:用来为bean注入ApplicationContext等容器对象
这些注解类的BeanPostProcessor,在spring配置文件中,可以通过这样的配置 <context:component-scan base-package="*.*" /> ,自动进行注册。(spring通过ComponentScanBeanDefinitionParser类来解析该标签)
3、下面通过完整的一个例子,来加深理解
1)定义一个JavaBean
- public class MyJavaBean implements InitializingBean {
- private String desc;
- private String remark;
- public MyJavaBean() {
- System.out.println("MyJavaBean的构造函数被执行啦");
- }
- public String getDesc() {
- return desc;
- }
- public void setDesc(String desc) {
- System.out.println("调用setDesc方法");
- this.desc = desc;
- }
- public String getRemark() {
- return remark;
- }
- public void setRemark(String remark) {
- System.out.println("调用setRemark方法");
- this.remark = remark;
- }
- public void afterPropertiesSet() throws Exception {
- System.out.println("调用afterPropertiesSet方法");
- this.desc = "在初始化方法中修改之后的描述信息";
- }
- public void initMethod() {
- System.out.println("调用initMethod方法");
- }
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append("[描述:").append(desc);
- builder.append(", 备注:").append(remark).append("]");
- return builder.toString();
- }
- }
2)定义一个BeanFactoryPostProcessor
- public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
- public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
- System.out.println("调用MyBeanFactoryPostProcessor的postProcessBeanFactory");
- BeanDefinition bd = beanFactory.getBeanDefinition("myJavaBean");
- MutablePropertyValues pv = bd.getPropertyValues();
- if (pv.contains("remark")) {
- pv.addPropertyValue("remark", "在BeanFactoryPostProcessor中修改之后的备忘信息");
- }
- }
- }
3)定义一个BeanPostProcessor
- public class MyBeanPostProcessor implements BeanPostProcessor {
- public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("BeanPostProcessor,对象" + beanName + "调用初始化方法之前的数据: " + bean.toString());
- return bean;
- }
- public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
- System.out.println("BeanPostProcessor,对象" + beanName + "调用初始化方法之后的数据:" + bean.toString());
- return bean;
- }
- }
4)spring的配置
- <?xml version="1.0" encoding="UTF-8" ?>
- <beans xmlns="http://www.springframework.org/schema/beans"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
- xmlns:p="http://www.springframework.org/schema/p" xmlns:tx="http://www.springframework.org/schema/tx"
- xmlns:aop="http://www.springframework.org/schema/aop"
- xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
- http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
- http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"
- default-autowire="byName">
- <bean id="myJavaBean" class="com.ali.caihj.postprocessor.MyJavaBean" init-method="initMethod">
- <property name="desc" value="原始的描述信息" />
- <property name="remark" value="原始的备注信息" />
- </bean>
- <bean id="myBeanPostProcessor" class="com.ali.caihj.postprocessor.MyBeanPostProcessor" />
- <bean id="myBeanFactoryPostProcessor" class="com.ali.caihj.postprocessor.MyBeanFactoryPostProcessor" />
- </beans>
5)测试类
- public class PostProcessorMain {
- public static void main(String[] args) {
- ApplicationContext context = new ClassPathXmlApplicationContext("config/postprocessor.xml");
- MyJavaBean bean = (MyJavaBean) context.getBean("myJavaBean");
- System.out.println("===============下面输出结果============");
- System.out.println("描述:" + bean.getDesc());
- System.out.println("备注:" + bean.getRemark());
- }
- }
6)运行结果如下:
7)分析
从上面的结果可以看出,BeanFactoryPostProcessor在bean实例化之前执行,之后实例化bean(调用构造函数,并调用set方法注入属性值),然后在调用两个初始化方法前后,执行了BeanPostProcessor。初始化方法的执行顺序是,先执行afterPropertiesSet,再执行init-method。
4、进一步深入分析
在使用ApplicationContext启动spring容器的时候,在AbstractApplicationContext.refresh()方法中,完成相关初始化工作:
1)BeanFactoryPostProcessor.postProcessBeanFactory,是在第5步执行的,invokeBeanFactoryPostProcessors方法实现如下:
- /**
- * Instantiate and invoke all registered BeanFactoryPostProcessor beans,
- * respecting explicit order if given.
- * <p>Must be called before singleton instantiation.
- */
- protected void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory) {
- // Invoke factory processors registered with the context instance.
- for (Iterator it = getBeanFactoryPostProcessors().iterator(); it.hasNext();) {
- BeanFactoryPostProcessor factoryProcessor = (BeanFactoryPostProcessor) it.next();
- factoryProcessor.postProcessBeanFactory(beanFactory);
- }
- // Do not initialize FactoryBeans here: We need to leave all regular beans
- // uninitialized to let the bean factory post-processors apply to them!
- String[] postProcessorNames =
- beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false);
- // Separate between BeanFactoryPostProcessors that implement PriorityOrdered,
- // Ordered, and the rest.
- List priorityOrderedPostProcessors = new ArrayList();
- List orderedPostProcessorNames = new ArrayList();
- List nonOrderedPostProcessorNames = new ArrayList();
- for (int i = 0; i < postProcessorNames.length; i++) {
- if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {
- priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));
- }
- else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {
- orderedPostProcessorNames.add(postProcessorNames[i]);
- }
- else {
- nonOrderedPostProcessorNames.add(postProcessorNames[i]);
- }
- }
- // First, invoke the BeanFactoryPostProcessors that implement PriorityOrdered.
- Collections.sort(priorityOrderedPostProcessors, new OrderComparator());
- invokeBeanFactoryPostProcessors(beanFactory, priorityOrderedPostProcessors);
- // Next, invoke the BeanFactoryPostProcessors that implement Ordered.
- List orderedPostProcessors = new ArrayList();
- for (Iterator it = orderedPostProcessorNames.iterator(); it.hasNext();) {
- String postProcessorName = (String) it.next();
- orderedPostProcessors.add(getBean(postProcessorName));
- }
- Collections.sort(orderedPostProcessors, new OrderComparator());
- invokeBeanFactoryPostProcessors(beanFactory, orderedPostProcessors);
- // Finally, invoke all other BeanFactoryPostProcessors.
- List nonOrderedPostProcessors = new ArrayList();
- for (Iterator it = nonOrderedPostProcessorNames.iterator(); it.hasNext();) {
- String postProcessorName = (String) it.next();
- nonOrderedPostProcessors.add(getBean(postProcessorName));
- }
- invokeBeanFactoryPostProcessors(beanFactory, nonOrderedPostProcessors);
- }
- /**
- * Invoke the given BeanFactoryPostProcessor beans.
- */
- private void invokeBeanFactoryPostProcessors(ConfigurableListableBeanFactory beanFactory, List postProcessors) {
- for (Iterator it = postProcessors.iterator(); it.hasNext();) {
- BeanFactoryPostProcessor postProcessor = (BeanFactoryPostProcessor) it.next();
- postProcessor.postProcessBeanFactory(beanFactory);
- }
- }
通过beanFactory.getBeanNamesForType(BeanFactoryPostProcessor.class, true, false),获取spring配置文件中定义的所有实现BeanFactoryPostProcessor接口的bean,然后根据优先级进行排序,之后对于每个BeanFactoryPostProcessor,调用postProcessBeanFactory方法。
2)而BeanPostProcessor的执行,取决于配置文件中bean的定义,如果定义的bean是singleton并且不是抽象类,也不延迟初始化,则BeanPostProcessor是在第11步中执行;而对于prototype的bean,BeanPostProcessor是在程序getBean的时候执行的。在第6步中,调用registerBeanPostProcessors方法,注册所有实现BeanPostProcessor接口的bean,该方法的实现如下:
- protected void registerBeanPostProcessors(ConfigurableListableBeanFactory beanFactory) {
- 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.
- int beanProcessorTargetCount = beanFactory.getBeanPostProcessorCount() + 1 + postProcessorNames.length;
- beanFactory.addBeanPostProcessor(new BeanPostProcessorChecker(beanFactory, beanProcessorTargetCount));
- // Separate between BeanPostProcessors that implement PriorityOrdered,
- // Ordered, and the rest.
- List priorityOrderedPostProcessors = new ArrayList();
- List orderedPostProcessorNames = new ArrayList();
- List nonOrderedPostProcessorNames = new ArrayList();
- for (int i = 0; i < postProcessorNames.length; i++) {
- if (isTypeMatch(postProcessorNames[i], PriorityOrdered.class)) {
- priorityOrderedPostProcessors.add(beanFactory.getBean(postProcessorNames[i]));
- }
- else if (isTypeMatch(postProcessorNames[i], Ordered.class)) {
- orderedPostProcessorNames.add(postProcessorNames[i]);
- }
- else {
- nonOrderedPostProcessorNames.add(postProcessorNames[i]);
- }
- }
- // First, register the BeanPostProcessors that implement PriorityOrdered.
- Collections.sort(priorityOrderedPostProcessors, new OrderComparator());
- registerBeanPostProcessors(beanFactory, priorityOrderedPostProcessors);
- // Next, register the BeanPostProcessors that implement Ordered.
- List orderedPostProcessors = new ArrayList();
- for (Iterator it = orderedPostProcessorNames.iterator(); it.hasNext();) {
- String postProcessorName = (String) it.next();
- orderedPostProcessors.add(getBean(postProcessorName));
- }
- Collections.sort(orderedPostProcessors, new OrderComparator());
- registerBeanPostProcessors(beanFactory, orderedPostProcessors);
- // Finally, register all other BeanPostProcessors.
- List nonOrderedPostProcessors = new ArrayList();
- for (Iterator it = nonOrderedPostProcessorNames.iterator(); it.hasNext();) {
- String postProcessorName = (String) it.next();
- nonOrderedPostProcessors.add(getBean(postProcessorName));
- }
- registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
- }
在第11步中,调用finishBeanFactoryInitialization方法,该方法通过调用DefaultListableBeanFactory.preInstantiateSingletons(),进行相关初始化工作:
从上面的代码可以看出,对于非抽象类、非延迟初始化的单例bean,在spring容器启动的时候调用getBean方法来实例化bean,并进行相关初始化工作,getBean方法最终调用AbstractAutowireCapableBeanFactory.doCreateBean方法,该方法的实现如下:
- protected Object doCreateBean(final String beanName, final RootBeanDefinition mbd, final Object[] args) {
- // Instantiate the bean.
- BeanWrapper instanceWrapper = null;
- if (mbd.isSingleton()) {
- instanceWrapper = (BeanWrapper) this.factoryBeanInstanceCache.remove(beanName);
- }
- if (instanceWrapper == null) {
- instanceWrapper = createBeanInstance(beanName, mbd, args);
- }
- final Object bean = (instanceWrapper != null ? instanceWrapper.getWrappedInstance() : null);
- Class beanType = (instanceWrapper != null ? instanceWrapper.getWrappedClass() : null);
- // Allow post-processors to modify the merged bean definition.
- synchronized (mbd.postProcessingLock) {
- if (!mbd.postProcessed) {
- applyMergedBeanDefinitionPostProcessors(mbd, beanType, beanName);
- mbd.postProcessed = true;
- }
- }
- // Eagerly cache singletons to be able to resolve circular references
- // even when triggered by lifecycle interfaces like BeanFactoryAware.
- boolean earlySingletonExposure = (mbd.isSingleton() && this.allowCircularReferences &&
- isSingletonCurrentlyInCreation(beanName));
- if (earlySingletonExposure) {
- if (logger.isDebugEnabled()) {
- logger.debug("Eagerly caching bean '" + beanName +
- "' to allow for resolving potential circular references");
- }
- addSingletonFactory(beanName, new ObjectFactory() {
- public Object getObject() throws BeansException {
- return getEarlyBeanReference(beanName, mbd, bean);
- }
- });
- }
- // Initialize the bean instance.
- Object exposedObject = bean;
- try {
- populateBean(beanName, mbd, instanceWrapper);
- exposedObject = initializeBean(beanName, exposedObject, mbd);
- }
- catch (Throwable ex) {
- if (ex instanceof BeanCreationException && beanName.equals(((BeanCreationException) ex).getBeanName())) {
- throw (BeanCreationException) ex;
- }
- else {
- throw new BeanCreationException(mbd.getResourceDescription(), beanName, "Initialization of bean failed", ex);
- }
- }
- if (earlySingletonExposure) {
- Object earlySingletonReference = getSingleton(beanName, false);
- if (earlySingletonReference != null) {
- if (exposedObject == bean) {
- exposedObject = earlySingletonReference;
- }
- else if (!this.allowRawInjectionDespiteWrapping && hasDependentBean(beanName)) {
- String[] dependentBeans = getDependentBeans(beanName);
- Set actualDependentBeans = new LinkedHashSet(dependentBeans.length);
- for (int i = 0; i < dependentBeans.length; i++) {
- String dependentBean = dependentBeans[i];
- if (!removeSingletonIfCreatedForTypeCheckOnly(dependentBean)) {
- actualDependentBeans.add(dependentBean);
- }
- }
- if (!actualDependentBeans.isEmpty()) {
- throw new BeanCurrentlyInCreationException(beanName,
- "Bean with name '" + beanName + "' has been injected into other beans [" +
- StringUtils.collectionToCommaDelimitedString(actualDependentBeans) +
- "] in its raw version as part of a circular reference, but has eventually been " +
- "wrapped. This means that said other beans do not use the final version of the " +
- "bean. This is often the result of over-eager type matching - consider using " +
- "'getBeanNamesOfType' with the 'allowEagerInit' flag turned off, for example.");
- }
- }
- }
- }
- // Register bean as disposable.
- registerDisposableBeanIfNecessary(beanName, bean, mbd);
- return exposedObject;
- }
在该方法中,首先调用createBeanInstance方法,创建bean实例对象(这个时候执行bean的构造方法),然后调用populateBean方法,对bean进行填充,注入相关依赖,之后再调用方法initializeBean,进行相关初始化工作,initializeBean方法的实现如下:
- protected Object initializeBean(String beanName, Object bean, RootBeanDefinition mbd) {
- if (bean instanceof BeanNameAware) {
- ((BeanNameAware) bean).setBeanName(beanName);
- }
- if (bean instanceof BeanClassLoaderAware) {
- ((BeanClassLoaderAware) bean).setBeanClassLoader(getBeanClassLoader());
- }
- if (bean instanceof BeanFactoryAware) {
- ((BeanFactoryAware) bean).setBeanFactory(this);
- }
- Object wrappedBean = bean;
- if (mbd == null || !mbd.isSynthetic()) {
- wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
- }
- try {
- invokeInitMethods(beanName, wrappedBean, mbd);
- }
- catch (Throwable ex) {
- throw new BeanCreationException(
- (mbd != null ? mbd.getResourceDescription() : null),
- beanName, "Invocation of init method failed", ex);
- }
- if (mbd == null || !mbd.isSynthetic()) {
- wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
- }
- return wrappedBean;
- }
从上面的实现可以看出,先调用applyBeanPostProcessorsBeforeInitialization方法,执行每个BeanPostProcessor的postProcessBeforeInitialization,然后调用invokeInitMethods方法,执行bean的初始化方法,最后调用applyBeanPostProcessorsAfterInitialization方法,执行每个BeanPostProcessor的postProcessAfterInitialization方法。这三个方法的实现如下:
- public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName)
- throws BeansException {
- Object result = existingBean;
- for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
- BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
- result = beanProcessor.postProcessBeforeInitialization(result, beanName);
- }
- return result;
- }
- public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName)
- throws BeansException {
- Object result = existingBean;
- for (Iterator it = getBeanPostProcessors().iterator(); it.hasNext();) {
- BeanPostProcessor beanProcessor = (BeanPostProcessor) it.next();
- result = beanProcessor.postProcessAfterInitialization(result, beanName);
- }
- return result;
- }
- protected void invokeInitMethods(String beanName, Object bean, RootBeanDefinition mbd)
- throws Throwable {
- boolean isInitializingBean = (bean instanceof InitializingBean);
- if (isInitializingBean && (mbd == null || !mbd.isExternallyManagedInitMethod("afterPropertiesSet"))) {
- if (logger.isDebugEnabled()) {
- logger.debug("Invoking afterPropertiesSet() on bean with name '" + beanName + "'");
- }
- ((InitializingBean) bean).afterPropertiesSet();
- }
- String initMethodName = (mbd != null ? mbd.getInitMethodName() : null);
- if (initMethodName != null && !(isInitializingBean && "afterPropertiesSet".equals(initMethodName)) &&
- !mbd.isExternallyManagedInitMethod(initMethodName)) {
- invokeCustomInitMethod(beanName, bean, initMethodName, mbd.isEnforceInitMethod());
- }
- }
从invokeInitMethods方法的实现可以看出,先执行afterPropertiesSet方法,然后再通过反射,执行init-method指定的方法。
相关推荐
内容概要:本文深入探讨了空间电压矢量脉宽调制(SVPWM)技术,特别是五段式和七段式的实现方法及其优缺点。首先介绍了SVPWM的基本原理,包括电压矢量的合成、扇区判断和矢量作用时间计算。接着详细解释了五段式和七段式的具体实现步骤,并提供了相应的Python和C语言代码示例。此外,还讨论了模块化搭建的方法,包括MATLAB/Simulink和C语言的实现。最后,分享了一些实用的调试技巧和注意事项。 适合人群:从事电机控制、电力电子领域的工程师和技术人员,尤其是对SVPWM技术感兴趣的初学者和有一定经验的研发人员。 使用场景及目标:帮助读者理解SVPWM的工作原理,掌握五段式和七段式的实现方法,能够在实际项目中应用SVPWM技术,提高系统的性能和可靠性。 其他说明:文中提供的代码示例可以帮助读者更好地理解和实践SVPWM技术,同时引用的相关文献也为进一步学习提供了参考资料。
该MATLAB Simulink模型提供了与太阳能集成的储能系统(ESS)的综合仿真。该模型是为旨在探索、研究或原型可再生能源解决方案的用户设计的。它包括模拟太阳能发电、电池存储和并网或独立系统的能源管理的组件。太阳能电池板的输入电压可以根据用户而改变 特征 太阳能发电:模拟具有不同太阳辐照度的光伏(PV)系统。 两个储能系统的集成:引入两个动态储能系统来储存能量,它们是锂离子电池和超级电容电池。超级电容器电池被引入来处理由可再生能源引起的波动,锂离子电池被用于支持电网 电池储能:为锂离子电池和超级电容电池实施高效的充电和放电机制 能量管理系统(EMS):平衡光伏系统、电池和负载之间的能量流动。 负载动力学:支持可变负载条件,以测试系统的健壮性。 用户友好的设计:模块化和可定制的模型架构,易于适应。 应用程序 可再生能源的电网整合。 离网储能系统的开发。 理解ESS和太阳能概念的教育目的。 可再生能源技术的研究和开发。
内容概要:本文详细探讨了新能源汽车VCU(整车控制器)电控开发的关键技术和应用场景。首先介绍了VCU的重要性和主要职责,强调它是汽车的大脑,负责处理驾驶员操作信号并协调多个子系统的工作。接着阐述了VCU电控开发的具体流程,包括需求分析、硬件设计、软件开发以及测试验证四个主要环节。在软件开发部分,着重讲解了控制算法实现和通信协议的设计,展示了具体的代码示例。此外,文中还提到了一些实际开发过程中遇到的技术难题及解决方案,如信号滤波、故障诊断等。 适合人群:从事新能源汽车行业研究和技术开发的专业人士,尤其是对VCU电控开发感兴趣的工程师。 使用场景及目标:适用于希望深入了解新能源汽车VCU电控开发全过程的学习者;帮助开发者掌握从需求分析到最终产品落地的完整开发链路;提供实用的技术指导,提高开发效率和产品质量。 其他说明:文章不仅提供了理论知识,还有丰富的实战经验分享,对于理解和解决实际开发中的问题是很有价值的参考资料。
内容概要:本文详细介绍了信捷XD3 PLC驱动的六轴机器人项目,涵盖了硬件组合、梯形图编程、C语言编程以及维纶通触摸屏的应用。信捷XD3 PLC作为核心控制器,通过梯形图实现基本逻辑控制,如启动、停止、互锁等;C语言则用于处理复杂的运动轨迹规划和算法计算。维纶通触摸屏提供了友好的人机交互界面,便于参数设置和任务示教。文中还分享了许多实际项目中的经验和技巧,如梯形图的安全互锁设计、C语言中的浮点运算优化、触摸屏的通信配置等。 适合人群:具备一定PLC编程基础和技术背景的工程师,尤其是从事工业自动化领域的技术人员。 使用场景及目标:适用于需要深入了解PLC编程、C语言应用及人机交互设计的技术人员,帮助他们更好地理解和解决六轴机器人控制系统中的复杂问题。 其他说明:文章不仅提供了理论知识,还结合了大量的实际案例和代码示例,有助于读者在实践中快速上手并解决问题。
超过100个项目组成的项目资料
内容概要:本文详细介绍了西门子博途PLC中S型速度曲线加减速及其与位置轨迹规划相结合的技术。S型速度曲线通过平滑处理加速度,使得设备启动和停止时的速度变化更为柔和,减少了对机械设备的冲击。文中不仅解释了S型速度曲线的工作原理,还给出了具体的LAD语言和SCL语言代码示例,展示了如何在博途平台上实现这一功能。此外,文章还讨论了位置轨迹规划的具体方法,如利用目标位置数组和循环条件判断来实现多点位置的平滑过渡。最后,文章分享了一些调试技巧和实践经验,强调了参数选择和优化的重要性。 适合人群:从事自动化控制领域的工程师和技术人员,尤其是那些对PLC编程有一定基础的人群。 使用场景及目标:适用于需要高精度和平稳运动控制的工业设备,如包装机械、数控机床等。主要目标是减少设备启动和停止时的冲击,提高生产效率和产品质量。 其他说明:文中提供的代码示例和调试技巧可以帮助读者更好地理解和应用S型速度曲线加减速及位置轨迹规划技术。建议读者在实践中结合具体设备特性和需求进行参数调整和优化。
仿真
内容概要:本文详细介绍了基于扩展卡尔曼滤波(EKF)的15状态INS/GPS松组合导航系统的实现方法。首先定义了15个状态变量,包括位置误差、速度误差、姿态误差以及陀螺仪和加速度计的零偏。接着阐述了状态转移矩阵F的设计,重点讨论了速度误差与姿态误差之间的耦合关系,以及IMU零偏的建模。文中还探讨了GPS量测更新的具体实现,特别是在GPS信号丢失时的处理方法。此外,强调了协方差矩阵的初始化和调参技巧,如将GPS的HDOP融入观测噪声矩阵,以及处理姿态误差发散等问题。最后,提到了一些常见的调试陷阱,如姿态误差线性化范围和地理系更新周期的选择。 适合人群:从事导航系统开发的研究人员和技术工程师,尤其是对EKF、INS和GPS融合感兴趣的从业者。 使用场景及目标:适用于需要精确导航的应用场景,如无人机、自动驾驶汽车等。目标是通过EKF实现高精度的位置和姿态估计,确保在GPS信号不稳定的情况下仍能维持较长时间的导航精度。 其他说明:文章提供了大量代码片段作为辅助解释,帮助读者更好地理解和实现该系统。同时,文中提到的实际调试经验和常见错误也为初学者提供了宝贵的指导。
内容概要:本文详细介绍了一种适用于锂电行业分切机的三菱PLC张力控制通用程序模板。该模板涵盖锥度计算、模拟量输入输出、张力检测与PID调节、电气控制逻辑四大模块。通过动态调整伺服电机的转速和张力,确保材料收卷的均匀性和稳定性。文中提供了详细的代码示例和技术细节,如锥度计算中的加权平均滤波、模拟量处理中的非线性补偿、PID调节中的死区控制等。此外,还包括完整的程序注释和电气图纸,便于二次开发和实际应用。 适合人群:从事PLC编程和自动化控制的工程师,尤其是专注于锂电行业的技术人员。 使用场景及目标:① 锂电分切机的张力控制优化;② 提升材料收卷的质量和效率;③ 快速掌握张力控制的核心逻辑和实现方法。 其他说明:该模板不仅提供代码实现,还包含了大量实战经验和调试技巧,有助于解决实际应用中的常见问题。
内容概要:本文详细探讨了双极性SPWM控制的单相全桥逆变电路及其电压电流双闭环控制方法。首先介绍了电路的基本参数设定,如直流输入电压范围10-40V,输出交流峰值正负10-40V,频率可在1-200Hz之间调节。接着阐述了双极性SPWM控制原理,并提供了Python代码用于生成SPWM波形。随后深入讲解了电压电流双闭环控制的具体实现,包括电压环和电流环的PI调节器参数设置及优化方法。最后讨论了仿真过程中的一些注意事项和技术细节,如死区时间设置、滤波器参数选择、过流保护等。 适合人群:从事电力电子研究的技术人员、高校师生及相关领域的研究人员。 使用场景及目标:适用于需要进行逆变电路设计、仿真和优化的研究项目,旨在提高逆变电路的性能和稳定性,确保其能够适应不同应用场景的需求。 其他说明:文中提供的代码片段和参数配置有助于读者更好地理解和实践双极性SPWM控制及双闭环控制技术,同时也指出了常见问题及解决方案。
内容概要:本文探讨了市场模式下光伏用户群体的电能共享与需求响应模型。研究指出,通过集群方式实现电能共享能够为光伏用户提供更高的经济效益。文中介绍了基于光伏电能供需比(SDR)的内部价格模型,用于合理确定电能交易价格;以及用户参与需求响应(DR)的效用成本模型,旨在平衡经济性和舒适度。此外,文章还讨论了非合作博弈与分布式优化算法的应用,确保用户在现有电价机制下实现效用最大化。最终,通过实际算例验证了模型的有效性,结果显示整体用电成本降低,光功率互用水平提高。 适合人群:对光伏能源管理、智能电网、需求响应等领域感兴趣的科研人员和技术开发者。 使用场景及目标:适用于研究和开发光伏用户群的电能管理和需求响应系统,目标是提高清洁能源利用率,降低用电成本,增强系统的稳定性和效率。 其他说明:文章不仅提供了理论模型,还包括具体的Matlab代码实现,便于读者理解和实践。
基于51单片机protues仿真的烘干机控制系统(仿真图、源代码、AD原理图、流程图) 设计一款以单片机作为主控的便于携带的衣物快速烘干装置,具有定时烘干、过热保护等功能。 1、利用电机带动风扇,电热丝加热,实现热空气在烘干袋中流动,促进衣物快速干燥。 2、烘干袋中带有温度和湿度传感器,实时监测,保证安全的同时可以调节相关参数满足用户烘干需求。 3、设置一个总开关,有温湿度传感器,有显示屏可以实时监测数据 4、具有定时功能,温湿度超出范围自动断电。 5、仿真图、源代码、AD原理图、流程图;
内容概要:本文详细介绍了利用Matlab实现低秩矩阵分解的方法,特别针对图像和信号处理中的杂波去除问题。文中首先解释了为何选择低秩矩阵分解这一方法,即很多实际数据矩阵虽然看起来复杂,但实际上具有低维结构,可以通过分解为低秩矩阵和稀疏矩阵来分别表示主要结构和杂波。接着展示了具体的Matlab代码实现,包括参数设置、初始化、迭代更新规则以及收敛条件的检查。此外,还提供了多个应用场景的具体实例,如处理含噪图像、老照片修复等,并讨论了一些优化技巧,如采用随机SVD提高效率。 适合人群:从事图像处理、信号处理的研究人员和技术开发者,尤其是对低秩矩阵分解感兴趣的学者。 使用场景及目标:适用于需要从含噪数据中提取有用信息的各种场合,如医学影像、遥感图像、音频信号等领域。目的是通过去除杂波,提高数据质量,增强后续分析的有效性和准确性。 其他说明:文中不仅给出了完整的代码示例,还深入探讨了各个步骤背后的数学原理,帮助读者理解算法的工作机制。同时提醒使用者注意处理大规模数据时可能出现的问题及解决方案。
内容概要:本文详细介绍了利用LS-DYNA进行轿车碰撞仿真的方法和技术要点,特别关注安全气囊在碰撞过程中对驾驶员的保护作用。文章首先解释了K文件中关于气囊配置的关键参数设定,如气囊起爆逻辑、接触定义、摩擦系数等。接着探讨了如何通过特定的输出设置来获取驾驶员关键节点的速度、加速度以及力的变化情况,并展示了如何使用Python脚本处理仿真结果,评估头部伤害指数(HIC)和其他重要指标。此外,文中还提到了一些实际案例,比如调整气囊泄气孔尺寸对胸腔压缩量的影响,以及如何识别并解决仿真中可能出现的问题。 适合人群:从事车辆安全研究的专业人士、碰撞仿真工程师、汽车制造商的研发团队成员。 使用场景及目标:适用于希望深入了解安全气囊工作原理及其对乘员保护效果的技术人员;旨在提高车辆安全性设计水平,优化安全气囊及其他被动安全系统的性能。 其他说明:文章不仅提供了理论指导,还包括了许多实用的操作技巧和注意事项,对于初次接触此类仿真的读者尤其有帮助。同时强调了参数选择的重要性,指出即使是细微的变化也可能导致显著不同的结果。
内容概要:本文详细介绍了如何利用Simulink和Matlab构建涡喷发动机动态模型,特别是采用容腔法对发动机各个关键部件进行建模。文章首先解释了容腔法的基本思想及其优势,接着展示了具体模块(如进气道、压气机、燃烧室、涡轮、尾喷管等)的数学模型和相应的Matlab函数实现。文中还探讨了扰动模拟的方法,包括高度、马赫数以及燃油量的扰动,并提供了具体的代码示例。此外,作者分享了一些调试技巧和常见错误,强调了模型参数调整的重要性。最后,通过一系列可视化图表展示了模型的动态响应特性。 适合人群:航空航天工程领域的研究人员和技术人员,尤其是从事航空发动机设计、仿真和优化工作的专业人士。 使用场景及目标:适用于需要深入了解涡喷发动机构造及其动态特性的场合,帮助工程师们更好地理解和预测发动机在不同工况下的行为表现,从而改进控制系统的设计和提高飞行安全性。 其他说明:文章不仅提供了理论知识,还包括了大量的实用代码段和实践经验,使得读者能够动手实践并深入理解所讨论的内容。
内容概要:本文详细介绍了利用Matlab/Simulink进行LLC并网/离网逆变器的建模与仿真。主要内容涵盖主电路设计(LLC谐振腔、全桥逆变)、坐标变换(abc转dq)、双闭环控制(电流电压环)、调制方法(SVPWM vs SPWM)以及各种优化技巧。文中强调了锁相环(PLL)的应用、参数整定、死区时间设置、谐波抑制等关键技术点,并提供了具体的MATLAB代码示例。通过这些技术手段,实现了并网模式下THD小于3%,离网模式下电压畸变率不超过1.8%的优异性能。 适合人群:从事电力电子、新能源发电领域的研究人员和技术人员,尤其是对逆变器设计和仿真感兴趣的工程师。 使用场景及目标:适用于希望深入了解LLC逆变器工作原理及其仿真优化的人群。目标是在实际应用中提高逆变器的效率和稳定性,减少谐波失真,确保系统的可靠性和高性能。 其他说明:文章不仅提供了详细的理论解释,还分享了许多实际调试经验和代码片段,帮助读者更好地理解和掌握相关技术。
内容概要:本文详细介绍了基于STC8H1K08(8051内核)的无刷电机驱动方案,涵盖硬件设计和软件实现两个方面。硬件部分强调了PCB布局的优化,如三明治结构、2oz铜厚处理大电流路径以及霍尔接口设计。软件部分则深入探讨了GPIO初始化、状态机设计、霍尔信号处理、反电动势检测等关键技术点。此外,文中提供了详细的代码示例,展示了如何通过条件编译实现霍尔有感和无感模式之间的快速切换。 适合人群:具有一定电子电路和嵌入式编程基础的技术人员,尤其是从事电机控制系统开发的工程师。 使用场景及目标:适用于需要开发高效、可靠的无刷电机驱动系统的项目,旨在帮助开发者理解和掌握STC8H1K08在无刷电机驱动方面的应用,提高开发效率和产品质量。 其他说明:文中不仅分享了许多实践经验和技术细节,还提供了一些常见问题的解决方案,如ADC采样误差、MOS管发热等问题。这些内容有助于开发者避开常见的陷阱,顺利完成项目开发。
内容概要:本文详细介绍了基于Matlab的燃料电池混合动力系统中有限状态机(FSM)能量管理方法的设计与实现。首先解释了有限状态机的基础概念及其在燃料电池混合动力系统中的应用背景。接着展示了具体的Matlab代码实现,包括状态定义、状态转移逻辑和能量分配策略。文中通过多个代码片段演示了如何根据电池荷电状态(SOC)、燃料电池功率等因素确定系统的工作状态,并合理分配能量。此外,作者分享了一些调试经验和优化技巧,如滞环控制、自愈机制等,确保系统的稳定性和高效性。最后,通过仿真验证了该方法的有效性,提高了系统效率和电池寿命。 适合人群:从事新能源汽车、燃料电池技术和控制系统开发的研究人员和技术人员。 使用场景及目标:适用于需要优化燃料电池混合动力系统能量管理策略的研发项目,旨在提高系统的效率、稳定性和安全性。 其他说明:文中提供的Matlab代码可以直接运行,便于读者理解和实践。同时,作者强调了简单可靠方案的实际价值,尤其是在面对复杂的工业应用场景时。
内容概要:本文详细介绍了利用Matlab/Simulink实现基于无迹扩展卡尔曼滤波(UKF/EKF)的路面附着系数估计方法。首先,通过Dugoff轮胎模型构建非线性轮胎力计算模块,考虑了滑移率和垂向载荷的影响。接着,建立了7自由度整车模型,涵盖车身横摆、侧倾、四个轮子旋转以及质心运动。重点讨论了UKF和EKF模块的具体配置,包括状态方程、观测方程、雅可比矩阵的生成及噪声协方差矩阵的设定。通过对不同工况下的仿真测试,展示了UKF在处理强非线性问题时的优势,特别是在低附着路面和急加速情况下表现更为出色。 适合人群:从事车辆动力学研究、自动驾驶系统开发及相关领域的工程师和技术人员。 使用场景及目标:适用于需要精确估计路面附着系数的应用场合,如ABS、ESP等底盘电控系统的优化设计。目标是提高车辆行驶的安全性和稳定性。 其他说明:文中提供了详细的建模步骤和参数选择建议,有助于读者快速掌握并应用于实际项目中。同时,强调了UKF相较于EKF在某些复杂工况下的优越性,但也在实时性方面进行了比较。
内容概要:本文详细介绍了基于滑模(SMC)和H无穷控制相结合的方法应用于永磁直线同步电机(PMLSM)控制的Matlab程序设计。首先阐述了PMLSM的基本数学模型及其运动方程,随后深入讲解了滑模控制的设计原理,包括滑模面的选择和控制律的计算。接着讨论了H无穷控制的目标和实现方式,特别是利用Matlab中的hinfsyn函数进行控制器设计。文中给出了完整的程序框架,展示了如何将这两种控制方法结合起来,以提高系统的鲁棒性和抗干扰能力。此外,还提供了具体的参数设置建议、控制量融合策略以及针对参数摄动和外部扰动的实际测试案例。 适合人群:从事电机控制领域的研究人员和技术人员,尤其是那些对高级控制理论感兴趣并希望通过Matlab实现复杂控制算法的人。 使用场景及目标:适用于需要高精度位置控制的应用场合,如工业自动化生产线、精密加工设备等。主要目标是通过结合滑模控制和H无穷控制的优势,克服传统控制方法难以应对的非线性因素和不确定性的挑战,从而获得更好的动态响应和平稳性。 其他说明:文中不仅提供了详细的理论解释,还有丰富的代码实例供读者参考。对于初学者来说,可以通过逐步理解和修改提供的代码来掌握这一先进的控制技术。同时提醒读者注意离散化处理的重要性,避免因不当的操作导致数值不稳定的问题。