Spring概述
- 使用Spring开发可以将Bean对象,Dao组件对象,Service组件对象等交给Spring容器来管理,这样使得很多复杂的代码在Spring中开发却变得非常的优雅和简洁,有效的降低代码的耦合度,极大的方便项目的后期维护、升级和扩展。
- Spring是一个IOC(DI)和AOP容器框架。
Spring的优良特性
- **非侵入式:**基于Spring开发的应用中的对象可以不依赖于Spring的API。
- 控制反转:IOC(Inversion of Control),指的是将对象的创建权交给Spring去创建。使用Spring之前,对象的创建都是由我们自己在代码中new创建。而使用Spring之后。对象的创建都是由给了Spring框架。
- 依赖注入:DI(Dependency Injection),是指依赖的对象不需要手动调用setXX方法去设置,而是通过配置赋值。
- 面向切面编程:AOP(Aspect Oriented Programming)该模块将AOP 编程功能集成到了 Spring 框架中。这样,凡是 Spring 框架管理的任何对 象都可以很容易地支持 AOP。该模块为应用程序中基于 Spring 管理的对象提供了事务管理服务。
- 容器:Spring是一个容器,因为它包含并且管理应用对象的生命周期。
- **组件化:**Spring实现了使用简单的组件配置组合成一个复杂的应用。在 Spring 中可以使用XML和Java注解组合这些对象。
- **一站式:**在IOC和AOP的基础上可以整合各种企业应用的开源框架和优秀的第三方类库(实际上Spring 自身也提供了表述层的SpringMVC和持久层的Spring JDBC)。
Spring框架分为四大模块:
Core核心模块。负责管理组件的Bean对象
spring-beans-4.0.0.RELEASE.jar
spring-context-4.0.0.RELEASE.jar
spring-core-4.0.0.RELEASE.jar
spring-expression-4.0.0.RELEASE.jar
面向切面编程
spring-aop-4.0.0.RELEASE.jar
spring-aspects-4.0.0.RELEASE.jar
数据库操作
spring-jdbc-4.0.0.RELEASE.jar
spring-orm-4.0.0.RELEASE.jar
spring-oxm-4.0.0.RELEASE.jar
spring-tx-4.0.0.RELEASE.jar
spring-jms-4.0.0.RELEASE.jar
Web模块
spring-web-4.0.0.RELEASE.jar
spring-webmvc-4.0.0.RELEASE.jar
spring-websocket-4.0.0.RELEASE.jar
spring-webmvc-portlet-4.0.0.RELEASE.jar
BeanFactory的三个子接口:
- HierarchicalBeanFactory:提供父容器的访问功能
- ListableBeanFactory:提供了批量获取Bean的方法
- AutowireCapableBeanFactory:在BeanFactory基础上实现对已存在实例的管理
BeanFactory和ApplicationContext之间的关系
- BeanFactory和ApplicationContext是Spring的两大核心接口,而其中ApplicationContext是BeanFactory的子接口。它们都可以当做Spring的容器,Spring容器是生成Bean实例的工厂,并管理容器中的Bean。在基于Spring的Java EE应用中,所有的组件都被当成Bean处理,包括数据源,Hibernate的SessionFactory、事务管理器 等。
- Spring的核心是容器,而容器并不唯一,框架本身就提供了很多个容器的实现,大概分为两种类型:
一种是不常用的BeanFactory,这是最简单的容器,只能提供基本的DI功能;
一种就是继承了BeanFactory后派生而来的ApplicationContext(应用上下文),它能提供更多企业级的服务,例如解析配置文本信息等等,这也是ApplicationContext实例对象最常见的应用场景。
BeanFactory和ApplicationContext的区别
- BeanFactory:
- 采用延迟加载Bean,直到第一次使用getBean()方法获取Bean实例 时,才会创建Bean。
- ApplicationContext:
- ApplicationContext在自身被实例化时一次完成所有Bean的 创建。大多数时候使用ApplicationContext。
- 区别
- 在服务启动时ApplicationContext就会校验XML文件的正确性 ,不会产生运行时bean装配错误
- BeanFactory在服务启动时,不会校验XML文件的正确性,获 取bean时,如果装配错误马上就会产生异常。
bean的作用域
五种作用域中,request、session和global session三种作用域仅在基于web的应用中使用(不必关心你所采用的是什么web应用框架),只能用在基于web的Spring ApplicationContext环境。
- 当一个bean的作用域为**Singleton**,那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用域。
- 当一个bean的作用域为**Prototype**,表示一个bean定义对应多个对象实例。Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域
- 当一个bean的作用域为**Request**,表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。
- 当一个bean的作用域为**Session**,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅在基于web的Spring ApplicationContext情形下有效
- 当一个bean的作用域为**Global Session**,表示在一个全局的HTTP Session中,一个bean定义对应一个实例。典型情况下,仅在使用portlet context的时候有效。该作用域仅在基于web的Spring ApplicationContext情形下有效。
beans.xml下内容
Spring架构内容:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
</beans>
如何使用beans
1.开发环境:
2.类A:
package test;
public class A {
//测试是否有被beans调用且实例化
public A() {
System.out.println("A 被实例化了");
}
//属性依赖B
private B b;
//调用B的test方法
public void test() {
b.test();
}
public void setB(B b) {
this.b = b;
}
}
3.类B:
package test;
public class B {
//测试是否有被beans调用且实例化
public B() {
System.out.println("B 被实例化了");
}
public void test() {
System.out.println("B test()");
}
}
4.测试 类Test
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {
public static void main(String[] args) {
//1.把spring内容初始化
//注意:接口不能被实例化,这里实例化ApplicationContext的子类
ApplicationContext act=new ClassPathXmlApplicationContext("beans.xml");
//2.获取bean A
A a=(A) act.getBean("a");
//3.尝试调用A的test方法
a.test();
}
}
5.beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="a" class="test.A">
<!--
value="基本类型赋值"
ref="引用类型赋值"
name="b":代表A里的属性b
ref="b":代表下面配置的 id="b"
-->
<property name="b" ref="b"></property>
</bean>
<bean id="b" class="test.B"/>
</beans>
如果beans.xml文件存放于不同位置情况下的决绝方法
OrderDetail的存放在E盘下
package test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class Test {
public static void main(String[] args) {
//1.把文件放在工程底下
//ApplicationContext act=new FileSystemXmlApplicationContext("beans.xml");
//2.把文件放在硬盘目录底下
//ApplicationContext act=new FileSystemXmlApplicationContext("E:\\beans.xml");
//3.如果类路径下,硬盘目录下,工程目录下都有
ApplicationContext act=new FileSystemXmlApplicationContext(new String[]{"classpath:beans.xml","file:E:\\beans.xml","beans.xml"});
}
}
已经采用工厂模式和采用静态工厂模式开发情况下不改代码,配置bean
类E:
public class E {
public E() {
System.out.println("E 被实例化了");
}
}
类K:
public class K {
public K() {
System.out.println("K 被实例化了");
}
}
Factory类:
public class Factory {
//(一)实例方法
public E getEInstance() {
return new E();
}
//(二)静态方法
public static K getKInstance() {
return new K();
}
}
测试 类Test:
public class Test {
public static void main(String[] args) {
ApplicationContext act=new ClassPathXmlApplicationContext("beans.xml");
}
beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--(一)-->
<bean id="factory" class="test.Factory"></bean>
<bean id="E" factory-bean="factory" factory-method="getEInstance"></bean>
<!--(二)-->
<bean id="k" class="test.Factory" factory-method="getKInstance"/>
</beans>
使用bean给属性注入值
Student类:
public class Student {
private int id;
private String name;//姓名
private Locale locale;//语言 国家 en_US
private URL website;//网址
private Date birthday;//日期
//集合
private List<String> aihao;//爱好集合
private Map<String,Integer> score;//成绩集合
private Set<String> lessons;//课程集合
//提供Set方法
public void setId(int id) {
this.id = id;
}
public void setName(String name) {
this.name = name;
}
public void setLocale(Locale locale) {
this.locale = locale;
}
public void setWebsite(URL website) {
this.website = website;
}
public void setBirthday(Date birthday) {
this.birthday = birthday;
}
public void setAihao(List aihao) {
this.aihao = aihao;
}
public void setScore(Map score) {
this.score = score;
}
public void setLessons(Set lessons) {
this.lessons = lessons;
}
//提供toString方法 打印输出信息
@Override
public String toString() {
return "Student [id=" + id + ", name=" + name + ", locale=" + locale
+ ", website=" + website + ", birthday=" + birthday
+ ", aihao=" + aihao + ", score=" + score + ", lessons="
+ lessons + "]";
}
测试 类Test:
public class Test {
public static void main(String[] args) {
ApplicationContext act=new ClassPathXmlApplicationContext("beans.xml");
Student stu=(Student) act.getBean("student");
System.out.println(stu);
}
beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="student" class="test.Student" scope="prototype">
<!-- 注入值 -->
<property name="id" value="100"></property>
<property name="name" value="zhangsan"></property>
<property name="locale" value="en_US"></property>
<property name="website" value="http://www.baidu.com"></property>
<property name="birthday" value="2020/10/01"></property>
<!-- 集合注入值方法 -->
<property name="aihao">
<list>
<value>shangwang</value>
<value>dayouxi</value>
<value>paobu</value>
<value>chifan</value>
</list>
</property>
<property name="score">
<map>
<entry key="yuwen" value="150"/>
<entry key="wuli" value="100"/>
<entry key="shuxue" value="150"/>
</map>
</property>
<property name="lessons">
<set>
<value>huaxue</value>
<value>shengwu</value>
</set>
</property>
</bean>
</beans>
动态Web工程
spring托管做法:
- 配置listener 监听web应用启动的事件
- 获取容器
- 问容器索取UserService的bean
详细如下:
1.生成一个web.xml配置一个listener
2.添加web架包,比原有的java架包中多个多出一个web包
选中所有架包右键---->Bulid Path---->Add to Bulid Path
3.配置侦听器
找到spring-web-4.1.7.RELEASE.jar下的ContextLoaderListener.class文件
复制
4.粘贴到listener-class下
注意:去除**.class**
创建一个beans.xml在 WEB-INF 下
beans.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<!--实例化-->
<bean id="userService" class="service.UserService"></bean>
</beans>
5.获取容器
WebApplicationContext wct=WebApplicationContextUtils.getRequiredWebApplicationContext(getServletContext());
6.问容器索取 XXX 的bean
//例如:
//使用getBean();
UserService userService=(UserService) wct.getBean("userService");
使用构造函数给bean的引用对象注入值方法:
public class P {
public String hello() {
return "hello";
}
}
public class M {
private P p;
public M(P p) {
System.out.println("M 被实例化了");
this.p=p;
}
public void test() {
System.out.println(p.hello());
}
}
public class Test {
public static void main(String[] args) {
ApplicationContext act=new ClassPathXmlApplicationContext("beans.xml");
M m=(M) act.getBean("m");
m.test();
}
}
bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="m" class="test.M">
<constructor-arg index="0" ref="p"></constructor-arg>
</bean>
<bean id="p" class="test.P"></bean>
</beans>
使用property节点给bean的引用对象注入值方法:
public class P {
public String hello() {
return "hello";
}
}
public class M {
private P p;
//注意要有空构造方法和属性的setter方法
public void setP(P p) {
this.p = p;
}
public M(){}
public M(P p)
{
System.out.println("M 被实例化了");
this.p=p;
}
public void test()
{
System.out.println(p.hello());;
}
}
public class Test {
public static void main(String[] args) {
ApplicationContext act=new ClassPathXmlApplicationContext("beans.xml");
M m=(M) act.getBean("m");
m.test();
}
}
bean:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd">
<bean id="m" class="test.M">
<property name="p" ref="p"></property>
</bean>
<bean id="p" class="test.P">
</bean>
</beans>
Spring 半自动装配:
autowire=“byType”
- 从Spring环境中获取目标对象时,目标对象中的属性会根据类型在整个spring环境中查找标签的class属性值。如果有相同的,那么获取这个对象,实现关联。
- 在xml文件中bean里添加属性autowire=“byType”,会自动帮当前bean的属性赋值,根据类型从容器中查找合适的bean来赋值,如果本类的属性依赖的多个类,有多个值的时候会报错,如果属性依赖的类没有装配,则为null。
//例如:
<bean id="m" class="test.M" autowire="byType">
autowire=“byName”
- 从Spring环境中获取目标对象时,目标对象中的属性会根据名称在整个Spring环境中查找标签的id属性值。如果有相同的,那么获取这个对象,实现关联。整个Spring环境:表示所有的spring配置文件中查找,那么id不能有重复的。
- 在bean中添加属性autowire=“byName”,会自动根据名字从容器查找合适的bean来赋值,根据名字找不到,不会报错,值为 null;
//例如:
<bean id="orderService" class="test.OrderService" autowire="byName">
Spring 全自动装配
需要多一个aop包:
//例如:
<context:component-scan base-package="test"></context:component-scan>
在需要容器帮忙实例化的bean“头上戴上帽子”:
@Service //给service层的bean带的
@Controller //给servlet层的bean带的
@Repository //给dao层的bean带的
@Component //给不知道什么层的bean带的
给bean中需要装配值的引用属性"也戴上帽子"
@Resource //表示按照名字装配
@Autowired //表示按照类型装配