创建maven项目,导入spring相关的包的此处省略…
package com.mp.aop.annotation.day02.config;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Component;
@ComponentScan("com.mp.aop.annotation.day02.service")
public class MyConfig {
}
此处配置@ComponentScan 注解扫描指定的package及其子包;将其所有实现了@bean @Component 等注解的类统一交由sping IOC来管理
准备程序入口,访问整体的spring bean
package com.mp.aop.annotation.day02;
import com.mp.aop.annotation.day02.config.MyConfig;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import java.util.stream.Stream;
public class MainManager {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
// 已经完成了整个spring容器的初始化;这里先简单的获取下,我们容器负责管理的所有bean
Stream.of(context.getBeanDefinitionNames()).forEach(s -> System.out.println(s));
}
}
org.springframework.context.annotation.internalConfigurationAnnotationProcessor
org.springframework.context.annotation.internalAutowiredAnnotationProcessor
org.springframework.context.annotation.internalCommonAnnotationProcessor
org.springframework.context.event.internalEventListenerProcessor
org.springframework.context.event.internalEventListenerFactory
myConfig
可以看到,刚开始程序会创建6个bean,其中5个为spring容器需要初始化(后面会详细介绍分析);另外一个为我们添加的配置类.
package com.mp.aop.annotation.day02.service;
import com.mp.aop.annotation.MyAnnotation;
import lombok.Data;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
/**
* ClassName: Person
* Function: TODO
* Date: 2020-04-11 21:34
* author mp
* version V1.0
*/
@Component
@Data
public class Person {
static {
System.out.println("this is person Static");
}
@Value("mp")
String name;
@Value("10")
int age;
String addr;
public Person(String name, int age,String addr) {
this.name = name;
this.age = age;
this.addr = addr;
System.out.println("constuctor ...");
}
public void setName(String name) {
this.name = name;
System.out.println("person.setName。。。。"+name);
}
public void setAge(int age) {
this.age = age;
System.out.println("person.setAge: "+ age);
}
public void setAddr(String addr) {
this.addr = addr;
System.out.println("person.setAddr: "+addr);
}
public Person() {
System.out.println("constructor null");
}
public void p1(){
System.out.println("this name:"+this.name+" this age:"+this.age);
}
/*@Bean("p1")
public Person getPerson(){
System.out.println("自定义...");
return new Person("zhuge",100,"wuhan");
}*/
}
再次执行,main入口程序,我们将看到,spring初始化的bean会多了一个person
在main程序中,获取car这个bean,打印其信息
// 获取car这个bean对象,打印其对象信息
System.out.println(context.getBean(Person.class));
打印结果:
Person(name=mp, age=10, addr=null)
public AnnotationConfigApplicationContext(Class>... annotatedClasses) {
this(); // 构造器,初始化AnnotatedBeanDefinitionReader和 ClassPathBeanDefinitionScanner并准备好5个sping系统需要的BeanDefinition.
register(annotatedClasses); // 注册我们的配置类AppConfig 对应的BeanDefinition,此时我们的beanFactory中有6个beanDefinitionName了
refresh(); // 重点流程
}
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); // @1 说明
// 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); // @2 说明
// Last step: publish corresponding event.
finishRefresh(); //
}
- 会创建好spring需要的5个bean
- 根据@ComponentScan扫描的包路径,ClassPathBeanDefinitionScanner 去target根据文件系统找到对应的class文件,并根据是否有注解来判断,决定是否要加入到beanDefinitionNames 列表中,为后面初始化做准备.
- 所以,这里beanDefinitionNames 列表扫描会新增1个person -bean
- 实例化通过包扫描的bean, 实例化person对象,并完成属性注入,重点来了…
Object sharedInstance = getSingleton(beanName); // 这里是否单例池缓存中取对象,由于之前没有创建,所以这里为null,流程继续往下走
mbd.isSingleton() 为默认单例,开始创建实例
后记: 本次我初步梳理流程,后面会完善各个细节.
package com.mp.aop.annotation.day02.config;
import java.lang.annotation.*;
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface MyValue {
String value() default "";
}
package com.mp.aop.annotation.day02.service;
import com.mp.aop.annotation.day02.config.MyValue;
import lombok.Data;
import org.springframework.stereotype.Component;
/**
* ClassName: Car
* Function: TODO
* Date: 2020-04-12 09:12
* author mp
* version V1.0
*/
@Component
@Data
public class Car {
@MyValue(value = "布加迪")
String name;
@MyValue(value = "6666w")
String price;
static {
System.out.println("static car...");
}
}
我这边采用的策略是,在完成spring bean构建之后,通过beanFactory获取对应的bean,做字段的依赖注入
package com.mp.aop.annotation.day02.service;
import com.mp.aop.annotation.day02.config.MyValue;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.SmartInitializingSingleton;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import java.util.stream.Stream;
/**
* ClassName: ServicePostProcess
* Function: TODO
* Date: 2020-04-10 22:59
* author mp
* version V1.0
*/
@Component
public class MyPostProcess implements SmartInitializingSingleton,BeanFactoryPostProcessor {
BeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("this is factory...");
this.beanFactory = beanFactory;
}
@Override
public void afterSingletonsInstantiated() {
System.out.println("process afterSingletons...");
// 处理@MyValue注解
Car car = beanFactory.getBean(Car.class);
Stream.of(Car.class.getDeclaredFields())
.filter(field -> field.getAnnotation(MyValue.class) != null)
.forEach(field -> {
MyValue myValue = field.getAnnotation(MyValue.class);
try {
field.set(car,myValue.value()); // 属性注入.
} catch (IllegalAccessException e) {
e.printStackTrace();
}
// 设置属性
// System.out.println(field.getName());
//
//1. 方法2,反射找到对应的set方法做属性的设置
/*String fieldName = field.getName();
Class> type = field.getType();
String setMethodName = "set".concat(fieldName.substring(0,1).toUpperCase()).concat(fieldName.substring(1));
try {
Method method = Car.class.getMethod(setMethodName, type);
method.invoke(car,myValue.value());
} catch (Exception e) {
e.printStackTrace();
}*/
});
System.out.println("car: "+ car);
}
}
打印结果: Car(name=布加迪, price=6666w) 完成自定义属性注解.
今天先记录到这里,后面再继续细节… 每天进步一点.