Spring Ioc-注解支持
# 一、注解支持
# 1、Spring中的注解
在日常开发中,通常我们采用注解方式来进行Bean的注入,例如如下代码:
public class SysLogController {
@Autowired
private SysLogServiceImpl sysLogService;
}
这样的好处在于,不再需要在XML配置文件中进行使用ref属性,极大地增加了开发效率。
# 2、支持注解
现在我们手写的框架需要支持注解,就需要Bean的某个阶段去解释注解。
Bean的整个过程,其实我们可以简单将其分为:
- 实例化前
- 实例化中
- 实例化后
这三个阶段,我们要给程序提供一个入口,来方便我们进行相应的操作,可以考虑调用一个Bean处理器Processor,由处理器来解释注解。
public interface BeanPostProcessor {
/**
* Bean初始化之前
*
* @param bean Bean
* @param beanName Bean id
*/
Object postProcessBeforeInitialization(Object bean, String beanName);
/**
* Bean初始化之后
*
* @param bean Bean
* @param beanName Bean id
*/
Object postProcessAfterInitialization(Object bean, String beanName);
}
接下来我们来定义注解:
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
现在我们需要利用反射来获取所有标注了Autowired 注解的成员变量,把它初始化成一个 Bean,然后注入属性。现在我们来实现BeanPostProcessor
接口:
public class AutowiredAnnotationBeanPostProcessor implements BeanPostProcessor {
private AutowireCapableBeanFactory beanFactory;
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
Object result = bean;
Class<?> clazz = bean.getClass();
Field[] fields = clazz.getDeclaredFields();
if (fields != null) {
for (Field field : fields) {
boolean isAutowired = field.isAnnotationPresent(me.xu.spring.beans.factory.annotation.Autowired.class);
if (isAutowired) {
String fieldName = field.getName();
try {
Object autowiredObj = this.getBeanFactory().getBean(fieldName);
field.setAccessible(true);
field.set(bean, autowiredObj);
} catch (BeansException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
}
return result;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
return null;
}
public AutowireCapableBeanFactory getBeanFactory() {
return beanFactory;
}
public void setBeanFactory(AutowireCapableBeanFactory beanFactory) {
this.beanFactory = beanFactory;
}
}
这段代码核心思想:就是判断每一个属性是不是带有 Autowired 注解,如果有,就根据属性名获取 Bean。
# 3、抽象工厂类
在上段代码中,我们引入了AutowireCapableBeanFactory
,这个工厂是专门处理注解的工厂,之前的SimpleBeanFactory
是专门处理加载Bean逻辑的,现在我们需要为这些工厂抽象出一个抽象类工厂,去实现一些默认的功能:
public abstract class AbstractBeanFactory extends DefaultSingletonBeanRegistry implements BeanFactory, BeanDefinitionRegistry {
private Map<String, BeanDefinition> beanDefinitions = new ConcurrentHashMap<>(256);
private List<String> beanDefinitionNames = new ArrayList<>();
/**
* Bean半成品
*/
private final Map<String, Object> earlySingletonObjects = new HashMap<String, Object>(16);
public AbstractBeanFactory() {
}
public void refresh() {
for (String beanName : beanDefinitionNames) {
try {
getBean(beanName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public Object getBean(String beanName) throws BeansException {
// 先尝试直接单例获取
Object singleton = getSingleton(beanName);
// 如果没有,开始实例化Bean
if (singleton == null) {
// 尝试从Bean半成品中获取
singleton = earlySingletonObjects.get(beanName);
if (singleton == null) {
// 如果半成品也没有,创建Bean实例并注册
// 获取Bean定义
BeanDefinition beanDefinition = beanDefinitions.get(beanName);
try {
// 反射实例化Bean
singleton = createBean(beanDefinition);
// 注册单例Bean
registerSingleton(beanName, singleton);
// Bean处理器
//step 1 : 初始化之前
applyBeanPostProcessorsBeforeInitialization(singleton, beanName);
//step 2 : 初始化中
if (beanDefinition.getInitMethodName() != null && !beanDefinition.getInitMethodName().equals("")) {
invokeInitMethod(beanDefinition, singleton);
}
//step 3 : 初始化后
applyBeanPostProcessorsAfterInitialization(singleton, beanName);
} catch (Exception e) {
e.printStackTrace();
}
}
}
return singleton;
}
private void invokeInitMethod(BeanDefinition beanDefinition, Object singleton) {
Class<?> clz = singleton.getClass();
Method method = null;
try {
method = clz.getMethod(beanDefinition.getInitMethodName());
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
try {
method.invoke(singleton);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
private Object createBean(BeanDefinition beanDefinition) {
// 类名
Class<?> clz = null;
// 创建半成品Bean
Object obj = doCreateBean(beanDefinition);
// 放入半成品Bean集合中
earlySingletonObjects.put(beanDefinition.getId(), obj);
try {
// 反射获取类名
clz = Class.forName(beanDefinition.getClassName());
} catch (Exception e) {
e.printStackTrace();
}
// 处理配置参数(属性注入)
handleProperty(beanDefinition, clz, obj);
return obj;
}
private Object doCreateBean(BeanDefinition beanDefinition) {
Class clz = null;
Object obj = null;
Constructor constructor = null;
try {
clz = Class.forName(beanDefinition.getClassName());
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
// 处理构造器参数
ConstructorArgumentValues constructorArgumentValues = beanDefinition.getConstructorArgumentValues();
if (!constructorArgumentValues.isEmpty()) {
// 参数类型
Class<?>[] paramTypes = new Class<?>[constructorArgumentValues.getArgumentCount()];
// 参数值
Object[] paramValues = new Object[constructorArgumentValues.getArgumentCount()];
// 遍历构造器参数集合
for (int i = 0; i < constructorArgumentValues.getArgumentCount(); i++) {
ConstructorArgumentValue constructorArgumentValue = constructorArgumentValues.getIndexedArgumentValue(i);
if ("String".equals(constructorArgumentValue.getType()) || "java.lang.String".equals(constructorArgumentValue.getType())) {
paramTypes[i] = String.class;
paramValues[i] = constructorArgumentValue.getValue();
} else if ("Integer".equals(constructorArgumentValue.getType()) || "java.lang.Integer".equals(constructorArgumentValue.getType())) {
paramTypes[i] = Integer.class;
paramValues[i] = Integer.valueOf((String) constructorArgumentValue.getValue());
} else if ("int".equals(constructorArgumentValue.getType())) {
paramTypes[i] = int.class;
paramValues[i] = Integer.valueOf((String) constructorArgumentValue.getValue()).intValue();
} else {
paramTypes[i] = String.class;
paramValues[i] = constructorArgumentValue.getValue();
}
}
try {
// 获取构造函数
constructor = clz.getConstructor(paramTypes);
// 利用构造函数反射实例化Bean
obj = constructor.newInstance(paramValues);
} catch (NoSuchMethodException | InvocationTargetException | IllegalArgumentException | SecurityException e) {
e.printStackTrace();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
} else {
try {
obj = clz.newInstance();
} catch (InstantiationException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
return obj;
}
private void handleProperty(BeanDefinition beanDefinition, Class<?> clz, Object obj) {
// 处理属性
PropertyValues propertyValues = beanDefinition.getPropertyValues();
if (!propertyValues.isEmpty()) {
// 遍历属性集合
for (int i = 0; i < propertyValues.size(); i++) {
PropertyValue propertyValue = propertyValues.getPropertyValueList().get(i);
String pName = propertyValue.getName();
String pType = propertyValue.getType();
Object pValue = propertyValue.getValue();
boolean isRef = propertyValue.isRef();
Class<?>[] paramTypes = new Class<?>[1];
Object[] paramValues = new Object[1];
// 如果是基本类型
if (!isRef) {
// 参数类型处理
if ("String".equals(pType) || "java.lang.String".equals(pType)) {
paramTypes[0] = String.class;
} else if ("Integer".equals(pType) || "java.lang.Integer".equals(pType)) {
paramTypes[0] = Integer.class;
} else if ("int".equals(pType)) {
paramTypes[0] = int.class;
} else {
paramTypes[0] = String.class;
}
// 参数具体数值
paramValues[0] = pValue;
} else {
// 如果是引用类型
try {
paramTypes[0] = Class.forName(pType);
// 再次调用getBean方法
paramValues[0] = getBean((String)pValue);
} catch (ClassNotFoundException | BeansException e) {
throw new RuntimeException(e);
}
}
// 方法名字
String methodName = "set" + pName.substring(0, 1).toUpperCase() + pName.substring(1);
Method method = null;
try {
// 获取到方法
method = clz.getMethod(methodName, paramTypes);
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
try {
// 反射调用方法
method.invoke(obj, paramValues);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
}
}
}
@Override
public Boolean containsBean(String name) {
return containsSingleton(name);
}
@Override
public void registerBean(String beanName, Object obj) {
registerSingleton(beanName, obj);
}
@Override
public boolean isSingleton(String name) {
return beanDefinitions.get(name).isSingleton();
}
@Override
public boolean isPrototype(String name) {
return beanDefinitions.get(name).isPrototype();
}
@Override
public Class getType(String name) {
return beanDefinitions.get(name).getClass();
}
@Override
public void registerBeanDefinition(String name, BeanDefinition beanDefinition) {
beanDefinitions.put(name, beanDefinition);
beanDefinitionNames.add(name);
if (!beanDefinition.isLazyInit()) {
try {
getBean(name);
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Override
public void removeBeanDefinition(String name) {
beanDefinitions.remove(name);
beanDefinitionNames.remove(name);
removeSingleton(name);
}
@Override
public BeanDefinition getBeanDefinition(String name) {
return beanDefinitions.get(name);
}
@Override
public boolean containsBeanDefinition(String name) {
return beanDefinitions.containsKey(name);
}
abstract public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException;
abstract public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException;
}
我们把之前的方法比如getBean
、createBean
、doCreateBean
方法都抽象在这个类中,其中getBean
方法中有如下核心代码:
//step 1 : 初始化之前
applyBeanPostProcessorsBeforeInitialization(singleton, beanName);
//step 2 : 初始化中
if (beanDefinition.getInitMethodName() != null && !beanDefinition.getInitMethodName().equals("")) {
invokeInitMethod(beanDefinition, singleton);
}
//step 3 : 初始化后
applyBeanPostProcessorsAfterInitialization(singleton, beanName);
我们为这三个阶段提供了入口,定义了抽象方法 applyBeanPostProcessorBeforeInitialization 与 applyBeanPostProcessorAfterInitialization,由名字可以看出,分别是在 Bean 处理类初始化之前和之后执行的方法。这两个方法交给具体的继承类去实现。
# 4、AutowireCapableBeanFactory
在实现了抽象类工厂之后,我们就需要实现注解处理工厂类,让其继承抽象工厂类:
public class AutowireCapableBeanFactory extends AbstractBeanFactory{
private final List<AutowiredAnnotationBeanPostProcessor> beanPostProcessorList = new ArrayList<>();
public void addBeanPostProcessor(AutowiredAnnotationBeanPostProcessor beanPostProcessor) {
beanPostProcessorList.remove(beanPostProcessor);
beanPostProcessorList.add(beanPostProcessor);
}
public int getBeanPostProcessorCount() {
return beanPostProcessorList.size();
}
public List<AutowiredAnnotationBeanPostProcessor> getBeanPostProcessors() {
return beanPostProcessorList;
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (AutowiredAnnotationBeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
beanPostProcessor.setBeanFactory(this);
result = beanPostProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) throws BeansException {
Object result = existingBean;
for (AutowiredAnnotationBeanPostProcessor beanPostProcessor : getBeanPostProcessors()) {
beanPostProcessor.setBeanFactory(this);
result = beanPostProcessor.postProcessBeforeInitialization(result, beanName);
if (result == null) {
return result;
}
}
return result;
}
}
该类中,首先使用了一个集合来存储Bean处理器,并提供对该集合一些简单的数据操作方法。
其次,实现了两个具体方法,思想也很简单,遍历Bean处理器集合,执行Bean处理器处理Bean的逻辑。
# 5、XML上下文代码修改
现在我们需要把ClassPathXmlApplicationContext
中的工厂对象修改成新的工厂对象:
public class ClassPathXmlApplicationContext implements BeanFactory {
AutowireCapableBeanFactory beanFactory;
public ClassPathXmlApplicationContext(String fileName, boolean isRefresh) {
// 获取资源
Resource resource = new ClassPathXmlResource(fileName);
// 解析资源
//SimpleBeanFactory beanFactory = new SimpleBeanFactory();
// 创建处理注解的工厂对象
AutowireCapableBeanFactory beanFactory = new AutowireCapableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(beanFactory);
reader.loadBeanDefinitions(resource);
this.beanFactory = beanFactory;
if (!isRefresh) {
try {
refresh();
} catch (BeansException e) {
throw new RuntimeException(e);
}
}
}
public void refresh() throws BeansException, IllegalStateException {
// 注册处理器
registerBeanPostProcessors(this.beanFactory);
// 初始化Bean容器
onRefresh();
}
private void onRefresh() {
this.beanFactory.refresh();
}
}
在新的refresh
方法中,会先进行处理器的注册,这样BeanFactory中就有了Bena处理器,接着会调用onRefresh()
方法,这个方法会去执行抽象工厂类的refresh
方法。
# 二、案例测试
# 1、XML配置
<?xml version="1.0" encoding="UTF-8" ?>
<bean id = "CService" class="me.xu.spring.test.demo03.CServiceImpl"/>
<bean id = "FService" class="me.xu.spring.test.demo03.FServiceImpl"/>
</beans>
# 2、Bean类
public interface CService {
void C();
}
public class CServiceImpl implements CService{
@Override
public void C() {
System.out.println("子服务方法");
}
}
public interface FService {
void F();
void useC();
}
public class FServiceImpl implements FService{
@Autowired
private CService CService;
@Override
public void F() {
System.out.println("父服务方法");
}
@Override
public void useC() {
CService.C();
}
}
# 3、测试代码
public class Demo {
public static void main(String[] args) throws BeansException {
ClassPathXmlApplicationContext classPathXmlApplicationContext = new ClassPathXmlApplicationContext("demo.xml");
FService fService = (FService)classPathXmlApplicationContext.getBean("FService");
fService.F();
fService.useC();
}
}
// output
// 父服务方法
// 子服务方法
# 三、总结
通过这节的代码,我们使用了注解去加载我们所需要的Bean,流程如下:
- 抽象工厂在加载Bean之前,会去注册一个Bean处理器
- 加载Bean的时候,预留三个入口,分别是Bena实例化之前、Bean实例化中、Bean实例化之后
- 在Bean实例化之前,遍历Bean处理器集合,执行处理器逻辑
- 处理器逻辑很简单,获取Bean所自定义的字段,判断字段上是否有对应的注解,如果有注解,则获取字段名称,根据名称从BeanFactoy中获取Bean对象,然后设置该字段可访问以及该字段所对于的Bean