源码分析---SPRING
- 项目介绍
1. Spring框架简介
作为应用程序开发人员,您可以从Spring平台中受益的示例如下:
使Java方法在数据库事务中执行,而不必处理事务API。
使本地Java方法成为HTTP端点,而无需处理Servlet API。
使本地Java方法成为消息处理程序,而无需处理JMS API。
使本地Java方法成为管理操作,而无需处理JMX API。
2.1依赖注入和控制反转
Java应用程序 - 从受限制的嵌入式应用程序到n层服务器端企业应用程序的宽松术语 - 通常由协作形成应用程序的对象组成。因此,应用程序中的对象彼此依赖。
Spring框架控制反转(IoC)组件通过提供一种将不同组件组合成一个可以使用的完全工作的应用程序的形式化方法来解决这一问题。Spring Framework将形式化的设计模式编码为可以集成到您自己的应用程序中的一流对象。许多组织和机构以这种方式使用Spring Framework来设计健壮,可维护的应用程序。
2.2框架模块
Spring框架是一个分层架构,它包含一系列的功能要素,并被分为大约20个模块,如下图所示
Spring4框架图
这些模块被总结为以下几个部分:
Core Container核心容器
所述核心容器由以下部分组成spring-core, spring-beans,spring-context,spring-context-support,和spring-expression (弹簧表达式语言)模块。
的spring-core和spring-beans模块提供框架的基本零件,包括IOC和依赖注入特征。这 BeanFactory是工厂模式的复杂实现。它消除了对程序化单例的需求,并允许您从实际程序逻辑中分离依赖项的配置和规范。
所述上下文(spring-context)模块建立由设置在固体基体上的核心和豆类模块:它是访问一个框架式的方式是类似于一个JNDI注册表对象的装置。Context模块从Beans模块继承其功能,并添加对国际化(例如,使用资源包),事件传播,资源加载以及通过例如Servlet容器透明创建上下文的支持。Context模块还支持Java EE功能,例如EJB,JMX和基本远程处理。该ApplicationContext接口是语境模块的焦点。 spring-context-support支持将常见的第三方库集成到Spring应用程序上下文中,用于缓存(EhCache,Guava,JCache),邮件(JavaMail),调度(CommonJ,Quartz)和模板引擎(FreeMarker,JasperReports,Velocity)。
该spring-expression模块提供了一种功能强大的表达式语言,用于在运行时查询和操作对象图。它是JSP 2.1规范中指定的统一表达式语言(统一EL)的扩展。该语言支持设置和获取属性值,属性赋值,方法调用,访问数组,集合和索引器的内容,逻辑和算术运算符,命名变量以及从Spring的IoC容器中按名称检索对象。它还支持列表投影和选择以及常用列表聚合。
Data Access/Integration
JDBC模块提供了一个JDBC抽象层,它可以消除冗长的JDBC编码和解析数据库厂商特有的错误代码,这个模块包含了Spring对JDBC数据访问进行封装的所有类
ORM模块为流行的对象-关系映射API,如JPA、JDO、Hibernate、iBatis等,提供了一个交互层,利用ORM封装包,可以混合使用所有Spring提供的特性进行O/R映射,如前边提到的简单声明性事务管理
所述数据访问/集成层由JDBC,ORM,OXM,JMS和交易模块。
该spring-jdbc模块提供了一个JDBC -abstraction层,无需进行繁琐的JDBC编码和解析数据库供应商特定的错误代码。
该spring-tx模块支持 对实现特殊接口的类和所有POJO(普通旧Java对象)的类进行编程和声明式事务管理。
该spring-orm模块为流行的对象关系映射 API 提供了集成层 ,包括JPA, JDO和Hibernate。使用该spring-orm模块,您可以将所有这些O / R映射框架与Spring提供的所有其他功能结合使用,例如前面提到的简单声明式事务管理功能。
该spring-oxm模块提供了一个抽象层,支持对象/ XML映射实现,如JAXB,Castor,XMLBeans,JiBX和XStream。
所述spring-jms模块(Java消息服务)包含用于生成和使用消息的功能。从Spring Framework 4.1开始,它提供了与spring-messaging模块的集成 。
Web
所述网络层由的spring-web,spring-webmvc,spring-websocket,和 spring-webmvc-portlet模块。
该spring-web模块提供基本的面向Web的集成功能,例如多部分文件上载功能以及使用Servlet侦听器和面向Web的应用程序上下文初始化IoC容器。它还包含一个HTTP客户端以及Spring的远程支持的Web相关部分。
该spring-webmvc模块(也称为Web-Servlet模块)包含Spring的模型 - 视图 - 控制器(MVC)和Web应用程序的REST Web服务实现。Spring的MVC框架提供了域模型代码和Web表单之间的清晰分离,并与Spring Framework的所有其他功能集成在一起。
该spring-webmvc-portlet模块(也称为Web-Portlet模块)提供了在Portlet环境中使用的MVC实现,并镜像了基于Servlet的spring-webmvc模块的功能。
Message
Spring框架4包括spring-messaging从关键抽象模块 Spring集成项目,例如Message,MessageChannel,MessageHandler,和其他人作为基于消息的应用奠定了基础。该模块还包括一组用于将消息映射到方法的注释,类似于基于Spring MVC注释的编程模型。
AOP
AOP模块提供了一个符合AOP联盟标准的面向切面编程的实现,它让你可以定义例如方法拦截器和切点,从而将逻辑代码分开,降低它们之间的耦合性,利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中。
单独的spring-aspects模块提供与AspectJ的集成。
该spring-instrument模块提供了在某些应用程序服务器中使用的类检测支持和类加载器实现。该spring-instrument-tomcat 模块包含Spring的Tomcat检测代理。
Test
该spring-test模块支持使用JUnit或TestNG对Spring组件进行单元测试和集成测试。
Spring 依赖
GroupId | ArtifactId |
org.springframework | spring-aop |
org.springframework | spring-aspects |
org.springframework | spring-beans |
org.springframework | spring-context |
org.springframework | spring-context-support |
org.springframework | spring-core |
org.springframework | spring-expression |
org.springframework | spring-instrument |
org.springframework | spring-instrument-tomcat |
org.springframework | spring-jdbc |
org.springframework | spring-jms |
org.springframework | spring-messaging |
org.springframework | spring-orm |
org.springframework | spring-oxm |
org.springframework | spring-test |
org.springframework | spring-tx |
org.springframework | spring-web |
org.springframework | spring-webmvc |
org.springframework | spring-webmvc-portlet |
org.springframework | spring-websocket |
- 设计思想
- 通过容器装配所用的BEAN
- 通过工厂模板创建bean
- 通过DI完成依赖注入
- 类图设计
1、xml容器初始化过程
2、注解容器加载过程
- ComponentScanBeanDefinitionParser.parse 解析注解
- 核心分析
1、ApplicationContext与BeanFactory ioc探究
实例化的工作会在容器启动后过AbstractApplicationContext中reflash方法自动进行。我们常用的ApplicationContext实现类ClassPathXmlApplicationContext继承了AbstractApplicationContext类,继承关系如下图.
AbstractApplicationContext里的reflash方法是Spring初始IOC容器一个非常重要的方法,不管你是ApplicationContext哪个实现类,最终都会进入这个方法。
IOC实现
ApplicationContext 容器
ClassPathXmlApplicationContext
FileSystemXmlApplicationContext
AbstractApplicationContext
//ioc核心代码 初始化Bean窗口过程
public void refresh() throws BeansException, IllegalStateException {
Object var1 = this.startupShutdownMonitor;
synchronized(this.startupShutdownMonitor) {
// 调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
this.prepareRefresh();
/告诉子类启动refreshBeanFactory()方法,Bean定义资源文件的载入从 //子类的refreshBeanFactory()方法启动
ConfigurableListableBeanFactory beanFactory = this.obtainFreshBeanFactory();
this.prepareBeanFactory(beanFactory);
try {
//为容器的某些子类指定特殊的BeanPost事件处理器
this.postProcessBeanFactory(beanFactory);
this.invokeBeanFactoryPostProcessors(beanFactory);
//为BeanFactory注册BeanPost事件处理器.
//BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
this.registerBeanPostProcessors(beanFactory);
//初始化信息源,和国际化相关.
this.initMessageSource();
//初始化容器事件传播器.
this.initApplicationEventMulticaster();
//调用子类的某些特殊Bean初始化方法
this.onRefresh();
//为事件传播器注册事件监听器.
this.registerListeners();
//初始化所有剩余的单态Bean.
this.finishBeanFactoryInitialization(beanFactory);
this.finishRefresh();
} catch (BeansException var9) {
if(this.logger.isWarnEnabled()) {
this.logger.warn("Exception encountered during context initialization - cancelling refresh attempt: " + var9);
}
//销毁以创建的单态Bean
this.destroyBeans();
//取消refresh操作,重置容器的同步标识.
this.cancelRefresh(var9);
throw var9;
} finally {
//清空缓存
this.resetCommonCaches();
}
}
}
//刷新bean工厂
protected final void refreshBeanFactory() throws BeansException {
if(this.hasBeanFactory()) {
this.destroyBeans();
this.closeBeanFactory();
}
try {
DefaultListableBeanFactory beanFactory = this.createBeanFactory();
beanFactory.setSerializationId(this.getId());
this.customizeBeanFactory(beanFactory);
this.loadBeanDefinitions(beanFactory);
Object var2 = this.beanFactoryMonitor;
synchronized(this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
} catch (IOException var5) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + this.getDisplayName(), var5);
}
}
loadBeanDefinitions 加载BeanDefinition
AOP核心分析
1、Jdk动态代理实现
- 手写实现
- 手写spring ioc di 容器与依赖注入
- 目录结构
- bean接口
package com.ofsoft.framework.core;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.core.ResolvableType;
/**
* @author OF
* @version v1.0
* @className BenaFaction
* @date 2018/9/27
*/
public interface OFBeanFactory {
String FACTORY_BEAN_PREFIX = "&";
Object getBean(String var1);
<T> T getBean(String var1, Class<T> var2) ;
<T> T getBean(Class<T> var1) throws IllegalAccessException, InstantiationException;
Class<?> getType(String var1);
}
- 具体实现
package com.ofsoft.framework.core;
import com.ofsoft.framework.annotation.OFAutowired;
import com.ofsoft.framework.stereotype.OFComponent;
import com.ofsoft.framework.stereotype.OFRepository;
import com.ofsoft.framework.stereotype.OFService;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author OF
* @version v1.0
* @className OFApplicationContext
* @date 2018/9/27
*/
public class OFApplicationContext implements OFBeanFactory {
private static Map<String, Object> iocMapping = new ConcurrentHashMap<String, Object>();
public OFApplicationContext(String basePackage) {
init(basePackage);
}
/**
* 初始化
*
* @param basePackage
*/
private void init(String basePackage) {
//初始化配置文件
//加载IOC容器
initBean(basePackage);
//di依赖注入
inject();
}
private void initBean(String basePackage) {
//获取所用文件
List<String> files = findClassScanner(basePackage);
for (String fileName : files) {
Class<?> clazz = getClass(fileName);
//别名
String alis = getClassForAlis(clazz);
if (alis != null) {
Object obj = newInstance(clazz);
if ("".equals(alis)) {
iocMapping.put(firstToLowerCase(clazz.getSimpleName()), obj);
//根据接口类型实例
Class[] interfaces = clazz.getInterfaces();
for (Class anInterface : interfaces) {
iocMapping.put(firstToLowerCase(anInterface.getSimpleName()), obj);
}
} else {
//根据别名
iocMapping.put(alis, obj);
}
}
}
}
private String firstToLowerCase(String str) {
char[] c = str.toCharArray();
c[0] += 32;
return String.valueOf(c);
}
private Class<?> getClass(String classPath) {
try {
return Class.forName(classPath);
} catch (ClassNotFoundException e) {
e.printStackTrace();
return null;
}
}
private Object newInstance(Class clazz) {
try {
return clazz.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
/**
*
*/
public String getClassForAlis(Class<?> clazz) {
if (clazz.isAnnotationPresent(OFRepository.class) && !clazz.isAssignableFrom(OFRepository.class)) {
OFRepository repository = clazz.getAnnotation(OFRepository.class);
return repository.value();
} else if (clazz.isAnnotationPresent(OFService.class) && !clazz.isAssignableFrom(OFService.class)) {
OFService service = clazz.getAnnotation(OFService.class);
return service.value();
} else if (clazz.isAnnotationPresent(OFComponent.class) && !clazz.isAssignableFrom(OFComponent.class) && !clazz.isAssignableFrom(OFRepository.class) && !clazz.isAssignableFrom(OFService.class)) {
OFComponent component = clazz.getAnnotation(OFComponent.class);
return component.value();
} else {
return null;
}
}
private List<String> findClassScanner(final String basePackage) {
File file = new File(this.getClass().getClassLoader().getResource(basePackage.replaceAll("\\.", "/")).getFile());
final List<String> classFiles = new ArrayList<String>();
file.listFiles(new FileFilter() {
@Override
public boolean accept(File file) {
if (file.isDirectory()) {
classFiles.addAll(findClassScanner(basePackage + "." + file.getName()));
} else {
if (file.getName().endsWith(".class")) {
classFiles.add(basePackage + "." + file.getName().replace(".class", ""));
return true;
}
}
return false;
}
});
return classFiles;
}
@Override
public Object getBean(String beanName) {
return iocMapping.get(beanName);
}
@Override
public <T> T getBean(String beanName, Class<T> type) {
return type.cast(getBean(beanName));
}
@Override
public <T> T getBean(Class<T> type) {
try {
return type.newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return null;
}
@Override
public Class<?> getType(String beanName) {
return getBean(beanName).getClass();
}
private void inject() {
try {
for (Map.Entry<String, Object> entry : iocMapping.entrySet()) {
String clazz = entry.getKey();
Object obj = entry.getValue();
//获取所用字段
Field[] fields = obj.getClass().getDeclaredFields();
for (Field field : fields) {
if (field.isAnnotationPresent(OFAutowired.class)) {
//设置访问权限
field.setAccessible(true);
OFAutowired autowired = field.getAnnotation(OFAutowired.class);
if (!"".equals(autowired.value())) {
//根据别名
Object object = iocMapping.get(autowired.value());
field.set(obj, object);
} else {
//根据类型
Class<?> fieldClazz = field.getType();
Iterator iter = iocMapping.values().iterator();
while (iter.hasNext()) {
Object object = iter.next();
if (fieldClazz.isAssignableFrom(object.getClass())) {
field.set(obj, object);
break;
}
}
}
}
}
}
} catch (IllegalAccessException e1) {
e1.printStackTrace();
}
}
}
- 测试
package com.ofsoft.demo;
import com.ofsoft.demo.bean.TestBean;
import com.ofsoft.framework.core.OFApplicationContext;
import com.ofsoft.demo.service.UserService;
/**
* @author OF
* @version v1.0
* @className App
* @date 2018/9/27
*/
public class App {
public static void main(String[] args) {
OFApplicationContext applicationContext = new OFApplicationContext("com.ofsoft");
UserService userService = (UserService) applicationContext.getBean("userService");
userService.showUser();
TestBean testBean = applicationContext.getBean("testBean", TestBean.class);
testBean.show();
}
}
- 手写AOP
//代理对象需要的实现的接口
//利用spring的API,创建接口代理工厂
ProxyFactory proxy = new ProxyFactory();
proxy.setTarget(new Animal());
proxy.addAdvice(new MethodBeforeAdvice() {
@Override
public void before(Method method, Object[] objects, Object o) throws Throwable {
System.out.println("在吃饭方法调用之前拦截:吃饭前要洗手");
}
});
proxy.addAdvice(new AfterReturningAdvice() {
@Override
public void afterReturning(Object boj,Method method, Object[] objects, Object o) throws Throwable {
System.out.println("吃饭方法完成之后调用:饭后要洗碗");
}
});
Animal animalProxy = (Animal) proxy.getProxy();
animalProxy.eat();
- 总结(设计模式)
- 策略
- 模板
- 工厂
- 代理
- 接口隔离
- 依赖倒置
- 开闭原则
- 单一原则
类方法:判断类类型是否相同。
isAssignableFrom