4.1Aware回调模拟实现
在createBean的时候,我们想在加了Component注解的类里面加一个字段beanName,该字段存储bean对象的name属性
spring会提供一个接口BeanNameAware来实现
package com.rainwood.spring;
public interface BeanNameAware {
void setBeanName(String name);
}
我们在UserService类里可以继承该接口重写setBeanName方法
package com.rainwood.liming.service;
import com.rainwood.spring.*;
@Component("userService")
//@Scope("prototype")
public class UserService implements BeanNameAware{
@Autowired
private OrderService orderService;
private String beanName;
public void test() {
System.out.println(orderService);
System.out.println(beanName);
}
@Override
public void setBeanName(String name) {
beanName = name;
}
}
设想如果没有setBeanName方法的话,在自动注入时候,仅有一个beanName字段是无法将Bean的name属性传进来赋给beanName
我们这里利用set方法,在spring容器createBean方法中调用setBean方法就可以实现将beanName传入。
public Object createBean(String beanName, BeanDefination beanDefination) {
Class clazz = beanDefination.getClazz();
try {
//首先看getDeclaredConstructor(Class<?>... parameterTypes)
//这个方法会返回制定参数类型的所有构造器,包括public的和非public的,当然也包括private的。
//getDeclaredConstructors()的返回结果就没有参数类型的过滤了。
Object instance = clazz.getDeclaredConstructor().newInstance();
//依赖注入
//getDeclaredFields():获得某个类的所有声明的字段,即包括public、private和proteced,但是不包括父类的申明字段。
for (Field declaredField : clazz.getDeclaredFields()) {
if(declaredField.isAnnotationPresent(Autowired.class)) {
//spring在依赖注入时候会去是spring容器池里去根据类型和名字来找对应的bean
//这里我们简化用名字来找
Object bean = getBean(declaredField.getName());
declaredField.setAccessible(true);//功能是启用或禁用安全检查
declaredField.set(instance, bean);
}
}
//Aware回调
//判断instance是否实现了BeanNameAware接口,如果实现了就调用setBeanName将当前bean的名字beanName传进去
if(instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
我们和之前不同,我们在createBean时候,再加一个参数beanName传入createBean方法,
//Aware回调
//判断instance是否实现了BeanNameAware接口,如果实现了就调用setBeanName将当前bean的名字beanName传进去
if(instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
检验instance对象是否是继承了BeanNameAware接口,如果继承了,就可以利用重写的setBeanName方法将beanName注入进去
4.2初始化模拟实现
和Aware回调类似,我们需要一个InitializingBean接口,该接口有afterPropertiesSet方法
package com.rainwood.spring;
public interface InitializingBean {
void afterPropertiesSet() throws Exception;
}
让UserService继承InitializingBean
package com.rainwood.liming.service;
import com.rainwood.spring.*;
@Component("userService")
//@Scope("prototype")
public class UserService implements BeanNameAware, InitializingBean {
@Autowired
private OrderService orderService;
private String beanName;
public void test() {
System.out.println(orderService);
System.out.println(beanName);
}
@Override
public void setBeanName(String name) {
beanName = name;
}
//初始化时候调用这个方法想做啥就做啥
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("初始化");
}
}
同样的在createBean的时候
//初始化
if(instance instanceof InitializingBean) {
try {
((InitializingBean)instance).afterPropertiesSet();
} catch (Exception e) {
e.printStackTrace();
}
}
继续判断instance是否继承了InitializingBean接口
继承了的话就调用afterPropertiesSet方法进行各种初始化操作