文章目录
前言:
先前写过一篇基础版的spring控制反转及依赖注入的demo, 后面自身通过渠道学习, 对spring有了更清晰的认知, 故整理了spring核心功能如下代码样例:
先前的文章地址: 模拟spring控制反转及依赖注入
1.学习收获
通过手写模拟,了解Spring的底层源码启动过程
通过手写模拟,了解BeanDefinition、BeanPostProcessor的概念
通过手写模拟,了解Spring解析配置类等底层源码工作流程
通过手写模拟,了解依赖注入,Aware回调等底层源码工作流程
通过手写模拟,了解Spring AOP的底层源码工作流程
2.注意事项
该案例仅用于学习使用, demo中使用的都是java开发所必会的基础技能, 所以不用担心看不懂, but程序中会有一些小bug, 例没有处理循环依赖; 扫描时未递归查询clazz文件目录等, 故动手能力一般的不要随便调整文件的存放结构(包结构)
3.实现代码
- spring注解
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Autowired {
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Component {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface ComponentScan {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface Scope {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface WrxValue {
String value() default "";
}
- spring接口
/**
* 核心: spring中有很多的"啊伟"回调
* 说明: 实现思路与 InitializingBean差不多,都是在创建bean时去回调方法
*/
public interface BeanNameAware {
/**
* 创建bean时给实现类设置beanName
* @Param: name beanName
* @Author: wrx
* @Date: 2021/9/5 14:53
*/
void setBeanName(String name);
}
/**
* 核心: bean的后置处理器
* 说明: 创建bean的过程中,每一个bean都会遍历调用该接口的实现类方法,该功能非常强大,发挥你天马行空的想象力
* @Author: wrx
* @Date: 2021/9/5 13:20
*/
public interface BeanPostProcessor {
/**
* 后置处理器初始化前执行的方法
* @Param: bean bean的实例
* @Param: beanName bean名
* @Return:
* @Author: wrx
* @Date: 2021/9/5 14:09
*/
default Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
/**
* 后置处理器初始化后执行的方法
* @Param: bean bean的实例
* @Param: beanName bean名
* @Return:
* @Author: wrx
* @Date: 2021/9/5 14:09
*/
default Object postProcessAfterInitialization(Object bean, String beanName) {
return bean;
}
}
/**
* 创建bean时的初始化接口
* @Author: wrx
* @Date: 2021/9/5 13:18
*/
public interface InitializingBean {
/**
* 创建bean过程中的自定义操作
*/
void afterPropertiesSet();
}
- spring BeanDefinition 及 ApplicationContext
/**
* 核心: Bean定义类
* 说明: 该类只是'bean定义',还需主动创建'bean'
* @Author: wrx
* @Date: 2021/9/4 18:10
*/
public class BeanDefinition {
/**
* 定义Class类型
*/
private Class type;
/**
* 单例 or 多例
*/
private String scope;
/**
* 是否懒加载
*/
private boolean isLazy;
public Class getType() {
return type;
}
public void setType(Class type) {
this.type = type;
}
public String getScope() {
return scope;
}
public void setScope(String scope) {
this.scope = scope;
}
public boolean isLazy() {
return isLazy;
}
public void setLazy(boolean lazy) {
isLazy = lazy;
}
}
/**
* 容器
* @Author: wrx
* @Date: 2021/9/4 18:21
*/
public class WrxApplicationContext {
/**
* 配置类、即包扫描类,用于指定要扫描的路径
*/
private Class configClass;
/**
* 扫描时存储BeanDefinition的 Map key: BeanName value: bean定义
*/
private Map<String, BeanDefinition> beanDefinitionMap = new HashMap<>();
/**
* 扫描后创建单例bean
*/
private Map<String, Object> singletonObjects = new HashMap<>();
/**
* 扫描时加入BeanPostProcessor的实现类到 后置处理器集合
*/
private List<BeanPostProcessor> beanPostProcessorList = new ArrayList<>();
/**
* ApplicationContext构造方法,初始化时即做好创建Bean定义、创建Bean
* @Param: configClass 包扫描类
* @Author: wrx
* @Date: 2021/9/4 23:28
*/
public WrxApplicationContext(Class configClass) {
this.configClass = configClass;
// 扫描
scan(configClass);
// 扫描结束后,根据beanDefinitionMap存储单例Bean到singletonObjects
for (Map.Entry<String, BeanDefinition> entry : beanDefinitionMap.entrySet()) {
String beanName = entry.getKey();
BeanDefinition beanDefinition = entry.getValue();
if (beanDefinition.getScope().equals("singleton")) {
Object bean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, bean);
}
//多例每次getBean都要new新的,不用处理
}
}
/**
* 创建Bean,且该过程需要对属性进行依赖注入
* @param beanName
* @param beanDefinition
* @return
*/
private Object createBean(String beanName, BeanDefinition beanDefinition) {
Class clazz = beanDefinition.getType();
Object instance = null;
try {
//此案例只处理了bean的无参构造的情况,实际还得处理有参的
//clazz.newInstance 只能调用无参构造, clazz.getConstructor().newInstance()则可以支持有参构造
instance = clazz.getConstructor().newInstance();
for (Field field : clazz.getDeclaredFields()) {
//对属性进行注解的依赖注入
if (field.isAnnotationPresent(Autowired.class)) {
field.setAccessible(true);
//此处实际得先根据beanType找,多个再根据beanName去找,该demo只实现根据字段名找bean
field.set(instance, getBean(field.getName()));
}
}
//与InitializingBean思路差不多
if (instance instanceof BeanNameAware) {
((BeanNameAware)instance).setBeanName(beanName);
}
//每一个bean初始时前都要调用所有BeanPostProcessor实现类的postProcessBeforeInitialization方法
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessBeforeInitialization(instance, beanName);
}
//添加对Bean初始化过程自定义操作的支持(实现InitializingBean即可)
if (instance instanceof InitializingBean) {
((InitializingBean)instance).afterPropertiesSet();
}
//每一个bean初始时后都要调用所有BeanPostProcessor实现类的postProcessAfterInitialization方法
//aop就是基于该功能实现
for (BeanPostProcessor beanPostProcessor : beanPostProcessorList) {
instance = beanPostProcessor.postProcessAfterInitialization(instance, beanName);
}
} catch (Exception e) {
e.printStackTrace();
}
return instance;
}
/**
* 根据名称获取Bean
* @Param: beanName bean名,例 userService
* @Return: Bean对象
* @Author: wrx
* @Date: 2021/9/4 18:04
*/
public Object getBean(String beanName) {
//未定义的bean则直接抛异常
if (!beanDefinitionMap.containsKey(beanName)) {
throw new NullPointerException();
}
BeanDefinition beanDefinition = beanDefinitionMap.get(beanName);
//判断是bean定义中存储的是 单例还是多例
if (beanDefinition.getScope().equals("singleton")) {
//单例模式每次都会从单例池中获取bean,无则创建
Object singletonBean = singletonObjects.get(beanName);
if (singletonBean == null) {
singletonBean = createBean(beanName, beanDefinition);
singletonObjects.put(beanName, singletonBean);
}
return singletonBean;
} else {
//原型模式则直接创建bean
Object prototypeBean = createBean(beanName, beanDefinition);
return prototypeBean;
}
}
/**
* @Description: 包扫描,初始化Bean等
* @Param: configClass 配置类
* @Author: wrx
* @Date: 2021/9/4 17:03
*/
private void scan(Class configClass) {
if (configClass.isAnnotationPresent(ComponentScan.class)) {
ComponentScan componentScanAnnotation = (ComponentScan) configClass.getAnnotation(ComponentScan.class);
String path = componentScanAnnotation.value();
// 例 com.wrx.service => com/wrx/service
path = path.replace(".", "/");
//ClassLoader classLoader = wrxApplicationContext.class.getClassLoader();
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
//根据相对路径获取到全路径
URL resource = classLoader.getResource(path);
File file = new File(resource.getFile());
if (file.isDirectory()) {
for (File f : file.listFiles()) {
//获取绝对路径
String absolutePath = f.getAbsolutePath();
//截取从com开始, .class结束 ,并由 com/wrx/service/xxx.class => com.wrx.service.xxx.class
absolutePath = absolutePath.substring(absolutePath.indexOf("com"), absolutePath.indexOf(".class"));
absolutePath = absolutePath.replace("\\", ".");
try {
//根据 com.wrx.service.xxx.class 加载为 Clazz
Class<?> clazz = classLoader.loadClass(absolutePath);
//判断该clazz是否包含 @Component, 包含则表示该类为Bean, 接着处理 '单例'及'多例'
if (clazz.isAnnotationPresent(Component.class)) {
//判断一个类是否实现了 BeanPostProcessor,是则实例化添加进集合
if (BeanPostProcessor.class.isAssignableFrom(clazz)) {
BeanPostProcessor instance = (BeanPostProcessor) clazz.getConstructor().newInstance();
beanPostProcessorList.add(instance);
}else{
//否则添加bean定义
createAndPutBeanDefinition(clazz);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
/**
* 创建bean定义并添加进map
* @Param: clazz
* @Author: wrx
* @Date: 2021/9/5 13:55
*/
private void createAndPutBeanDefinition(Class<?> clazz) {
Component componentAnnotation = clazz.getAnnotation(Component.class);
String beanName = componentAnnotation.value();
if ("".equals(beanName)) {
//如果没有配置beanName,则默认以类名首字母小写
beanName = Introspector.decapitalize(clazz.getSimpleName());
}
//只要类包含@Compent表示该类为Bean,直接创建Bean定义
BeanDefinition beanDefinition = new BeanDefinition();
beanDefinition.setType(clazz);
//看下该类是否有@Scope,有则直接设置配置的scope,无则默认单例
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);
}
}
- 我们(程序员)使用spring的代码
package com.wrx.config;
import com.spring.annotation.ComponentScan;
@ComponentScan("com.wrx.service")
public class AppConfig {
}
package com.wrx.service;
import com.spring.annotation.Component;
/**
* @author wrx
*/
@Component
public class OrderService {
public void test() {
System.out.println("OrderService test");
}
}
package com.wrx.service;
/**
* 仅用来测试jdk动态代理
*/
public interface UserInterface {
void test();
void test2();
void test3();
}
package com.wrx.service;
import com.spring.Interface.BeanNameAware;
import com.spring.annotation.Autowired;
import com.spring.annotation.Component;
import com.spring.annotation.WrxValue;
/**
* @author wrx
*/
@Component
//@Scope("prototype")
//@Scope("singleton")
public class UserService implements UserInterface, BeanNameAware {
@Autowired
private OrderService orderService;
@WrxValue("测试bean初始化前给test赋值")
private String initValue;
/**
* 假设你希望知道该bean的名字,可以实现aware,创建bean时会回调aware中的方法
*/
private String beanName;
@Override
public void setBeanName(String name) {
this.beanName = name;
}
@Override
public void test() {
System.out.println(beanName);
}
@Override
public void test2() {
orderService.test();
}
@Override
public void test3() {
System.out.println(initValue);
}
}
package com.wrx.service;
import com.spring.Interface.BeanPostProcessor;
import com.spring.annotation.Component;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
* BeanPostProcessor的实现类
* @author wrx
*/
@Component
public class WrxBeanPostProcessor implements BeanPostProcessor {
/**
* 后置处理器初始化后执行的方法
* @Param: bean bean的实例
* @Param: beanName bean名
* @Return:
* @Author: wrx
* @Date: 2021/9/5 14:09
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
//假设该后置处理器我只想针对 userService,因为每个bean初始化时都会调用BeanPostProcessor的实现方法,所以加if判断
if (beanName.equals("userService")) {
//AOP实际上也是基于BeanPostProcessor实现的,此处模拟aop的jdk代理,返回代理对象
Object proxyInstance = Proxy.newProxyInstance(WrxBeanPostProcessor.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;
}
}
package com.wrx.service;
import com.spring.Interface.BeanPostProcessor;
import com.spring.annotation.Component;
import com.spring.annotation.WrxValue;
import java.lang.reflect.Field;
/**
* BeanPostProcessor的实现类
* @author wrx
*/
@Component
public class WrxValueBeanPostProcessor implements BeanPostProcessor {
/**
* 后置处理器初始化前执行的方法
* @Param: bean bean的实例
* @Param: beanName bean名
* @Return:
* @Author: wrx
* @Date: 2021/9/5 14:09
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
//此处我自定义的功能是,在bean初始化前,对有@WrxValue的属性进行赋值
for (Field field : bean.getClass().getDeclaredFields()) {
if (field.isAnnotationPresent(WrxValue.class)) {
field.setAccessible(true);
try {
field.set(bean, field.getAnnotation(WrxValue.class).value());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
return bean;
}
}
- 测试代码
package com.wrx;
import com.spring.WrxApplicationContext;
import com.wrx.config.AppConfig;
import com.wrx.service.UserInterface;
/**
* @author wrx
*/
public class Test {
public static void main(String[] args) {
/*UserService.class --> 无参构造(多个时推断构造方法)-->普通对象-->依赖注入(属性赋值)
-->初始化前(@PostCostruct)-->初始化(Initialzingean)-->初始化后(AOP,基于BeanPostProcess)-->代理对象-->Bean */
// 扫描--->创建单例Bean BeanDefinition BeanPostPRocess
WrxApplicationContext applicationContext = new WrxApplicationContext(AppConfig.class);
UserInterface userService = (UserInterface) applicationContext.getBean("userService");
userService.test();
userService.test2();
userService.test3();
}
}