首先回顾一下我们之前的流程ApplicationContext
构造方法
@ComponetScan
注解,扫描包,获取其路径及其对应的字节码文件@Componet
注解,并获取或者生成BeanName
BeanDefinition
,包含其类和类型(单例,多例)beanDefinitionMap
singletonObjects
getBean(String beanName)
方法
BeanDefinition
获取类信息singletonObjects
获取对象
creatBean()
// 后续说为什么为空creatBean()
,返回创建的对象creatBean(Class clazz)
返回创建的对象
如果Component
不包含BeanName
在扫描扫描包的时候,发现含有Component
注解的时候,查看其value值,如果为空,我们用方法将其类名首字母小写为BeanName
try {
Class<?> clazz = classLoader.loadClass(className);
if(clazz.isAnnotationPresent(Component.class)){
// 获得注解value值 beanName
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value();
// component未赋值
if("".equals(beanName)){
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition=new BeanDefinition();
beanDefinition.setType(clazz);
if(clazz.isAnnotationPresent(Scope.class)){
Scope scope = clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scope.value());
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
我们需要实现依赖注入, @Autoware
注解,在什么时候注入依赖呢
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD) // 用在变量声明上
public @interface Autoware {
}
@Scope(value = "prototype")
@Component
public class UserService {
@Autoware
OrderService orderService;
public void test(){
System.out.println("UserService - test");
}
}
我们应该在创建对象的时候,扫描其FIELD
是否有@Autoware
注解,如果包含其注解
private Object creatBean(String beanName, BeanDefinition beanDefinition) {
Class clazz=beanDefinition.getType();
try {
// 反射获取对象
Object instance = clazz.getConstructor().newInstance();
// 依赖注入
for (Field f : clazz.getDeclaredFields()) {
if(f.isAnnotationPresent(Autoware.class)){
f.setAccessible(true);
f.set(instance, getBean(f.getName())); // 通过获取其名字获取其对象 装载上去
}
}
return instance;
} 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);
}
}/
这里就解答了为什么当时
如果获取到的bean为空,在creatBean()
// 后续说为什么为空
我们是逐个创建对象,有可能当前创建的对象依赖后面的还未创建的对象
对于UserService
想知道自己的BeanName
创建BeanNameAware
接口,包含setBeanName(String beanName)
方法
package com.yqyang.spring;
public interface BeanNameAware {
public void setBeanName(String beanName);
}
对于UserService
实现该接口
我们在creatBean()
时就能查看类是否instanceof
该接口,如果是可以回调UserService
实现的接口方法
private Object creatBean(String beanName, BeanDefinition beanDefinition) {
Class clazz=beanDefinition.getType();
try {
// 反射获取对象
Object instance = clazz.getConstructor().newInstance();
// 依赖注入
for (Field f : clazz.getDeclaredFields()) {
if(f.isAnnotationPresent(Autoware.class)){
f.setAccessible(true);
f.set(instance, getBean(f.getName()));
}
}
// Aware回调
if(instance instanceof BeanNameAware){
((BeanNameAware) instance).setBeanName(beanName);
}
return instance;
} 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);
}
}
和上面差不多,定义InitializingBean
接口
package com.yqyang.spring;
public interface InitializingBean {
public void afterPropertiesSet();
}
对于UserService
实现该接口
我们在creatBean()
时就能查看类是否instanceof
该接口,如果是可以回调UserService
实现的接口方法
private Object creatBean(String beanName, BeanDefinition beanDefinition) {
Class clazz=beanDefinition.getType();
try {
// 反射获取对象
Object instance = clazz.getConstructor().newInstance();
// 依赖注入
for (Field f : clazz.getDeclaredFields()) {
if(f.isAnnotationPresent(Autoware.class)){
f.setAccessible(true);
f.set(instance, getBean(f.getName()));
}
}
// Aware回调
if(instance instanceof BeanNameAware){
((BeanNameAware) instance).setBeanName(beanName);
}
// 初始化
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
return instance;
} 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);
}
}
可能在初始化前后执行一些操作
定义BeanPostProcessor
接口,返回值为Object为了后面的动态代理AOP
public interface BeanPostProcessor {
public Object postProcessBeforeInitialization(String beanName, Object bean);
public Object postProcessAfterInitialization(String beanName, Object bean);
}
我们需要在ApplicationContext
添加变量
private ArrayList<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
其获取是在扫描包时,获取实现该接口的对象,添加到beanPostProcessorList
try {
Class<?> clazz = classLoader.loadClass(className);
if (clazz.isAnnotationPresent(Component.class)) {
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.newInstance();
beanPostProcessorList.add(instance);
}
Component component = clazz.getAnnotation(Component.class);
String beanName = component.value();
if (beanName.equals("")) {
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
if (clazz.isAnnotationPresent(Scope.class)) {
Scope scopeAnnotation = clazz.getAnnotation(Scope.class);
beanDefinition.setScope(scopeAnnotation.value());
} else {
beanDefinition.setScope("singleton");
}
beanDefinitionMap.put(beanName, beanDefinition);
}
在creatBean()
初始化前后,遍历列表,获取各个对象执行方法
BeanPostProcessor
,也就是beanPostProcessorList
中有多个方法,创建一个对象的时候会导致各个实现该对象的方法重复执行,在实现接口的时候可以利用传入创建Bean的参数启到限制的作用,只让我们创建的对象执行。
private Object createBean(String beanName, BeanDefinition beanDefinition){
Class clazz = beanDefinition.getType();
try {
Object instance = clazz.getConstructor().newInstance();
// 依赖注入
for (Field f : clazz.getDeclaredFields()) {
if (f.isAnnotationPresent(Autowired.class)) {
f.setAccessible(true);
f.set(instance, getBean(f.getName()));
}
}
// Aware
if (instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(beanName, instance);
}
// 初始化
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(beanName, instance);
}
return instance;
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
return null;
}
测试类-记得放在扫描包下
@Component
public class YqyangBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(String beanName, Object bean) {
if (beanName.equals("userService")) {
System.out.println("1111");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(String beanName, Object bean) {
if (beanName.equals("userService")) {
System.out.println("2222");
}
return bean;
}
}
jdk实现动态代理需要接口,创建接口UserInterface
public interface UserInterface {
public void test();
}
UserService
实现该接口
@Scope
@Component
public class UserService implements UserInterface {
@Autoware
OrderService orderService;
public void test(){
System.out.println("UserService - test");
}
}
在实现postProcessAfterInitialization
接口时,获取其动态代理对象,并且调用原来的方法。
@Component
public class ZhouyuBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(String beanName, Object bean) {
if (beanName.equals("userService")) {
System.out.println("1111");
}
return bean;
}
@Override
public Object postProcessAfterInitialization(String beanName, Object bean) {
if (beanName.equals("userService")) {
Object proxyInstance = Proxy.newProxyInstance(ZhouyuBeanPostProcessor.class.getClassLoader(), bean.getClass().getInterfaces(), new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("代理逻辑");
return method.invoke(bean, args);
}
});
return proxyInstance;
}
return bean;
}
}