目录导航
前言
这个小节,我们根据spring源码来进一步封装IOC与AOP源码~
手写SpringV2.0
一切从ApplicationContext上下文开始
spring的ApplicationContext最核心的方法就是refresh了,这个我们之前讲过,所以我这边先预留出来一个refresh方法。
public class GPApplicationContext{
public void refresh(){}
}
然后让其实现 BeanFactory
public interface GPBeanFactory {
/**
* 根据beanName从IOC容器之中获得一个实例Bean
* @param beanName
* @return
*/
Object getBean(String beanName);
}
得到:
public class GPApplicationContext implements GPBeanFactory {
private String [] configLocations;
private GPBeanDefinitionReader reader;
//用来保证注册式单例的容器
private Map<String,Object> beanCacheMap = new HashMap<String, Object>();
//用来存储所有的被代理过的对象
private Map<String,GPBeanWrapper> beanWrapperMap = new ConcurrentHashMap<String, GPBeanWrapper>();
public GPApplicationContext(String ... configLocations){
this.configLocations = configLocations;
refresh();
}
//依赖注入,从这里开始,通过读取BeanDefinition中的信息
//然后,通过反射机制创建一个实例并返回
//Spring做法是,不会把最原始的对象放出去,会用一个BeanWrapper来进行一次包装
//装饰器模式:
//1、保留原来的OOP关系
//2、我需要对它进行扩展,增强(为了以后AOP打基础)
@Override
public Object getBean(String beanName) {
GPBeanDefinition beanDefinition = this.beanDefinitionMap.get(beanName);
String className = beanDefinition.getBeanClassName();
try{
//生成通知事件
GPBeanPostProcessor beanPostProcessor = new GPBeanPostProcessor();
Object instance = instantionBean(beanDefinition);
if(null == instance){ return null;}
//在实例初始化以前调用一次
beanPostProcessor.postProcessBeforeInitialization(instance,beanName);
GPBeanWrapper beanWrapper = new GPBeanWrapper(instance);
beanWrapper.setAopConfig(instantionAopConfig(beanDefinition));
beanWrapper.setPostProcessor(beanPostProcessor);
this.beanWrapperMap.put(beanName,beanWrapper);
//在实例初始化以后调用一次
beanPostProcessor.postProcessAfterInitialization(instance,beanName);
// populateBean(beanName,instance);
//通过这样一调用,相当于给我们自己留有了可操作的空间
return this.beanWrapperMap.get(beanName).getWrappedInstance();
}catch (Exception e){
e.printStackTrace();
}
return null;
}
private GPAopConfig instantionAopConfig(GPBeanDefinition beanDefinition) throws Exception{
GPAopConfig config = new GPAopConfig();
String expression = reader.getConfig().getProperty("pointCut");
String[] before = reader.getConfig().getProperty("aspectBefore").split("\\s");
String[] after = reader.getConfig().getProperty("aspectAfter").split("\\s");
String className = beanDefinition.getBeanClassName();
Class<?> clazz = Class.forName(className);
Pattern pattern = Pattern.compile(expression);
Class aspectClass = Class.forName(before[0]);
//在这里得到的方法都是原生的方法
for (Method m : clazz.getMethods()){
//public .* com\.gupaoedu\.vip\.spring\.demo\.service\..*Service\..*\(.*\)
//public java.lang.String com.gupaoedu.vip.spring.demo.service.impl.ModifyService.add(java.lang.String,java.lang.String)
Matcher matcher = pattern.matcher(m.toString());
if(matcher.matches()){
//能满足切面规则的类,添加的AOP配置中
config.put(m,aspectClass.newInstance(),new Method[]{aspectClass.getMethod(before[1]),aspectClass.getMethod(after[1])});
}
}
return config;
}
//传一个BeanDefinition,就返回一个实例Bean
private Object instantionBean(GPBeanDefinition beanDefinition){
Object instance = null;
String className = beanDefinition.getBeanClassName();
try{
//因为根据Class才能确定一个类是否有实例
if(this.beanCacheMap.containsKey(className)){
instance = this.beanCacheMap.get(className);
}else{
Class<?> clazz = Class.forName(className);
instance = clazz.newInstance();
this.beanCacheMap.put(className,instance);
}
return instance;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
}
BeanDefinitionReader用对配置文件进行查找,读取、解析
public class GPBeanDefinitionReader {
private Properties config = new Properties();
private List<String> registyBeanClasses = new ArrayList<String>();
//在配置文件中,用来获取自动扫描的包名的key
private final String SCAN_PACKAGE = "scanPackage";
public GPBeanDefinitionReader(String... locations){
//在Spring中是通过Reader去查找和定位对不对
InputStream is = this.getClass().getClassLoader().getResourceAsStream(locations[0].replace("classpath:",""));
try {
config.load(is);
} catch (IOException e) {
e.printStackTrace();
}finally {
try {
if(null != is){is.close();}
}catch (Exception e){
e.printStackTrace();
}
}
doScanner(config.getProperty(SCAN_PACKAGE));
}
public List<String> loadBeanDefinitions(){
return this.registyBeanClasses;
}
//每注册一个className,就返回一个BeanDefinition,我自己包装
//只是为了对配置信息进行一个包装
public GPBeanDefinition registerBean(String className){
if(this.registyBeanClasses.contains(className)){
GPBeanDefinition beanDefinition = new GPBeanDefinition();
beanDefinition.setBeanClassName(className);
beanDefinition.setFactoryBeanName(lowerFirstCase(className.substring(className.lastIndexOf(".") + 1)));
return beanDefinition;
}
return null;
}
//递归扫描所有的相关联的class,并且保存到一个List中
private void doScanner(String packageName) {
URL url = this.getClass().getClassLoader().getResource("/" + packageName.replaceAll("\\.","/"));
File classDir = new File(url.getFile());
for (File file : classDir.listFiles()){
if(file.isDirectory()){
doScanner(packageName + "." +file.getName());
}else {
registyBeanClasses.add(packageName + "." + file.getName().replace(".class",""));
}
}
}
public Properties getConfig(){
return this.config;
}
private String lowerFirstCase(String str){
char [] chars = str.toCharArray();
chars[0] += 32;
return String.valueOf(chars);
}
}
BeanDefinition用来存储配置文件中的信息
BeanDefinition相当于保存在内存中的配置
public class GPBeanDefinition {
private String beanClassName;
private boolean lazyInit = false;
private String factoryBeanName;
public String getBeanClassName() {
return beanClassName;
}
public void setBeanClassName(String beanClassName) {
this.beanClassName = beanClassName;
}
public boolean isLazyInit() {
return lazyInit;
}
public void setLazyInit(boolean lazyInit) {
this.lazyInit = lazyInit;
}
public String getFactoryBeanName() {
return factoryBeanName;
}
public void setFactoryBeanName(String factoryBeanName) {
this.factoryBeanName = factoryBeanName;
}
}
BeanWrapper
public class GPBeanWrapper extends GPFactoryBean {
private GPAopProxy aopProxy = new GPAopProxy();
public GPBeanPostProcessor getPostProcessor() {
return postProcessor;
}
public void setPostProcessor(GPBeanPostProcessor postProcessor) {
this.postProcessor = postProcessor;
}
//还会用到 观察者 模式
//1、支持事件响应,会有一个监听
private GPBeanPostProcessor postProcessor;
private Object wrapperInstance;
//原始的通过反射new出来,要把包装起来,存下来
private Object originalInstance;
public GPBeanWrapper(Object instance){
//从这里开始,我们要把动态的代码添加进来了
this.wrapperInstance = aopProxy.getProxy(instance);
this.originalInstance = instance;
}
public Object getWrappedInstance(){
return this.wrapperInstance;
}
// 返回代理以后的Class
// 可能会是这个 $Proxy0
public Class<?> getWrappedClass(){
return this.wrapperInstance.getClass();
}
public void setAopConfig(GPAopConfig config){
aopProxy.setConfig(config);
}
public Object getOriginalInstance() {
return originalInstance;
}
}
BeanPostProcessor用做事件监听
public class GPBeanPostProcessor {
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName){
return bean;
}
}
refresh方法实现定位、加载、注册功能
回到ApplicationContext上下文这个核心类,我们现在实现refresh方法。
public void refresh(){
//定位
this.reader = new GPBeanDefinitionReader(configLocations);
//加载
List<String> beanDefinitions = reader.loadBeanDefinitions();
//注册
doRegisty(beanDefinitions);
//依赖注入(lazy-init = false),要是执行依赖注入
//在这里自动调用getBean方法
doAutowrited();
// MyAction myAction = (MyAction)this.getBean("myAction");
// myAction.query(null,null,"任性的Tom老师");
}
然后实现注册:
//真正的将BeanDefinitions注册到beanDefinitionMap中
private void doRegisty(List<String> beanDefinitions) {
//beanName有三种情况:
//1、默认是类名首字母小写
//2、自定义名字
//3、接口注入
try {
for (String className : beanDefinitions) {
Class<?> beanClass = Class.forName(className);
//如果是一个接口,是不能实例化的
//用它实现类来实例化
if(beanClass.isInterface()){ continue; }
GPBeanDefinition beanDefinition = reader.registerBean(className);
if(beanDefinition != null){
this.beanDefinitionMap.put(beanDefinition.getFactoryBeanName(),beanDefinition);
}
Class<?>[] interfaces = beanClass.getInterfaces();
for (Class<?> i: interfaces) {
//如果是多个实现类,只能覆盖
//为什么?因为Spring没那么智能,就是这么傻
//这个时候,可以自定义名字
this.beanDefinitionMap.put(i.getName(),beanDefinition);
}
//到这里为止,容器初始化完毕
}
}catch (Exception e){
e.printStackTrace();
}
}
实现自动注入:
//开始执行自动化的依赖注入
private void doAutowrited() {
for(Map.Entry<String,GPBeanDefinition> beanDefinitionEntry : this.beanDefinitionMap.entrySet()){
String beanName = beanDefinitionEntry.getKey();
if(!beanDefinitionEntry.getValue().isLazyInit()){
Object obj = getBean(beanName);
// System.out.println(obj.getClass());
}
}
for(Map.Entry<String,GPBeanWrapper> beanWrapperEntry : this.beanWrapperMap.entrySet()){
populateBean(beanWrapperEntry.getKey(),beanWrapperEntry.getValue().getOriginalInstance());
}
// System.out.println("===================");
}
public void populateBean(String beanName,Object instance){
Class clazz = instance.getClass();
//不是所有牛奶都叫特仑苏
if(!(clazz.isAnnotationPresent(GPController.class) ||
clazz.isAnnotationPresent(GPService.class))){
return;
}
Field [] fields = clazz.getDeclaredFields();
for (Field field : fields) {
if (!field.isAnnotationPresent(GPAutowired.class)){ continue; }
GPAutowired autowired = field.getAnnotation(GPAutowired.class);
String autowiredBeanName = autowired.value().trim();
if("".equals(autowiredBeanName)){
autowiredBeanName = field.getType().getName();
}
field.setAccessible(true);
try {
//System.out.println("=======================" +instance +"," + autowiredBeanName + "," + this.beanWrapperMap.get(autowiredBeanName));
field.set(instance,this.beanWrapperMap.get(autowiredBeanName).getWrappedInstance());
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}