手撕spring框架(4)
相关系列
手撕spring框架(1)
手撕spring框架(2)
手撕spring框架(3)
本节主要是讲通过BeanNameAware获取在容器中配置的Bean名称,使得Bean能够获取自身在容器中的标识。
简介
BeanNameAware接口在spring中是一个回调接口,它提供了一个用于设置Bean名称的方法。当一个Bean实现了BeanNameWaare接口时,在该Bean实例被实例化后,Spring容器会调用setBeanName方法,并将该Bean在Spring容器中的名称作为参数传递过去。
以下是示例代码:
package com.spring;
public interface BeanNameAware {
void setBeanName(String beanName);
}
使用
在UserService类中实现BeanNameAware中的setBeanName方法,源码如下:
package com.dzend.service;
import com.spring.Autowired;
import com.spring.BeanNameAware;
import com.spring.Component;
@Component(value = "userService")
public class UserService implements UserInterface, BeanNameAware {
private String beanName;
@Autowired
private OrderService orderService;
@DzendValue("xxxxx")
private String test;
@Override
public void test() {
System.out.println(test);
}
public OrderService getOrderService() {
return orderService;
}
@Override
public void setBeanName(String beanName) {
this.beanName = beanName;
}
}
调整DzendApplicationContext类中的createBean方法,在BeanPostProcessor初始化下加下以下代码:
if(instance instanceof BeanNameAware){
((BeanNameAware) instance).setBeanName(beanName);
}
最后DzendApplicationContext代码如下:
package com.spring;
import java.beans.Introspector;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class DzendApplicationContext {
private Class<?> configClass;
private Map<String,BeanDefinition> beanDefinitionMap= new HashMap<>();
private Map<String, Object> singletonObjects=new HashMap<>();
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
public DzendApplicationContext(Class configClass) {
this.configClass=configClass;
scan(configClass);
}
private void scan(Class configClass) {
if(configClass.isAnnotationPresent(ComponentScan.class)){
ComponentScan componentScan = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScan.value();
path = path.replace(".","/");
ClassLoader classLoader = DzendApplicationContext.class.getClassLoader();
URL resource = classLoader.getResource(path);
try {
path = URLDecoder.decode(path, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
File file = null;
try {
file = new File( URLDecoder.decode(resource.getFile(), "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
if(file.isDirectory()){
for (File f : file.listFiles()) {
String absolutePath = f.getAbsolutePath();
absolutePath = absolutePath.substring(absolutePath.indexOf("com"),absolutePath.indexOf(".class"));
absolutePath=absolutePath.replace("\\",".");
try {
Class<?> clazz = classLoader.loadClass(absolutePath);
if (clazz.isAnnotationPresent(Component.class)) {
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}
Component componentAnnotaion = clazz.getAnnotation(Component.class);
String beanName= componentAnnotaion.value();
if("".equals(beanName)){
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
String value = scopeAnnotation.value();
beanDefinition.setScope(value);
}else{
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName,beanDefinition);
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
}
}
}
}
public Object getBean(String beanName){
if(!beanDefinitionMap.containsKey(beanName)){
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(beanDefinition.getScope().equals("singleton")){
Object singletonObject = singletonObjects.get(beanName);
if(singletonObject == null){
singletonObject = createBean(beanName,beanDefinition);
singletonObjects.put(beanName,singletonObject);
}
return singletonObject;
}else{
//原型
Object prototypeBean = createBean(beanName, beanDefinition);
return prototypeBean;
}
}
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
Object instance = null;
try {
instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
if(field.isAnnotationPresent(Autowired.class)){
field.setAccessible(true);
field.set(instance,getBean(field.getName()));
}
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
}
if(instance instanceof BeanNameAware){
((BeanNameAware) instance).setBeanName(beanName);
}
if(instance instanceof InitializingBean){
((InitializingBean) instance).afterPropertiesSet();
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance,beanName);
}
} catch (InstantiationException e) {
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
} catch (InvocationTargetException e) {
throw new RuntimeException(e);
} catch (NoSuchMethodException e) {
throw new RuntimeException(e);
}
return instance;
}
}