IOC(Inversion of Control)控制反转作为Spring的核心思想,在Spring框架中,最核心的概念就是容器,IOC容器是Spring实现IOC的载体,它其实就是一个大工厂,用来管理我们所有的对象以及依赖关系。
- 原理就是通过Java反射技术来实现。
- 通过配置文件或注解来描述类之间的依赖关系。
- 通过配置和反射技术来构建对象和依赖关系。
Spring提供了两种不同类型的容器:
- 最基础、面向Spring框架的BeanFactory。
- 高级的、基于 BeanFactory基础之上、面向开发者的ApplicationContext。
简单实现IOC容器
原理:基于反射技术与工厂模式。
基于XML配置文件实现
核心流程
- 初始化IOC容器。
- 读取配置文件,提取节点。
- 将映射为BeanDefinition,注册到 beanDefinitionMap。
- 将 beanDefinitionMap 中所有的 BeanDefinition 实例化 Bean 对象。
- 设置属性,注入对象之间的依赖关系。
不扯干的,直接上代码,代码就是越肝越爽,肝了,先实现一个丐版吧!!!
pom
<dependencies>
<dependency>
<groupId>dom4j</groupId>
<artifactId>dom4j</artifactId>
<version>1.6.1</version>
</dependency>
<dependency>
<groupId>jaxen</groupId>
<artifactId>jaxen</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>
ApplicationContext
public interface ApplicationContext {
public Object getBean(String beanName);
public Object createBean(BeanDefinition beanDefinition);
}
BeanDefinition
public class BeanDefinition {
private String beanName;
private String className;
private Class beanClass;
private List<Property> properties = new ArrayList<Property>();
public BeanDefinition(){
}
public BeanDefinition(String beanName, String className){
this.beanName = beanName;
this.className = className;
}
public String getBeanName() {
return beanName;
}
public void setBeanName(String beanName) {
this.beanName = beanName;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
public List<Property> getProperties() {
return properties;
}
public void setProperties(List<Property> properties) {
this.properties = properties;
}
public Class getBeanClass() {
return beanClass;
}
public void setBeanClass(Class beanClass) {
this.beanClass = beanClass;
}
}
Property
public class Property {
private String name;
private String value;
private String ref;
public Property(String name, String value, String ref) {
this.name = name;
this.value = value;
this.ref = ref;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getRef() {
return ref;
}
public void setRef(String ref) {
this.ref = ref;
}
}
ClassPathXmlApplicationContext
public class ClassPathXmlApplicationContext implements ApplicationContext {
private String configLocation;
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<String, BeanDefinition>() ;
private Map<String, Object> iocMap = new HashMap<String, Object>();
public ClassPathXmlApplicationContext(String configLocation){
this.configLocation = configLocation;
parseXmlFile();
if(!beanDefinitionMap.isEmpty()){
for(Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()){
String id = entry.getKey();
//在依赖注入的时候,部分bean可能会提前已创建
if(!iocMap.containsKey(id)){
BeanDefinition bean = entry.getValue();
createBean(bean);
}
}
}
}
public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(null == beanDefinition){
throw new RuntimeException("no beanDefinition : " + beanName);
}
Object object = iocMap.get(beanName);
if(null != object){
return object;
} else {
return createBean(beanDefinition);
}
}
public Object createBean(BeanDefinition bean){
Object object = null;
Class cls = null;
String beanName = bean.getBeanName();
String className = bean.getClassName();
List<Property> properties = bean.getProperties();
System.out.println("["+beanName+"] create start>>>>");
//反射生成Class对象
try {
cls = Class.forName(className);
System.out.println("["+beanName+"] class >> :" + cls.toString());
bean.setBeanClass(cls);
} catch (Exception e) {
throw new RuntimeException("reflex class fail:["+beanName+"]" + "\n" +ExceptionUtils.getStackTrace(e));
}
try {
object = cls.newInstance();
} catch (Exception e) {
throw new RuntimeException("class instance fail:["+beanName+"]" + "\n" +ExceptionUtils.getStackTrace(e));
}
//设置属性
if(!properties.isEmpty()){
for(Property property:properties){
//value注入
if(property.getValue() != null){
Method setterMethod = BeanUtils.getSetterMethod(object, property.getName());
try{
setterMethod.invoke(object, property.getValue());
System.out.println("["+beanName+"] set value >> " + property.getName() + ":" + property.getValue());
}catch (Exception e){
throw new RuntimeException("set value fail:["+beanName+"."+property.getName() +"]" + "\n" +ExceptionUtils.getStackTrace(e));
}
}
//依赖注入
if(property.getRef() != null){
Method setterMethod = BeanUtils.getSetterMethod(object, property.getName());
Object refObj = getBean(property.getRef());
if(refObj == null){
throw new RuntimeException("set ref fail:["+property.getRef()+"] is null");
}
try{
setterMethod.invoke(object, refObj);
System.out.println("["+beanName+"] set DI >> " + property.getName() + ":" + refObj.toString());
}catch (Exception e){
throw new RuntimeException("set ref fail:["+beanName+"."+property.getRef() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
}
}
}
}
System.out.println("["+beanName+"] end>> :" + object.toString());
iocMap.put(beanName, object);
return object;
}
/**
* 解析xml文件
* @return
*/
private void parseXmlFile(){
Document document = null;
SAXReader reader = new SAXReader();
InputStream inputStream = ClassPathXmlApplicationContext.class.getResourceAsStream(configLocation);
try {
document = reader.read(inputStream);
} catch (DocumentException e) {
throw new RuntimeException("read xml file fail:" + "\n" +ExceptionUtils.getStackTrace(e));
}
List<Element> elementList = document.selectNodes("//bean");
if(!elementList.isEmpty()){
// 遍历所有bean节点
for(Element element : elementList){
String id = element.attributeValue("id");
if(beanDefinitionMap.containsKey(id)){
throw new RuntimeException("bean already exists: " + id);
}
String className = element.attributeValue("class");
BeanDefinition bean = new BeanDefinition(id, className);
//遍历bean下所有property属性节点
List<Element> properties= element.elements("property");
if(!properties.isEmpty()){
for(Element pElement : properties){
String name = pElement.attributeValue("name");
String value = pElement.attributeValue("value");
String ref = pElement.attributeValue("ref");
Property property = new Property(name, value, ref);
bean.getProperties().add(property);
}
}
beanDefinitionMap.put(id, bean);
}
}
}
}
BeanUtils
public class BeanUtils
{
/** * 匹配setter方法的正则表达式 */
private static final Pattern SET_PATTERN = Pattern.compile("set(\p{javaUpperCase}\w*)");
/**
* 获取对象的setter方法。
*/
public static Method getSetterMethod(Object obj, String property)
{
Method[] methods = obj.getClass().getMethods();
for (Method method : methods)
{
Matcher m = SET_PATTERN.matcher(method.getName());
if (m.matches() && (method.getParameterTypes().length == 1))
{
if(method.getName().toLowerCase().equals(("set" + property).toLowerCase())){
return method;
}
}
}
return null;
}
}
基于注解实现
@Autowired
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autowired {
}
@Component
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Component {
}
@Service
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Service {
}
@ComponentScan
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface ComponentScan {
String basePackage() default "";
}
@Value
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Value {
String value();
}
AnnotationConfigApplicationContext
public class AnnotationConfigApplicationContext implements ApplicationContext {
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<String, BeanDefinition>();
private Map<String, Object> iocMap = new HashMap<String, Object>();
private final Class<?> configClass;
public AnnotationConfigApplicationContext(Class<?> configClass) {
this.configClass = configClass;
scanPackageClass();
if(!beanDefinitionMap.isEmpty()){
for(Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()){
String id = entry.getKey();
//在依赖注入的时候,部分bean可能会提前已创建
if(!iocMap.containsKey(id)){
BeanDefinition bean = entry.getValue();
createBean(bean);
}
}
}
}
/**
* 扫描所有注解
*/
private void scanPackageClass(){
if(!configClass.isAnnotationPresent(ComponentScan.class)){
return;
}
//获取注解中的扫描路径
String basePackage = configClass.getDeclaredAnnotation(ComponentScan.class).basePackage();
List<Class<?>> classes = ClassUtils.getClasses(basePackage);
for(Class<?> cls : classes){
BeanDefinition beanDefinition = new BeanDefinition();
//@Component或@Service
if(cls.isAnnotationPresent(Component.class) || cls.isAnnotationPresent(Service.class)){
String beanName = cls.getSimpleName();;
//如果注解是@Service并且实现了接口,则取第一个接口为name
if(cls.isAnnotationPresent(Service.class) && cls.getInterfaces().length>0){
beanName = cls.getInterfaces()[0].getSimpleName();
}
beanName = ClassUtils.toLowerCaseFirstOne(beanName);//首字母小写
String className = cls.getName();
beanDefinition.setBeanClass(cls);
beanDefinition.setBeanName(beanName);
beanDefinition.setClassName(className);
if(beanDefinitionMap.containsKey(beanName)){
throw new RuntimeException("bean already exists: " + beanName);
}
beanDefinitionMap.put(beanName, beanDefinition);
}
}
}
public Object getBean(String beanName) {
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(null == beanDefinition){
throw new RuntimeException("no beanDefinition : " + beanName);
}
Object object = iocMap.get(beanName);
if(null != object){
return object;
} else {
return createBean(beanDefinition);
}
}
public Object createBean(BeanDefinition beanDefinition) {
Class<?> beanClass = beanDefinition.getBeanClass();
String beanName = beanDefinition.getBeanName();
System.out.println("["+beanName+"] create start>>>>");
Object object = null;
// 实例化
try {
object = beanClass.newInstance();
} catch (Exception e) {
throw new RuntimeException("class instance fail:["+ beanName +"]" + "\n" + ExceptionUtils.getStackTrace(e));
}
for(Field field: beanClass.getDeclaredFields()){
//属性赋值
if(field.isAnnotationPresent(Value.class)){
Value valueAnnotation = field.getAnnotation(Value.class);
String value = valueAnnotation.value();
//属性的setter方法
Method setterMethod = BeanUtils.getSetterMethod(object, field.getName());
Object val = null;
switch (field.getType().getName()){
case "java.lang.Integer":
val = Integer.parseInt(value);
break;
case "java.lang.String":
val = value;
break;
case "java.lang.Float":
val = Float.parseFloat(value);
break;
}
try {
setterMethod.invoke(object, val);
System.out.println("["+beanName+"] set value >> " + field.getName() + ":" + val);
} catch (Exception e) {
throw new RuntimeException("set value fail:[" + beanName + "." + field.getName() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
}
}
//依赖注入:@Autowired
if(field.isAnnotationPresent(Autowired.class)){
Object ref = getBean(field.getName());
if(ref == null){
throw new RuntimeException("set ref fail:["+field.getName()+"] is null");
}
field.setAccessible(true);
try {
field.set(object, ref);
System.out.println("["+beanName+"] set DI >> " + field.getName() + ":" + ref.toString());
} catch (IllegalAccessException e) {
throw new RuntimeException("set ref fail:["+ beanName +"."+ field.getName() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
}
}
}
iocMap.put(beanDefinition.getBeanName(), object);
return object;
}
}
ClassUtils
public class ClassUtils {
/**
* 从包package中获取所有的Class
*
* @param packageName
* @return
*/
public static List<Class<?>> getClasses(String packageName) {
// 第一个class类的集合
List<Class<?>> classes = new ArrayList<Class<?>>();
// 是否循环迭代
boolean recursive = true;
// 获取包的名字 并进行替换
String packageDirName = packageName.replace('.', '/');
// 定义一个枚举的集合 并进行循环来处理这个目录下的things
Enumeration<URL> dirs;
try {
dirs = Thread.currentThread().getContextClassLoader().getResources(packageDirName);
// 循环迭代下去
while (dirs.hasMoreElements()) {
// 获取下一个元素
URL url = dirs.nextElement();
// 得到协议的名称
String protocol = url.getProtocol();
// 如果是以文件的形式保存在服务器上
if ("file".equals(protocol)) {
// 获取包的物理路径
String filePath = URLDecoder.decode(url.getFile(), "UTF-8");
// 以文件的方式扫描整个包下的文件 并添加到集合中
findAndAddClassesInPackageByFile(packageName, filePath, recursive, classes);
} else if ("jar".equals(protocol)) {
// 如果是jar包文件
// 定义一个JarFile
JarFile jar;
try {
// 获取jar
jar = ((JarURLConnection) url.openConnection()).getJarFile();
// 从此jar包 得到一个枚举类
Enumeration<JarEntry> entries = jar.entries();
// 同样的进行循环迭代
while (entries.hasMoreElements()) {
// 获取jar里的一个实体 可以是目录 和一些jar包里的其他文件 如META-INF等文件
JarEntry entry = entries.nextElement();
String name = entry.getName();
// 如果是以/开头的
if (name.charAt(0) == '/') {
// 获取后面的字符串
name = name.substring(1);
}
// 如果前半部分和定义的包名相同
if (name.startsWith(packageDirName)) {
int idx = name.lastIndexOf('/');
// 如果以"/"结尾 是一个包
if (idx != -1) {
// 获取包名 把"/"替换成"."
packageName = name.substring(0, idx).replace('/', '.');
}
// 如果可以迭代下去 并且是一个包
if ((idx != -1) || recursive) {
// 如果是一个.class文件 而且不是目录
if (name.endsWith(".class") && !entry.isDirectory()) {
// 去掉后面的".class" 获取真正的类名
String className = name.substring(packageName.length() + 1, name.length() - 6);
try {
// 添加到classes
classes.add(Class.forName(packageName + '.' + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
return classes;
}
/**
* 以文件的形式来获取包下的所有Class
*
* @param packageName
* @param packagePath
* @param recursive
* @param classes
*/
public static void findAndAddClassesInPackageByFile(String packageName, String packagePath, final boolean recursive,
List<Class<?>> classes) {
// 获取此包的目录 建立一个File
File dir = new File(packagePath);
// 如果不存在或者 也不是目录就直接返回
if (!dir.exists() || !dir.isDirectory()) {
return;
}
// 如果存在 就获取包下的所有文件 包括目录
File[] dirfiles = dir.listFiles(new FileFilter() {
// 自定义过滤规则 如果可以循环(包含子目录) 或则是以.class结尾的文件(编译好的java类文件)
public boolean accept(File file) {
return (recursive && file.isDirectory()) || (file.getName().endsWith(".class"));
}
});
// 循环所有文件
for (File file : dirfiles) {
// 如果是目录 则继续扫描
if (file.isDirectory()) {
findAndAddClassesInPackageByFile(packageName + "." + file.getName(), file.getAbsolutePath(), recursive,
classes);
} else {
// 如果是java类文件 去掉后面的.class 只留下类名
String className = file.getName().substring(0, file.getName().length() - 6);
try {
// 添加到集合中去
classes.add(Class.forName(packageName + '.' + className));
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
}
// 首字母转小写
public static String toLowerCaseFirstOne(String s) {
if (Character.isLowerCase(s.charAt(0)))
return s;
else
return (new StringBuilder()).append(Character.toLowerCase(s.charAt(0))).append(s.substring(1)).toString();
}
}
跑起来看看
A
import com.syun.spring.ioc.core.annotation.Autowired;
import com.syun.spring.ioc.core.annotation.Component;
import com.syun.spring.ioc.core.annotation.Value;
@Component
public class A {
@Value(value = "a-1")
private String a1;
@Value(value = "a-2")
private String a2;
@Value(value = "a-3")
private String a3;
@Autowired
private B b;
public B getB() {
return b;
}
public void setB(B b) {
this.b = b;
}
public String getA1() {
return a1;
}
public void setA1(String a1) {
this.a1 = a1;
}
public String getA2() {
return a2;
}
public void setA2(String a2) {
this.a2 = a2;
}
public String getA3() {
return a3;
}
public void setA3(String a3) {
this.a3 = a3;
}
@Override
public String toString() {
return "A{" +
"a1='" + a1 + ''' +
", a2='" + a2 + ''' +
", a3='" + a3 + ''' +
", b=" + b +
'}';
}
}
B
import com.syun.spring.ioc.core.annotation.Component;
import com.syun.spring.ioc.core.annotation.Value;
@Component
public class B {
@Value(value = "b-1")
private String b1;
@Value(value = "b-2")
private String b2;
@Value(value = "b-3")
private String b3;
public String getB1() {
return b1;
}
public void setB1(String b1) {
this.b1 = b1;
}
public String getB2() {
return b2;
}
public void setB2(String b2) {
this.b2 = b2;
}
public String getB3() {
return b3;
}
public void setB3(String b3) {
this.b3 = b3;
}
@Override
public String toString() {
return "B{" +
"b1='" + b1 + ''' +
", b2='" + b2 + ''' +
", b3='" + b3 + ''' +
'}';
}
}
UserService
public interface UserService {
void getUserInfo();
}
UserServiceImpl
import com.syun.service.UserService;
import com.syun.spring.ioc.core.annotation.Service;
@Service
public class UserServiceImpl implements UserService {
public void getUserInfo() {
System.out.println("name:shiyunxi,age:22");
}
}
application.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans>
<bean id="userService" class="com.syun.service.impl.UserServiceImpl"></bean>
<bean id="a" class="com.syun.entry.A">
<property name="a1" value="shiyunxi"></property>
<property name="a2" value="男"></property>
<property name="b" ref="b"></property>
</bean>
<bean id="b" class="com.syun.entry.B">
<property name="b1" value="2018"></property>
<property name="b2" value="12"></property>
<property name="b3" value="8"></property>
</bean>
</beans>
XmlTest
public class XmlTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("/application.xml");
A a = (A) applicationContext.getBean("a");
System.out.println(a.toString());
UserService userService = (UserService) applicationContext.getBean("userService");
userService.getUserInfo();
}
}
AnnotationTest
@ComponentScan(basePackage = "com.syun")
public class AnnotationTest {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(AnnotationTest.class);
A a = (A) applicationContext.getBean("a");
System.out.println(a.toString());
UserService userService = (UserService) applicationContext.getBean("userService");
userService.getUserInfo();
}
}
循环依赖
上面的IOC容器还存在一个棘手的问题,循环依赖。
Spring如何解决循环依赖
Spring解决循环依赖的理论依据是基于Java的引用传递,当我们获取到对象的引用时,对象的属性是可以延迟设置的。Spring的单例对象的初始化主要分为三步:
- 实例化:调用对象的构造方法实例化对象。
- 属性赋值:填充属性。
- 初始化:属性注入后,执行自定义初始化。
循环依赖主要发生在实例化、注入,存在构造器循环依赖和属性注入依赖。
Spring为了解决单例的循环依赖问题,使用了三级缓存。
/** Cache of singleton objects: bean name --> bean instance */
private final Map<String, Object> singletonObjects = new ConcurrentHashMap<>(256);
/** Cache of singleton factories: bean name --> ObjectFactory */
private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<>(16);
/** Cache of early singleton objects: bean name --> bean instance */
private final Map<String, Object> earlySingletonObjects = new HashMap<>(16);
- 第一级缓存 singletonObjects:存放了已实例化、初始化的完成的Bean对象。
- 第二级缓存 earlySingletonObjects:存放了已实例化、未属性赋值的半成品的Bean对象。
- 第三级缓存 singletonFactories:存放可以生成Bean的工厂。
为么使用三级缓存
① 使用一级缓存
- 实例化A,将半成品的A放到一级缓存中,发现需要B,再去实例化B。
- 实例化B过程中发现需要A,于是从一级缓存中取出A(半成品),完成B的创建,将B加入一级缓存。
- 继续创建A,从一级缓存拿到B,填充到A的属性中,完成A的创建。
存在问题:基本流程下,是可以解决循环依赖的,但是在创建过程中,当另一个线程取A,可能会出现拿到化的半成品的A。
② 使用二级缓存
一级缓存:存放已实例化和初始化的 Bean。
二级缓存:存放已实例化未属性赋值的Bean(半成品)。
- 实例化A,将半成品的A放到二级缓存,发现需要B,再去实例化B。
- 实例化B,将半成品的B放到二级缓存,创建过程中发现需要A,于是B先查一级缓存,没有,再查二级缓存,找到A后,完成B的创建,将B加入一级缓存,并删除二级缓存的B。
- 继续创建A,从一级缓存拿到B,填充到A的属性中,完成A的创建,将A放到一级缓存,并删除二级缓存中的A。
存在问题:这个流程保证了线程安全,如果A有AOP的话,因为二级缓存存放的是原始对象,而我们需要注入A的代理对象,这样的话就满足不了代理需求。
③ 使用三级缓存
三级缓存 缓存的是ObjectFactory , 也就是一个Lambda表达式,主要是为了生成代理对象。如果当前Bean需要AOP , 那么执行完lambda之后得到的就是一个代理对象 ,如果无需AOP , 那就是原始对象。
- 实例化A的过程中需要B,先将A放到三级缓存里面,再去实例化B。
- 实例化B的过程中发现需要A,于是B先查一级缓存,没有,再查二级缓存,还没有,再查三级缓存,找到了A后,把A放到二级缓存,并删除三级缓存中的A。
- B初始化完成后,将B放到一级缓存,此时B里面的A还是创建中状态,继续创建A,直接从一级缓存里面拿到B,完成A的初始化,并将A放到一级缓存中,删除二级缓存的A。
简单解决循环依赖
下面通过一级缓存和二级缓存两种方式,简单解决循环依赖问题,基于AnnotationConfigApplicationContext 代码优化。
① 使用一级缓存
改动比较小,只是在实例化的时候,将object保存到缓存中。
② 使用二级缓存
public Object getSingletonObject(String beanName){
/**
* 1.先从一级缓存获取。
* 2.当从一级缓存获取不到,则从二级缓存获取。
*/
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
if(null == beanDefinition){
throw new RuntimeException("no beanDefinition : " + beanName);
}
Object object = singletonObjects.get(beanName);
if(object == null){
object = earlySingletonObjects.get(beanName);
if(object == null){
object = createBean(beanDefinition);
}
}
return object;
}
public Object createBean(BeanDefinition beanDefinition) {
Class<?> beanClass = beanDefinition.getBeanClass();
String beanName = beanDefinition.getBeanName();
System.out.println("["+beanName+"] create start>>>>");
Object object = null;
// 实例化
try {
object = beanClass.newInstance();
//将半成品存放到二级缓存
earlySingletonObjects.put(beanName, object);
System.out.println("["+beanName+"] 半成品保存到二级缓存");
} catch (Exception e) {
throw new RuntimeException("class instance fail:["+ beanName +"]" + "\n" + ExceptionUtils.getStackTrace(e));
}
for(Field field: beanClass.getDeclaredFields()){
//属性赋值
if(field.isAnnotationPresent(Value.class)){
Value valueAnnotation = field.getAnnotation(Value.class);
String value = valueAnnotation.value();
//属性的setter方法
Method setterMethod = BeanUtils.getSetterMethod(object, field.getName());
Object val = null;
switch (field.getType().getName()){
case "java.lang.Integer":
val = Integer.parseInt(value);
break;
case "java.lang.String":
val = value;
break;
case "java.lang.Float":
val = Float.parseFloat(value);
break;
}
try {
setterMethod.invoke(object, val);
System.out.println("["+beanName+"] set value >> " + field.getName() + ":" + val);
} catch (Exception e) {
throw new RuntimeException("set value fail:[" + beanName + "." + field.getName() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
}
}
//依赖注入:@Autowired
if(field.isAnnotationPresent(Autowired.class)){
//从缓存获取bean
Object ref = getSingletonObject(field.getName());
if(ref == null){
throw new RuntimeException("set ref fail:["+field.getName()+"] is null");
}
field.setAccessible(true);
try {
field.set(object, ref);
System.out.println("["+beanName+"] set DI >> " + field.getName() + ":" + ref.toString());
} catch (IllegalAccessException e) {
throw new RuntimeException("set ref fail:["+ beanName +"."+ field.getName() +"] " + "\n" +ExceptionUtils.getStackTrace(e));
}
}
}
System.out.println("["+beanName+"] end >> :" + object.toString());
// 将完整的bean保存到一级缓存,并且删除二级缓存
singletonObjects.put(beanName, object);
earlySingletonObjects.remove(beanName);
System.out.println("["+beanName+"] 完整版保存到一级缓存,并删除二级缓存");
return object;
}
实现过程中也参考了不少优秀的博客,在此就不贴啦,附上我的gitee地址吧。