相比较XML配置来说,当项目过大的时候难以维护。Spring还有一种支持0配置的注解式编程。
老套路还是先跑个栗子
Maven 依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.1.7.RELEASE</version>
</dependency>
定义一个类
@Component
public class User {
private String userName;
private Integer email;
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Integer getEmail() {
return email;
}
public void setEmail(Integer email) {
this.email = email;
}
public String sayHello() {
return "hello";
}
}
bean配置文件
@Configuration
public class Configuration {
@Bean
public User user() {
return new User();
}
}
测试类
public class AnnotationConfigApplicationContextDemo {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(Configuration.class);
User user = applicationContext.getBean(User.class);
String s = user.sayHello();
System.out.println(s);
}
}
入口类AnnotationConfigApplicationContext
看下整体结构
![](https://img.haomeiwen.com/i19002306/46fe87db4d4b48a4.png)
AnnotationConfigApplicationContext方法,注册config、bean;配置scan大多方法功能类似
![](https://img.haomeiwen.com/i19002306/9a01e84ca61eca01.png)
四个构造方法:
public AnnotationConfigApplicationContext() {
//初始化Bean的读取和扫描器
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(DefaultListableBeanFactory beanFactory) {
//父类中this.beanFactory = new DefaultListableBeanFactory() 创建BeanFactory
super(beanFactory);
this.reader = new AnnotatedBeanDefinitionReader(this);
this.scanner = new ClassPathBeanDefinitionScanner(this);
}
public AnnotationConfigApplicationContext(Class<?>... annotatedClasses) {
this();
//注册bean配置类
register(annotatedClasses);
//刷新上下文
refresh();
}
public AnnotationConfigApplicationContext(String... basePackages) {
this();
//配置扫描包的路径
scan(basePackages);
refresh();
}
new AnnotatedBeanDefinitionReader 逻辑到《Spring注解式编程之AnnotatedBeanDefinitionReader》这里就不过多解释,还是看下主流程。
核心方法 AnnotatedBeanDefinitionReader.doRegisterBean()
<T> void doRegisterBean(Class<T> annotatedClass, @Nullable Supplier<T> instanceSupplier, @Nullable String name,
@Nullable Class<? extends Annotation>[] qualifiers, BeanDefinitionCustomizer... definitionCustomizers) {
//将配置类信息转成AnnotatedGenericBeanDefinition
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
//@Conditional装配条件判断是否跳过注册
if (this.conditionEvaluator.shouldSkip(abd.getMetadata())) {
return;
}
//设置回调
abd.setInstanceSupplier(instanceSupplier);
//解析Bean的作用域,默认singleton
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
//生成bean配置类的name
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
//通用注解解析 Lazy, primary DependsOn, Role ,Description这五个注解
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
//@Qualifier特殊限定符处理
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class == qualifier) {
//如果配置@Primary 则@Autowired 注入首选
abd.setPrimary(true);
}
else if (Lazy.class == qualifier) {
//如果配置@Lazy 则IOC容器启动时不创建bean
abd.setLazyInit(true);
}
else {
//其他注解加到abd中
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
//自定义注册Bean,在applicationContext创建后使用lambda创建
//applicationContext.registerBean(User.class, () -> new User());
for (BeanDefinitionCustomizer customizer : definitionCustomizers) {
customizer.customize(abd);
}
//根据BeanName和abd封装一个BeanDefinitionHolder
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
//创建代理对象
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
//注册Bean ->DefaultListableBeanFactory.registerBeanDefinition()
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
相比较XML方式,只有解析XML变成解析注解,最后DefaultListableBeanFactory.registerBeanDefinition() 将bean定义信息已beanname,beandifine键值对的形式注册到ioc容器中。
refresh()
public void refresh() throws BeansException, IllegalStateException {
synchronized (this.startupShutdownMonitor) {
// Prepare this context for refreshing.
prepareRefresh();
// Tell the subclass to refresh the internal bean factory.
ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
// Prepare the bean factory for use in this context.
prepareBeanFactory(beanFactory);
try {
// Allows post-processing of the bean factory in context subclasses.
postProcessBeanFactory(beanFactory);
// Invoke factory processors registered as beans in the context.
invokeBeanFactoryPostProcessors(beanFactory);
// Register bean processors that intercept bean creation.
registerBeanPostProcessors(beanFactory);
// Initialize message source for this context.
initMessageSource();
// Initialize event multicaster for this context.
initApplicationEventMulticaster();
// Initialize other special beans in specific context subclasses.
onRefresh();
// Check for listener beans and register them.
registerListeners();
// Instantiate all remaining (non-lazy-init) singletons.
finishBeanFactoryInitialization(beanFactory);
// Last step: publish corresponding event.
finishRefresh();
}
catch (BeansException ex) {
if (logger.isWarnEnabled()) {
logger.warn("Exception encountered during context initialization - " +
"cancelling refresh attempt: " + ex);
}
// Destroy already created singletons to avoid dangling resources.
destroyBeans();
// Reset 'active' flag.
cancelRefresh(ex);
// Propagate exception to caller.
throw ex;
}
finally {
// Reset common introspection caches in Spring's core, since we
// might not ever need metadata for singleton beans anymore...
resetCommonCaches();
}
}
}
1、刷新预处理
2、获取刷新后的内部工厂
3、prepareBeanFactory主要完成beanFactory的一些属性设置
4、invokeBeanFactoryPostProcessors执行bean工厂后置处理器
5、注册BeanPostProcessor,拦截Bean创建过程
6、初始化MessageSource组件
7、初始化事件派发器
8、注册监听器
9、初始化剩下所有的单例Bean
10、完成BeanFactory创建工作
网友评论