目录
1. Web MVC发展史历程
2.Spring概要
3.Spring-依赖注入概要(IOC)
4.属性注入的三种实现方式
5.Spring-IoC XML装配
6.Spring-XML设置Bean的值
7.Spring-IoC 注解(1)
8.Spring-IoC 注解(2)
9.Spring-AOP切面编程(1)
10.Spring-AOP切面编程(2)
未完待续...
Spring-IOC配置
一、概要
1、简介
Spring支持三种方式配置Bean,Spring1.0仅支持基于XML的配置,Spring2.0新增基于注解配置的支持,Spring3.0新增基于Java类配置的支持,Spring4.0则新增给予Groovy动态语言配置的支持。
- Explicit configuration in XML:显示的XML配置
- Explicit configuration in Java:显示的JavaConfig,基于java类配置
- Implicit bean discovery and automatic wiring:隐式的bean扫描,基于java注解配置,自动注入
- Explicit configuration in Groovy DSL:Groovy动态语言配置
在实际开发中前面三种方式都会用到,后面一种相对用的比较少,因为需要学习Groovy语言
2、使用原则
-
隐式的bean扫描,基于注解自动注入(优先使用)
优点:在class文件中,降低维护成本。不需要第三方解析工具,利用java反射机制。编辑期就可以检验正确性,提高开发效率。
缺点:如果需要对注解进行修改,那么要重新编译整个工程。Bean之间的关系不好把控。符合条件的多个Bean注入时会抛出异常 -
Java 接口和类中配置实现配置(没办使用注解可以采用此方式)
同隐式的bean扫描,基于注解 - XML配置(第三方框架,无法修改源代码的情况下)
优点:简单易懂,配置文件修改不需要重新编译,扩展起来相对容易,比较典型的应用场景就是第三方的库中,一般都采用此种配置方式
缺点:配置文件过多的时候难以管理
二、XML配置
1、说明
使用 XML 装配 Bean 需要定义对应的 XML,这里需要引入对应的 XML 模式(XSD)文件,这些文件会定义配置 Spring Bean 的一些元素,当我们在 IDEA 中创建 XML 文件时,会有友好的提示
2、前期准备工作
- 在pom.xml文件中添加
<dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.1.4.RELEASE</version> </dependency>
-
创建xml文件
四、beans配置
1、命名空间(xmlns)
- 说明
这一功能是在spring2之后引进来的,spring的容器启动时回去寻找jar包下面的META-INF,看里面是否有spring.schema或者是spring.handlers,这个handler文件里面就定义了命名空间以及处理这个命名空间的Java类 -
完整结构图
- 说明
- beans(常用)
支持声明Bean和装配Bean,是Spring最核心也是最原始的命名空间 - context(常用)
为配置Spring应用上下文提供配置元素,包括自动检测和自动装配、注入非Spring直接管理的对象 - aop(常用)
为声明切面以及@AspectJ注解切面提供配置元素 - tx(常用)
提供声明式事务配置 - util(常用)
提供各种各样的工具类,包括集合配置为Bean、支持属性占位符元素 - mvc(常用)
启用Spring MVC能力,例如面向注解的控制器、视图控制和拦截器
- beans(常用)
2、XML配置的结构
- 简单的结构
<beans> <bean id="" class=""> <property name="" value=""/> </bean> <alias alias="alias" name="alias" /> <import resource="xxx.xml" /> </beans>
- 说明
-
<bean>
标签
主要用来进行Bean定义 -
<alias>
标签
用于定义Bean别名 - import标签
用于导入其他配置文件的Bean定义,这是为了加载多个配置文件,当然也可以把这些配置文件构造为一个数组(new String[] {“xxx.xml”, xxx.xml})传给ApplicationContext实现进行加载多个配置文件,那一个更适合由用户决定;这两种方式都是通过调用Bean Definition Reader 读取Bean定义,内部实现没有任何区别。<import>
标签可以放在<beans>
下的任何位置,没有顺序关系
-
五、bean的xml装配
1、说明
在spring容器内拼凑bean叫作装配。装配bean的时候,你是在告诉容器,需要哪些bean,以及容器如何使用依赖注入将它们配合在一起
2、Bean配置
- 完整的配置文件
<!--配置bean,配置后该类由spring管理--> <bean class="这个Bean的类" name/id="Bean在容器里面的唯一名称" scope="Bean的作用域范围" autowiring-mode="这个Bean的properties的自动注入方式" lazy-init="是否为懒加载" init-method="容器初始化该Bean后的回调方法" destroy-method = "容器在销毁该Bean后的回调方法" abstract="是否为抽象Bean,主要用来统一XML配置文档里面的很多Bean的属性配置,与Java的Abstract Class无任何关系" parent="父Bean的名称,会继承父Bean的属性,也是只在配置文档中有效,与Java的Class无任何关系" factory-method="工厂方法的名字" factory-bean="工厂Bean的名字" depends-on ="依赖Bean的名字,Spring保证会在初始化这个Bean前先初始化被依赖的Beans,这个属性不会被子Bean继承,子Bean要重新写自己的depends-on" autowire-candidate = "是否为自动注入的候选,一般当其他Bean设置autowiring-mode属性为自动搜寻时可以避免或允许该Bean被列入匹配列表" primary = "是否将该Bean在其他Bean的自动注入候选人中设为首选"> <!-- Constructor-arg方式给属性赋值写法一 --> <constructor-arg type="int" value="1"/> <!-- Constructor-arg方式给属性赋值写法二--> <constructor-arg name="xx" value="2"/> <!-- Constructor-arg方式给属性赋值写法三--> <constructor-arg index="0" value="3"/> <!-- Properties方式给属性赋值写法一--> <property name="xx"> <ref bean="另外一个Bean的名字"/> </property> <!-- Properties方式给属性赋值写法二--> <property name="xx" ref="另外一个Bean的名字"/> <!-- Properties方式给属性赋值写法三--> <property name="integerProperty" value="1"/> </bean>
六、bean配置说明
1、id(常用)
- 说明
- Bean 的名称,在 IOC 容器中必须是唯一的 , 代码中通过BeanFactory获取JavaBean实例时需以此作为索引名称
- 命名必须以字母开头,可以使用字母、数字、连字符、下划线、句号、冒号、 /*
- 若id没有指定,Spring 自动将全限定名#{number}作为 Bean 的名字,com.wener.example.bean.User#0
- id 可以指定多个名字,名字之间可用逗号、分号、或空格分隔
- 示例代码
// java 代码 public class User { private String name; private String password; }
<!-- xml配置 --> <bean id="user,userId" class="com.wener.example.bean.User"/>
2、name(了解)
- 说明
同上,如果给bean增加别名,可以通过name属性指定一个或多个。以废弃,用id代替
3、class(常用)
- 说明
一个类的全限定名(类的完整路径) - 示例代码
<!-- xml配置 --> <bean class="com.wener.example.bean.User"/>
4、scope(常用)
- 说明
用来配置 spring bean 的作用域。在spring2.0之前bean只有2种作用域即:singleton(单例)、non-singleton(也称 prototype), Spring2.0以后,增加了session、request、global session三种专用于Web应用程序上下文的Bean。因此,默认情况下Spring2.0现在有五种类型的Bean。当然,Spring2.0对 Bean的类型的设计进行了重构,并设计出灵活的Bean类型支持,理论上可以有无数多种类型的Bean,用户可以根据自己的需要,增加新的Bean类 型,满足实际应用需求 - 可选值
类型 说明 singleton 默认值,在Spring IoC容器中仅存在一个Bean实例,Bean以单实例的方式存在 prototype 每次从容器中调用Bean时,都返回一个新的实例 request 每次HTTP请求都会创建一个新的Bean,该作用域仅适用于WebApplicationContext环境 session 同一个HTTP session共享一个Bean,不同的HTTP session使用不同的Bean,该作用域仅适用于WebApplicationContext环境 globalSession 同一个全局Session共享一个Bean,一般用于Portlet环境,该作用域仅适用于WebApplicationContext环境 - singleton(单例)
- 说明
当一个bean的 作用域设置为singleton, 那么Spring IOC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。换言之,当把 一个bean定义设置为singleton作用域时,Spring IOC容器只会创建该bean定义的唯一实例。这个单一实例会被存储到单例缓存(singleton cache)中,并且所有针对该bean的后续请求和引用都 将返回被缓存的对象实例,这里要注意的是singleton作用域和GOF设计模式中的单例是完全不同的,单例设计模式表示一个ClassLoader中 只有一个class存在,而这里的singleton则表示一个容器对应一个bean,也就是说当一个bean被标识为singleton时候,spring的IOC容器中只会存在一个该bean,如果不希望在容器启动时提前实例化singleton的Bean,可以使用lazy-init属性进行控制 - 示例代码
<bean id="user" class="com.wener.example.bean.User" scope="singleton"/> // 或者 <bean id="user" class="com.wener.example.bean.User" singleton="true"/>
private static void test() { ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); UserDao dao = context.getBean("userDao", UserDao.class); UserDao dao1 = (UserDao) context.getBean("userDao"); System.out.println(dao); System.out.println(dao1); } // 两次输入的内存地址一致,说明是同一个对象 // com.wener.example.dao.impl.UserDaoImpl@46fa7c39 // com.wener.example.dao.impl.UserDaoImpl@46fa7c39
- 说明
- prototype
- 说明
设置为scope=”prototype”之后,每次调用getBean()都会返回一个新的实例
默认情况下,容器在启动时不会实例化prototype的Bean
Spring容器将prototype的Bean交给调用者后就不再管理它的生命周期 - 示例代码
<bean id="user" class="com.wener.example.bean.User" scope="prototype">
ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml"); User user = context.getBean("user", User.class); User user1 = context.getBean("user",User.class); System.out.println(user); System.out.println(user1); // 两次输入的内存地址不一样 // com.wener.example.bean.User@46fa7c39 // com.wener.example.bean.User@1fb700ee
- 说明
- request
- 说明
request表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP request内有效,配置实例:request、session、global session使用的时候首先要在初始化web的web.xml中做如下配置:如果你使用的是Servlet 2.4及以上的web容器,那么你仅需要在web应用的XML声明文件web.xml中增加下述ContextListener即可: - 示例代码
<web-app> ... <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> ... </web-app>
<bean id="user" class="com.wener.example.bean.User" scope="request" init-method="init" destroy-method="destroy"> </bean>
- 说明
- session
- 说明
session作用域表示该针对每一次HTTP请求都会产生一个新的bean,同时该bean仅在当前HTTP session内有效,和request配置实例的前提一样,配置好web启动文件就可以如下配置 - 示例代码
<web-app> ... <listener> <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class> </listener> ... </web-app> <bean id="user" class="com.wener.example.bean.User" scope="session" init-method="init" destroy-method="destroy"> </bean>
- 说明
5、abstract
- 说明
设定ApplicationContext是否对bean进行预先的初始化。 - 可选值
默认false默认不预先初始化,true预先初始化- 示例代码
<bean id="user" class="com.wener.example.bean.User" abstract="true" scope="session" init-method="init" destroy-method="destroy"> </bean>
- 示例代码
6、parent
- 说明
通过设置标签的parent属性,子将自动继承父的配置信息 - 可选值
父类id的值 - 示例代码
public class Parent { private String name; ... } public class Child extends Parent { private int age; ... }
<bean id="parent" class="com.wener.example.bean.Parent"> <property name="name" value="小明"/> </bean> <bean id="child" parent="parent" class="com.wener.example.bean.Child"> <property name="age" value="10"/> </bean>
8、init-method
- 说明
初始化方法,此方法将在BeanFactory创建JavaBean实例之后,在向应用层返回引用之前执行。一般用于一些资源的初始化工作。 - 示例代码
# java public class User implements Serializable { public void init() { System.out.println("初始化"); } } // xml配置 <bean class="com.werner.di.User" name="user" init-method="init"/>
9、destroy-method
- 说明:
销毁方法,此方法将在BeanFactory销毁的时候执行,一般用于资源释放。 - 示例代码
public class User implements Serializable { public void destroy() { } }
<bean class="com.wener.example.bean.User" id="user" init-method="init" destroy-method="destroy"/>