现在假设spring就是个容器,而配置文件中配置的bean属性才是我们真正需要的东西。
创建实例就是说,我把配置文件中的bean信息取出来化作一个真正的bean(实例化)并放到容器中。
InstantiationAwareBeanPostProcessor是实例化前后做的事情。
3-4:注入依赖关系;
第3步是创建实例之后对实例作了一些处理,第4步是把xml中配置的bean属性值赋予给容器中的实例化之后的bean。
5:bean初始化之前的处理;
BeanPostProcessor是初始化前后做的事情。
应用开发者需要把容器中实例化的bean拿出来用,这个拿出来的过程就是初始化(注意实例化与初始化的区别,instantiation (实例化)和initialization(初始化)),第五步就是在初始化之前,对已经实例化的bean再作一定的处理。
6,7:初始化。
如果bean实现了InitializingBean,那么将调用InitializingBean的afterPropertiesSet()方法做一些初始化处理。
如果没有实现InitializingBean,而是在配置文件中定义了init-method属性值,那么系统会找到init-method对应的方法并执行之,程序猿哥哥一般在这个方法里写一些初始化操作;
8:bean初始化之后的处理。
初始化之后在这个方法中再对bean进行修饰装点。
9,10:交给应用开发人员处理;
如果在
11.bean用完之后;
对于scope="singleton"的bean,使用完之后spring容器会做一些处理,比如编写释放资源、记录日志等操作。
12.销毁;
调用配置文件中的销毁方法销毁实例。
XML Schema : 用来描述 XML文档的结构,也被简称为XSD(XML Schema Definition),是一些规则的集合。(方式:通过定义schema文件 如 spring-tx-3.0.xsd)
xmlns : 命名空间是W3C推荐标准提供的一种统一命名XML文档中的元素和属性的机制
.xsd文件 : 用XML w3c 标准命名空间中规定的元素和属性编写的以targetNamespace作为{目标命名空间}的XML文件,能够约束引入此{目标命名空间}定义的元素和属性的XML文件。
.targetNamespace : 目标命名空间,它的主要作用是指明Schema定义的元素的命名空间。
classpath:properties/druid.properties
xmlns : 是spring的内置xsd xsi : 是调用xsi的schemaLocation去寻找具体的xsd位置
Spring除了基于XML的配置,还有基于Bean,基于注解的配置。但是基于XML的配置功能最强
IOC, spring的核心,贯穿Spring始终。直观的来说,就是由spring来负责控制对象的生命周期和对象间的关系,将对象之间的关系抽象出来,通过spring容器控制对象生成时机,减少对象之间的耦合度。
SpringIOC 的主要依赖源码是 spring-beans 和 spring-context两个包。
IOC容器指的是实现对依赖对象的创建(无参构造器)、管理(参数注入)、销毁(关闭BeanFactory).
spring的依赖注入有属性注入、构造函数注入、工厂方法注入等多种方式。Spring要把xml配置中bean的属性实例化为具体的bean,"依赖注入"是关卡。所谓的"依赖注入",就是把应用程序对bean的属性依赖都注入到spring容器中。
首先是属性注入:
host.com
aili.com
apple.com
yun.qq.com
BMW
BYD
7.HashMap
8.Properties 它是一种特殊的Map,键值都是String类型
[email protected]
[email protected]
构造函数注入: 构造函数的注入可以让属性在实例化的过程中就有了值(其实就相当于java在bean的构造函数中给属性赋值,只不过现在是在xml配置中实现)
niaofuli.com
20000
工厂方法的注入:
工厂类负责创建一个或者多个bean实例,调用工厂方法即可获取该实例。一旦在XML中注册了某工厂,那么调用工厂的过程中已经把该Bean实例化了。
code
package com.test;
public class CarFactory {
public Car createCar(){
Car car = new Car();
car.setBrand("红旗");
return car;
}
}
code 第6行的factory-bean指向第7行的id,第6行的factory-method就是Factory要调用的方法。第7行是Factory的Bean配置(也就是说,CarFactory这个java写的工厂类本身也是一个bean ).调用createCar就可以获取Car实例。
如果方法是静态的:
spring使用p命名空间进一步作了简化。
修改前
p命名
基于注解配置
基于XML的bean属性配置:bean的定义信息与bean的实现类是分离的。// 基于注解的配置:bean的定义信息是通过在bean实现类上标注注解实现。
1、Component : spring看到这个属性标志,会自动将FilterDao变成容器管理类,等同于在XML中这样配置:
package com.lh.json;
import org.springframework.stereotype.Component;
/**
* 页面筛选字段内容
* @author JOMNN
*
*/
@Component
public class FilterDao {
private String fvname;
private int fv;
public String getFvname() {
return fvname;
}
public void setFvname(String fvname) {
this.fvname = fvname;
}
public int getFv() {
return fv;
}
public void setFv(int fv) {
this.fv = fv;
}
@Override
public String toString() {
// TODO Auto-generated method stub
return this.fvname+"-"+this.fv;
}
}
5、@Autowired 成员变量或方法入参处标注,按类型匹配自动注入。
6、@Qualifier 按名称匹配方式注入。
7、@PostConstruct指定初始化方法。(相当于XML配置中的init-method)
8、@PreDestroy指定销毁方法。(相当于XML配置中的destroy-method)
9、@Scope 指定bean是prototype还是singleton。
使用context的规则:component-scan. 扫描这个包中的所有类,并从注解信息中获取bean的基本信息(没加注解的不扫描也不实例化)。
context:component-scan标签下面可以再加子标签过滤
附:过滤规则设置
context:component-scan节点允许有两个子节点
Filter Type | Examples Expression | Description | include-filter为例 |
annotation | org.example.SomeAnnotation | 符合SomeAnnoation的target class | 表示扫描base-package下的类上加了Aspect注解的类,并注册到spring的bean容器 |
assignable | org.example.SomeClass | 指定class或interface的全名 | 指定扫描StuService类作为bean |
aspectj | org.example..*Service+ | AspectJ語法 | |
regex | org\.example\.Default.* | Regelar Expression | |
custom | org.example.MyTypeFilter | Spring3新增自訂Type,實作org.springframework.core.type.TypeFilter |
package com.lh.controller;
import java.io.File;
import java.util.HashMap;
import java.util.UUID;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ibatis.annotations.Param;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import com.lh.def.SqlOpDef;
import com.lh.excel.util.ExcelUtil;
import com.lh.service.RequestAsyncProcessService;
/**
* 数据库添加页面
* @author JOMNN
*
*/
@Controller
@RequestMapping(value="inster")
public class InsterController implements ApplicationEventPublisherAware{
Log log=LogFactory.getLog(InsterController.class);
/**
* 事件分发
*/
@Resource
private ApplicationEventPublisher publisher;
/**
* 请求队列
*/
@Resource
private RequestAsyncProcessService requestAsyncProcessService;
/**
* ICP库
* @return
*/
@RequestMapping(value="icp")
public ModelAndView icpInsterHtml(){
HashMap map = new HashMap();
map.put("title_name", "添加: Icp备案库数据");
map.put("page", "1");
return new ModelAndView("html/inster",map);
}
/**
* 主域分类库
* @return
*/
@RequestMapping(value="hostType")
public ModelAndView hostTypeInsterHtml(){
HashMap map = new HashMap();
map.put("title_name", "添加: 主域分类库数据");
map.put("page", 2);
return new ModelAndView("html/inster",map);
}
/**
* 主域白名单库
* @return
*/
@RequestMapping(value="hostWhite")
public ModelAndView hostWhiteInsterHtml(){
HashMap map = new HashMap();
map.put("title_name", "添加: 主域白名单库数据");
map.put("page", 3);
return new ModelAndView("html/inster",map);
}
/**
* 域名状态库
* @return
*/
@RequestMapping(value="domainState")
public ModelAndView domainStateInsterHtml(){
HashMap map = new HashMap();
map.put("title_name", "添加: 域名状态库数据");
map.put("page", 4);
return new ModelAndView("html/inster",map);
}
/**
* 域名页面优化库
* @return
*/
@RequestMapping(value="domainOptimize")
public ModelAndView domainOptimizeInsterHtml(){
HashMap map = new HashMap();
map.put("title_name", "添加: 域名页面优化库数据");
map.put("page", 5);
return new ModelAndView("html/inster",map);
}
/**
* 主域白名单库
* @return
*/
@RequestMapping(value="domainInfo")
public ModelAndView domainInfoInsterHtml(){
HashMap map = new HashMap();
map.put("title_name", "添加: 域名信息库数据");
map.put("page", 6);
return new ModelAndView("html/inster",map);
}
@RequestMapping(value="single",method=RequestMethod.POST)
public String singleHtml(@Param("page") int page){
if (page == 1) {
return "html/instericp";
}
else if (page == 2) {
return "html/insterhostType";
}
else if (page == 3) {
return "html/insterhostWhite";
}
else if (page == 4) {
return "html/insterdomainState";
}
else if (page == 5) {
return "html/insterdomainOptimize";
}
else if (page == 6) {
return "html/insterdomainInfo";
}
else {
return "index/login";
}
}
@RequestMapping(value="inster.do")
@ResponseBody
public String insert(HttpServletRequest request,@Param("file") MultipartFile file){
//服务器上使用
String rootPath =request.getServletContext().getRealPath(File.separator+"WEB-INF");//target的目录
//使用sessionid + UUID 生成文件号
String fileId = request.getSession().getId() + UUID.randomUUID().toString().replaceAll("-", "")+SqlOpDef.getInster();
return ExcelUtil.analysisExcel(file, rootPath,publisher,requestAsyncProcessService,fileId,SqlOpDef.getInster());
}
@Override
public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
this.publisher = publisher;
}
@PostConstruct
public void init(){
log.info("本应用程序正式拉开帷幕。。。");
}
@PreDestroy
public void destroy(){
log.info("本应用程序正式落幕,吓吓侬。。。");
}
}
spring看到@Controller会如同看到@Component一样,转换成spring容器管理的bean。
spring看到@Autowired(required=false) / @Resource会自动注入(实例化)下面的requestAsyncProcessService。(直接用就行,就不用你来new一个对象啦)。
spring看到@PostConstruct就会在实例化本Bean后接着执行这个方法;
spring看到@PreDestroy就会在销毁之前执行下面的方法;
spring容器的三座大山:XML配置文件(或者注解配置、bean配置等),spring容器,bean类。不管是基于XML还是基于注解,无非就是为了把bean信息注入到spring容器中。
适用场景
整体是下面这样的:
简单点:
读取XML,转化并加工成BeanDefinition,实例化BeanDefinition。
具体点:
ResourceLoader加载XML配置信息后,由BeanDefinitionReader读取配置信息文件,把每个
再具体点:
从实例化的过程中可以看出,BeanDefinition起到中流砥柱的作用。因为BeanDefinition是配置文件
BeanDefinition接口的继承结构如图:
顶级的BeanDefinition其实是个接口,下面的AbstractBeanDefinition实现了这个接口,而最下面的ChildBeanDefinition和RootBeanDefinition分别继承了AbstractBeanDefinition。
半成品的BeanDefinition对象:
1. BeanFactory接口
org.springframework.beans包中的BeanFactory接口,BeanFactory接口提供了IoC容器最基本功能(工厂模式).(如图)
BeanFactory 有三个子类:ListableBeanFactory、HierarchicalBeanFactory 和AutowireCapableBeanFactory。
最终的默认实现类是 DefaultListableBeanFactory : ListableBeanFactory 接口表示这些 Bean 是可列表的,而 HierarchicalBeanFactory 表示的是这些 Bean 是有继承关系的,也就是每个Bean 有可能有父 Bean。AutowireCapableBeanFactory 接口定义 Bean 的自动装配规则。这四个接口共同定义了 Bean 的集合、Bean 之间的关系、以及 Bean 行为.
BeanFactory实现:
1: DefaultListableBeanFactory(是Spring注册及加载Bean的默认实现)
2: XmlBeanDefinationReader(是XML文件的读取和注册也就是:资源文件的读取、解析和注册)
步骤1、BeanFactory(继承的是DefaultListableBeanFactory),提供基本的IoC容器功能,可以从classpath或文件系统等获取资源;
步骤2、利用ClassPathResource
Resource cr = new ClassPathResource("applicationContext.xml");
Resource resource = new FileSystemResource(“beans.xml”);
BeanFactory beanFactory = new XmlBeanFactory(resource);
2、 ApplicationContext接口(扩展了BeanFactory)
而org.springframework.context包下的ApplicationContext接口扩展了BeanFactory,还提供了与Spring AOP集成、国际化处理、事件传播及提供不同层次的context实现 (如针对web应用的WebApplicationContext)。BeanFactory提供了IoC容器最基本功能,而 ApplicationContext 则增加了更多支持企业级功能支持。ApplicationContext完全继承BeanFactory,因而BeanFactory所具有的语义也适用于ApplicationContext。
ApplicationContext实现:
1、 ClassPathXmlApplicationContext(继承了抽象类):,从classpath获取配置文件;
BeanFactory beanFactory = new ClassPathXmlApplicationContext("classpath.xml");
2、FileSystemXmlApplicationContext:从文件系统获取配置文件。
BeanFactory beanFactory = new FileSystemXmlApplicationContext("fileSystemConfig.xml");
3.利用XmlWebApplicationContext读取
XmlWebApplicationContext ctx = new XmlWebApplicationContext();
概述:ApplicationContext是Spring提供的一个高级的IoC容器,它除了能够提供IoC容器的基本功能外,还为用户提供了以下的附加服务。
从ApplicationContext接口的实现,我们看出其特点(比起BeanFactory):
1. 支持信息源,可以实现国际化。(实现MessageSource接口)
2. 访问资源。(实现ResourcePatternResolver接口)
3. 支持应用事件。(实现ApplicationEventPublisher接口)
4. 提供附加服务(更面向框架的使用风格)
在配置文件中声明Bean定义也就是为Bean配置元数据。
方式1. 直接加载ApplicationContext
ApplicationContext ctx = new ClasspathXmlApplicationContext("applicationContext.xml");
方式2. 使用ContextLoaderListener
从ServletContext取得web.xml中初始化的ApplicationContext
在web.xml中配置listener
contextConfigLocation
classpath: ApplicationContext.xml
org.springframework.web.context.ContextLoaderListener
解释:
org.springframework.web.context.ContextLoaderListener
实现了 javax.servlet.ServletContextListener接口。ServletContextListener接口能够监听ServletContext对象的生命周期,因为每个web应用仅有一个ServletContext对象,故实际上该接口监听的是整个web应用。
方式3.使用 AnnotationConfigApplicationContext 注册配置类
1、使用 AnnotationConfigApplicationContext 注册 AppContext 类
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppContext.class);
Course course = ctx.getBean(Course.class);
course.getName();
}
正如以上代码所示,AppContext 配置类的注册方式是将其传递给 AnnotationConfigApplicationContext 构造函数。此外,您还可以使用所述上下文类的 register 方法来注册配置类。以下代码展示了另外一种方法。
2、注册 AppContext 类:另外一种方法
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppContext.class)
}
注册配置类将自动注册 @Bean 注释的方法名称,因而其对应的 bean 就是 Course、Module 和 Assignment。随后您可以使用 getBean 方法来获取相关的 bean,并调用其业务方法。如您所见,编写 Java 的配置类并将其注册到 Spring 上下文非常简单。下一节将讨论如何将基于 Java 的配置与 Web 应用程序配合使用。
资源Resource:
Resource是Sping中用于封装I/O操作的接口。在创建spring容器时,通常要访问XML配置文件(步骤1),除此之外还可以通过访问文件类型、二进制流等方式访问资源,还有当需要网络上的资源时可以通过访问URL,Spring把这些文件统称为Resource,Resource的体系结构如下:
常用的resource资源类型如下:
FileSystemResource:以文件的绝对路径方式进行访问资源,效果类似于Java中的File;
ClassPathResourcee:以类路径的方式访问资源,效果类似于this.getClass().getResource("/").getPath();
ServletContextResource:web应用根目录的方式访问资源,效果类似于request.getServletContext().getRealPath("");
UrlResource:访问网络资源的实现类。例如file: http: ftp:等前缀的资源对象;
ByteArrayResource: 访问字节数组资源的实现类。
资源加载器ResourceLoader:
spring Bean定义解析器:
实体解析器,dtd, schema解析类图:
属性编辑器(太多了只列出了部分),注册器:
环境相关类图: