如果我们想手动的在特定时机向容器注册beandefinition,为了能根据具体环境设置特定的属性值,比如我们自定义的数据源等;
1、手动注入
定义的类可以实现BeanDefinitionRegistryPostProcessor接口,那么这个类的方法会在配置文件或者被注解的所有类注册完后进行调用;
示例:
package springsrc;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
public class OO implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
}
@Override
public void postProcessBeanDefinitionRegistry(
BeanDefinitionRegistry registry) throws BeansException {
GenericBeanDefinition helloBean = new GenericBeanDefinition();
helloBean.setBeanClass(OOO.class);
// 新增Bean定义
registry.registerBeanDefinition("hello", helloBean);
}
}
调用
package springsrc;
import org.springframework.aop.aspectj.autoproxy.AspectJAwareAdvisorAutoProxyCreator;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.transaction.interceptor.TransactionInterceptor;
public class S {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("bean.xml");// 读取bean.xml中的内容
System.out.println(ctx.getBean("hello"));
}
}
结果:
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
springsrc.OOO@d64342
2、ApplicationContext
利用容器注入的ApplicationContext注入
public class SpringObjectFactory {
private static ApplicationContext applicationContext;
public void register(String beanName,Class<?> beanClass){
BeanDefinitionRegistry beanRegistry = (BeanDefinitionRegistry)applicationContext.getAutowireCapableBeanFactory();
try {
beanRegistry.getBeanDefinition(beanName);
return;
} catch (Exception e) {
GenericBeanDefinition definition = new GenericBeanDefinition();
definition.setBeanClass(beanClass);
definition.setScope(BeanDefinition.SCOPE_SINGLETON);
beanRegistry.registerBeanDefinition(beanName, definition);
}
}
@Autowired
public void setApplicationContext(ApplicationContext appCtx) {
applicationContext = appCtx;
Assert.isTrue(applicationContext.getAutowireCapableBeanFactory() instanceof BeanDefinitionRegistry, "autowireCapableBeanFactory should be BeanDefinitionRegistry");
}
}
3、实现 BeanFactoryPostProcessor
package example;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
public class DemoBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinitionRegistry beanRegistry = (BeanDefinitionRegistry)beanFactory;
//自定义逻辑,注入beandefinition
beanRegistry.registerBeanDefinition("",new GenericBeanDefinition());
}
}
其实只要想办法拿到容器的BeanFactory即 DefaultListableBeanFactory的实例,就可以向容器注入bean定义了
注册BeanDefinition接口声明