手写MVC初体验之功能类(三)
目录
1. 项目结构
结构图
流程图
在(二)中解释了bean的config包下的类的作用。这篇文章记录一下自己在support下的类。
- reader包:对应上图的BeanDefinitionReader类,用来扫描指定包下的类,将其封装为类路径的String集合。
- loader包:对应上图的ResourceLoader,属于BeanDefinitionReader的功能类,为其解析application.properties中的配置。
- registry包:对应上图的BeanDefinitionRegistry,将BeanDefinitionReader扫描到的类路径封装成BeanDefinition。
- wrapper包:对应上图的BeanWrapperProcess,将BeanDefinitionRegistry封装的BeanDefinition包装成BeanWrapper。
- autowire包:对应上图的BeanPostProcessor,将BeanWrapper中的实例对象进行依赖注入。
- factory包:对应上图的FactoryBean,为autowire包的操作提供bean的注入。
2. ApplicationContext
package org.framework.spring.v1.context.core.impl;
import org.framework.spring.v1.context.bean.support.autowire.BeanPostProcessor;
import org.framework.spring.v1.context.bean.support.autowire.factory.BeanPostProcessorFactory;
import org.framework.spring.v1.context.bean.support.reader.BeanDefinitionReader;
import org.framework.spring.v1.context.bean.support.reader.factory.BeanDefinitionReaderFactory;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import org.framework.spring.v1.context.bean.support.wrapper.BeanWrapperProcess;
import org.framework.spring.v1.context.bean.support.wrapper.factory.BeanWrapperProcessFactory;
import org.framework.spring.v1.context.core.ApplicationContext;
import java.util.Map;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/6/18 21:43
*/
public class AnnotationApplicationContext implements ApplicationContext {
private BeanDefinitionReader reader ;
private BeanDefinitionRegistry registry ;
private BeanWrapperProcess process ;
private BeanPostProcessor beanFactory ;
/**
* 传入的是application.properties
* @param contextConfiguration
*/
public AnnotationApplicationContext(String contextConfiguration) {
//通过reader加载配置文件
this.reader = BeanDefinitionReaderFactory.getAnnotation(contextConfiguration) ;
//注册 beanDefinitionMap
//一级缓存——beanName->BeanDefinition 交由reader下面的registry处理
this.registry = this.reader.getRegistry() ;
//二级缓存——BeanDefinition->BeanWrapper 交由process处理
this.process = BeanWrapperProcessFactory.getBeanWrapperProcess(this.registry) ;
//三级缓存——BeanWrapper->Bean
this.beanFactory = BeanPostProcessorFactory.getAutowireCapable(this.process) ;
}
@Override
public Map<String, Object> getIoc() {
return this.beanFactory.getIoc() ;
}
@Override
public void registerBean(String className) {
//首先是registerClassName列表中
//registry的BeanDefinition
//process的BeanDefinition
//beanFactory的Object
}
@Override
public void removeBean(String beanName) {
//首先是registerClassName列表中
//registry的BeanDefinition
//process的BeanDefinition
//beanFactory的Object
}
@Override
public int getIocCount() {
return this.beanFactory.getBeanCount() ;
}
@Override
public boolean isBeanExist(Object bean) {
return this.beanFactory.isBeanExist(bean) ;
}
@Override
public boolean isBeanNameExist(String beanName) {
return this.beanFactory.isBeanNameExist(beanName) ;
}
}
3. Reader
package org.framework.spring.v1.context.bean.support.reader;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/6/22 23:49
*/
public interface BeanDefinitionReader {
void doScanner(String scanPackage) ;
BeanDefinitionRegistry getRegistry();
BeanDefinitionRegistry getBeanFactory();
}
package org.framework.spring.v1.context.bean.support.reader.abs;
import org.framework.spring.v1.context.bean.support.loader.ResourceLoader;
import org.framework.spring.v1.context.bean.support.reader.BeanDefinitionReader;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import java.util.ArrayList;
import java.util.List;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/5 20:06
*/
public abstract class AbstractAnnotationBeanDefinitionReader implements BeanDefinitionReader {
protected ResourceLoader loader ;
protected BeanDefinitionRegistry registry ;
protected List<String> registerBeanClasses ;
public AbstractAnnotationBeanDefinitionReader(){
this.registerBeanClasses = new ArrayList<String>() ;
}
/**
* 加载BeanDefinition
*/
protected abstract void loadBeanDefinitions() ;
}
package org.framework.spring.v1.context.bean.support.reader.impl;
import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.config.definition.impl.DefaultRootBeanDefinition;
import org.framework.spring.v1.context.bean.support.loader.impl.PropertiesResourceLoader;
import org.framework.spring.v1.context.bean.support.reader.abs.AbstractAnnotationBeanDefinitionReader;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import org.framework.spring.v1.context.bean.support.registry.factory.BeanDefinitionRegistryFactory;
import org.framework.spring.v1.tools.StringUtil;
import java.io.File;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/6/18 22:57
*/
public class DefaultAnnotationBeanDefinitionReader extends AbstractAnnotationBeanDefinitionReader {
public DefaultAnnotationBeanDefinitionReader(String config) {
super();
this.loader = new PropertiesResourceLoader(config) ;
doScanner(this.loader.getProperty("spring.base.package")) ;
this.registry = BeanDefinitionRegistryFactory.getAnnotation() ;
loadBeanDefinitions();
}
/**
* 交由registry处理
* 通过扫描到的类,将类封装成BeanDefinition类型
* @return
*/
protected void loadBeanDefinitions(){
List<BeanDefinition> beanDefinitions = new ArrayList<BeanDefinition>() ;
//加载Bean,并且封装成BeanDefinition
try{
for (String registerBeanClass : registerBeanClasses) {
Class<?> beanClass = Class.forName(registerBeanClass) ;
//接口不做处理
if (beanClass.isInterface()){
continue ;
}
BeanDefinition beanDefinition =
doCreateBeanDefinition(StringUtil.toLowerFirstAlp(beanClass.getSimpleName()) , beanClass.getName()) ;
this.registry.registerBeanDefinition(beanDefinition.getFactoryBeanName() , beanDefinition) ;
Class<?>[] interfaces = beanClass.getInterfaces() ;
for (Class<?> anInterface : interfaces) {
//接口名首字母小写
beanDefinition = doCreateBeanDefinition(StringUtil.toLowerFirstAlp(anInterface.getName()) , beanClass.getName()) ;
//registry注册
this.registry.registerBeanDefinition(beanDefinition.getFactoryBeanName() , beanDefinition) ;
}
}
}catch (Exception e){
e.printStackTrace();
}
}
private BeanDefinition doCreateBeanDefinition(String factoryBeanName, String beanClassName) {
BeanDefinition beanDefinition = new DefaultRootBeanDefinition(factoryBeanName , beanClassName) ;
return beanDefinition ;
}
/**
* application.properties下的scanPackage属性
* @param scanPackage
*/
@Override
public void doScanner(String scanPackage) {
if (StringUtil.isNull(scanPackage) || StringUtil.isPackageRegular(scanPackage)){
throw new IllegalArgumentException("scanPackage of application.properties is error") ;
}
URL url = this.getClass().getClassLoader().getResource("/"+scanPackage.replaceAll("\\.","/"));
//获取文件夹
File classPath = new File(url.getFile()) ;
for (File file : classPath.listFiles()) {
if (file.isDirectory()) {
//采用递归的方式
doScanner(scanPackage + "." + file.getName());
continue ;
}
if (!file.getName().endsWith(".class")) {
continue;
}
registerBeanClasses.add(scanPackage + "." + file.getName().replace(".class","")) ;
}
}
@Override
public BeanDefinitionRegistry getRegistry() {
return this.registry ;
}
@Override
public BeanDefinitionRegistry getBeanFactory() {
return this.registry ;
}
}
4. Loader
package org.framework.spring.v1.context.bean.support.loader;
import org.framework.spring.v1.context.bean.config.resource.Resource;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/5 17:35
*/
public interface ResourceLoader {
Resource getResource(String resource) ;
String getProperty(String key) ;
}
package org.framework.spring.v1.context.bean.support.loader.impl;
import org.framework.spring.v1.context.bean.config.resource.Resource;
import org.framework.spring.v1.context.bean.config.resource.impl.DefaultResource;
import org.framework.spring.v1.context.bean.support.loader.ResourceLoader;
import org.framework.spring.v1.tools.StringUtil;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/9 10:28
*/
public class PropertiesResourceLoader implements ResourceLoader {
private Resource resource ;
public PropertiesResourceLoader(String config){
//resource生成properties
this.resource = new DefaultResource(config) ;
}
@Override
public Resource getResource(String resource) {
return this.resource ;
}
@Override
public String getProperty(String key) {
if (StringUtil.isNull(key)){
return null ;
}
return this.resource.getProperty(key) ;
}
}
5. Registry
package org.framework.spring.v1.context.bean.support.registry;
import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/6/22 23:22
*/
public interface BeanDefinitionRegistry {
void registerBeanDefinition(String beanName , BeanDefinition beanDefinition) throws Exception;
boolean removeBeanDefinition(String beanName) ;
BeanDefinition getBeanDefinition(String beanName) ;
boolean containsBeanDefinition(String beanName) ;
String[] getBeanDefinitionNames() ;
int getBeanDefinitionCount() ;
boolean isBeanNameInUse(String beanName) ;
}
package org.framework.spring.v1.context.bean.support.registry.abs;
import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import java.util.Map;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/8 10:02
*/
public abstract class AbstractAnnotationBeanDefinitionRegistry implements BeanDefinitionRegistry {
protected Map<String,BeanDefinition> beanDefinitionMap ;
}
package org.framework.spring.v1.context.bean.support.registry.impl;
import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.support.registry.abs.AbstractAnnotationBeanDefinitionRegistry;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/6/22 23:50
*/
public class AnnotationBeanDefinitionRegistry extends AbstractAnnotationBeanDefinitionRegistry {
public AnnotationBeanDefinitionRegistry() {
this(new ConcurrentHashMap<String, BeanDefinition>()) ;
}
public AnnotationBeanDefinitionRegistry(Map<String,BeanDefinition> beanDefinitionMap){
this.beanDefinitionMap = beanDefinitionMap ;
}
public Map<String,BeanDefinition> getBeanDefinitionMap(){
return this.beanDefinitionMap ;
}
//注册BeanDefinition
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition) throws Exception {
if(this.beanDefinitionMap.containsKey(beanDefinition.getFactoryBeanName())){
throw new Exception("the bean is exist ! { " + beanDefinition.getFactoryBeanName()+" }") ;
}
this.beanDefinitionMap.put(beanName , beanDefinition) ;
}
@Override
public boolean removeBeanDefinition(String beanName) {
this.beanDefinitionMap.remove(beanName) ;
return false;
}
@Override
public BeanDefinition getBeanDefinition(String beanName) {
return this.beanDefinitionMap.get(beanName);
}
@Override
public boolean containsBeanDefinition(String beanName) {
return this.beanDefinitionMap.containsKey(beanName) ;
}
@Override
public String[] getBeanDefinitionNames() {
Set<String> beanNameSet = this.beanDefinitionMap.keySet() ;
String[] beanNames = beanNameSet.toArray(new String[beanNameSet.size()]) ;
return beanNames ;
}
@Override
public int getBeanDefinitionCount() {
return this.beanDefinitionMap.size() ;
}
@Override
public boolean isBeanNameInUse(String beanName) {
return this.containsBeanDefinition(beanName) ;
}
}
6. Wrapper
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FXrADqRj-1594568026709)(C:\Users\keydous\AppData\Roaming\Typora\typora-user-images\image-20200712232714343.png)]
package org.framework.spring.v1.context.bean.support.wrapper;
import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.config.wrapper.BeanWrapper;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/5 23:16
*/
public interface BeanWrapperProcess {
void registerBeanWrapper(BeanDefinition beanDefinition) ;
boolean removeBeanWrapper(String beanName) ;
BeanWrapper getBeanWrapper(String beanName) ;
boolean containsBeanWrapper(String beanName) ;
int getBeanWrapperCount() ;
boolean isBeanWrapperExist(String beanName) ;
String[] getBeanNames() ;
}
package org.framework.spring.v1.context.bean.support.wrapper.abs;
import org.framework.spring.v1.context.bean.config.wrapper.BeanWrapper;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import org.framework.spring.v1.context.bean.support.wrapper.BeanWrapperProcess;
import java.util.Map;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/6 12:21
*/
public abstract class AbstractBeanWrapperProcess implements BeanWrapperProcess {
protected Map<String , BeanWrapper> factoryBeanInstanceCache ;
protected BeanDefinitionRegistry registry ;
public AbstractBeanWrapperProcess(Map<String, BeanWrapper> factoryBeanInstanceCache , BeanDefinitionRegistry registry) {
this.factoryBeanInstanceCache = factoryBeanInstanceCache;
this.registry = registry ;
init() ;
}
protected abstract void init() ;
}
package org.framework.spring.v1.context.bean.support.wrapper.impl;
import org.framework.spring.v1.context.annotation.Component;
import org.framework.spring.v1.context.bean.config.definition.BeanDefinition;
import org.framework.spring.v1.context.bean.config.wrapper.BeanWrapper;
import org.framework.spring.v1.context.bean.config.wrapper.impl.DefaultBeanWrapper;
import org.framework.spring.v1.context.bean.support.registry.BeanDefinitionRegistry;
import org.framework.spring.v1.context.bean.support.wrapper.abs.AbstractBeanWrapperProcess;
import org.framework.spring.v1.tools.StringUtil;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/5 23:14
*/
public class BeanWrapperProcessImpl extends AbstractBeanWrapperProcess {
public BeanWrapperProcessImpl(Map<String, BeanWrapper> factoryBeanInstanceCache , BeanDefinitionRegistry registry) {
super(factoryBeanInstanceCache ,registry);
}
@Override
protected void init() {
String[] beanNames = this.registry.getBeanDefinitionNames() ;
for (String beanName : beanNames) {
registerBeanWrapper(this.registry.getBeanDefinition(beanName));
}
}
public BeanWrapperProcessImpl(BeanDefinitionRegistry registry){
this(new ConcurrentHashMap<String, BeanWrapper>() , registry) ;
}
@Override
public void registerBeanWrapper(BeanDefinition beanDefinition) {
String beanName = beanDefinition.getFactoryBeanName() ;
BeanWrapper beanWrapper = doCreateWrapper(beanDefinition) ;
if (StringUtil.isNull(beanName) || beanWrapper == null){
return ;
}
this.factoryBeanInstanceCache.put(beanName,beanWrapper) ;
}
private BeanWrapper doCreateWrapper(BeanDefinition beanDefinition) {
String className = beanDefinition.getBeanClassName() ;
try {
Class<?> clazz = Class.forName(className) ;
/**
* 并不是所有的类都初始化,只有是组件的才初始化
*/
if (!clazz.isAnnotationPresent(Component.class)){
if (!clazz.isInterface()){
return null ;
}
}
Object bean = clazz.newInstance() ;
BeanWrapper beanWrapper = new DefaultBeanWrapper(bean , beanDefinition.getScopeValue()) ;
return beanWrapper ;
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InstantiationException e) {
e.printStackTrace();
}
return null ;
}
@Override
public boolean removeBeanWrapper(String beanName) {
BeanWrapper bw = this.factoryBeanInstanceCache.remove(beanName) ;
return bw != null ;
}
@Override
public BeanWrapper getBeanWrapper(String beanName) {
return this.factoryBeanInstanceCache.get(beanName) ;
}
@Override
public boolean containsBeanWrapper(String beanName) {
return this.factoryBeanInstanceCache.containsKey(beanName) ;
}
@Override
public int getBeanWrapperCount() {
return this.factoryBeanInstanceCache.size() ;
}
@Override
public boolean isBeanWrapperExist(String beanName) {
return this.containsBeanWrapper(beanName) ;
}
@Override
public String[] getBeanNames() {
Set<String> beanNames = this.factoryBeanInstanceCache.keySet();
String[] bns = beanNames.toArray(new String[beanNames.size()]);
return bns ;
}
}
7. Autowire
package org.framework.spring.v1.context.bean.support.autowire;
import java.util.List;
import java.util.Map;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/5 23:34
*/
public interface BeanPostProcessor {
Object getBean(String beanName) ;
boolean registerBean(String beanName , Object o) ;
boolean isBeanNameExist(String beanName) ;
boolean isBeanExist(Object bean) ;
List<Object> getBeans() ;
int getBeanCount() ;
Map<String,Object> getIoc() ;
}
package org.framework.spring.v1.context.bean.support.autowire.abs;
import org.framework.spring.v1.context.bean.support.factory.abs.AbstractSingletonFactoryBean;
import org.framework.spring.v1.context.bean.support.factory.impl.SimpleSingletonFactoryBean;
import org.framework.spring.v1.context.bean.support.autowire.BeanPostProcessor;
import org.framework.spring.v1.context.bean.support.wrapper.BeanWrapperProcess;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/5 23:46
*/
public abstract class AbstractBeanPostProcessor implements BeanPostProcessor {
protected Map<String,Object> ioc ;
protected BeanWrapperProcess process ;
protected AbstractSingletonFactoryBean factoryBean ;
public AbstractBeanPostProcessor(Map<String, Object> ioc, BeanWrapperProcess beanWrapperProcess , AbstractSingletonFactoryBean factoryBean) {
this.factoryBean = factoryBean ;
this.ioc = ioc;
this.process = beanWrapperProcess;
}
public AbstractBeanPostProcessor(BeanWrapperProcess beanWrapperProcess , AbstractSingletonFactoryBean factoryBean) {
this(new ConcurrentHashMap<String, Object>() , beanWrapperProcess , factoryBean) ;
init() ;
}
public AbstractBeanPostProcessor(BeanWrapperProcess beanWrapperProcess){
this(new ConcurrentHashMap<String, Object>() , beanWrapperProcess , new SimpleSingletonFactoryBean()) ;
}
protected abstract void init();
}
package org.framework.spring.v1.context.bean.support.autowire.impl;
import org.framework.spring.v1.context.annotation.Autowired;
import org.framework.spring.v1.context.bean.config.wrapper.BeanWrapper;
import org.framework.spring.v1.context.bean.support.factory.impl.SimpleSingletonFactoryBean;
import org.framework.spring.v1.context.bean.support.autowire.abs.AbstractBeanPostProcessor;
import org.framework.spring.v1.context.bean.support.wrapper.BeanWrapperProcess;
import org.framework.spring.v1.tools.StringUtil;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* @author gyh
* @csdn https://blog.csdn.net/qq_40788718
* @date 2020/7/5 23:45
*/
public class AnnotationBeanPostProcessor extends AbstractBeanPostProcessor {
public AnnotationBeanPostProcessor(BeanWrapperProcess beanWrapperProcess) {
super(beanWrapperProcess , new SimpleSingletonFactoryBean());
}
@Override
protected void init() {
String[] beanNames = this.process.getBeanNames() ;
for (String beanName : beanNames) {
this.registerBean(beanName , this.process.getBeanWrapper(beanName).getWrapperInstance()) ;
}
}
@Override
public Object getBean(String beanName) {
return this.ioc.get(beanName) ;
}
@Override
public boolean registerBean(String beanName, Object o) {
Field[] fields = o.getClass().getDeclaredFields() ;
for (Field field : fields) {
if (!field.isAnnotationPresent(Autowired.class)){
continue ;
}
Autowired autowired = field.getAnnotation(Autowired.class) ;
String autowiredValue ;
String fieldName = "".equals(autowiredValue = autowired.value().trim())
? StringUtil.toLowerFirstAlp(field.getType().getSimpleName()) : autowiredValue ;
BeanWrapper bw = this.process.getBeanWrapper(fieldName) ;
field.setAccessible(true) ;
try {
field.set(o , bw.getWrapperInstance()) ;
} catch (IllegalAccessException e) {
e.printStackTrace() ;
}
}
//ioc容器注入
this.ioc.put(beanName,o) ;
return true ;
}
@Override
public boolean isBeanNameExist(String beanName) {
return this.ioc.containsKey(beanName) ;
}
@Override
public boolean isBeanExist(Object bean) {
return this.ioc.containsValue(bean);
}
@Override
public List<Object> getBeans() {
return new ArrayList<Object>(this.ioc.values()) ;
}
@Override
public int getBeanCount() {
return this.ioc.size() ;
}
@Override
public Map<String, Object> getIoc() {
return this.ioc ;
}
}