spring框架-1
spring 的核心就是IOC(最重要)+AOP
Spring没有太多的新的东西,它只是抽象了大量的JavaEE应用中的常用代码,将它们抽象成一个框架,通过使用Spring可以大幅度地提高开发效率,并可以保证整个应用具有良好的设计。
Spring框架号称JavaEE应用的一站式解决方案,Spring本身提供了一个设计优良的MVC框架:SpringMVC.使用Spring框架则可以直接使用该MVC框架。但Spring却没有提供完整的持久层框架这可以理解成一种“空”,但这种“空”反而是Spring框架的魅力所在。
Spring能与大部分持久层框架无缝整合:Hibernate、JPA、MyBatis、甚至直接使用JDBC,随便我们喜欢,无论哪种持久层框架,Spring都会为我们提供无缝的整合以及极好的简化。从这个意义上看,Spring更像一种中间层容器,Spring向上可以与MVC框架无缝整合,向下可以与各种持久层框架无缝整合,具有强大的生命力。
由于Spring框架的特殊地位,所以轻量级JavaEE应用通常都会使用Spring。实际上,轻量级JavaEE这个概念也是由Spring框架衍生出来的,Spring框架暂时都没有较好的替代框架
spring 简介
Spring为企业应用的开发提供了一个轻量级的解决方案。该解决方案包括:基于依赖注入的核心机制、基于
卫AOP(Aspect Oriented Programming,面向健面的程序设计)的声明式事务管理、与各种持久层技术的整合,以及优秀的Web MVC 框架等。Spring致力于JavaEE应用各层的解决方案,而不是仅仅专注于某一层的方案。可以说:Spring是企业应用开发的“一站式“选择,Spring贯穿表现层、业务层、持久层。然而,Spring并不想取代那些已有的框架,而是以高度的开发性与它们无缝整合。

SSH(Struts2,Spring,Hibernate)
SSM(SpringMVC,Spring,Mybatis)
maven配置
//最基础的
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!--在基础IOC功能上提供扩展服务,还提供许多企业级服务的支持,有邮件服务、 任务调度、远程访问、缓存以及多种视图层框架的支持-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
<!-- Spring IOC的基础实现,包含访问配置文件、创建和管理bean等 -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>5.0.8.RELEASE</version>
</dependency>
</dependencies>
applicationContext.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: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定义和依赖注入 -->
</beans>
使用
在applicationContext.xml中配置bean
通过set方法装配
<bean id="user" class="com.origin.d630.User">
<property name="name" value="hh"></property>
<property name="age" value="12"></property>
</bean>
通过构造方法装配
<bean id="user" class="com.origin.d630.User">
<constructor-arg value="hh"></constructor-arg>
<constructor-arg value="12"></constructor-arg>
</bean>
main方法中创建context加载applicationContext.xml配置文件
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
通过getBean来获取实体类
User user = (User) context.getBean("user");
单例类 – 拓展
public class Person {
private String name = "tom";
private Person() {
}
static private Person person;
static Person getPerson() {
if (person == null) { //加入双重校验锁
synchronized (Person.class) {
if (person == null) {
person = new Person();
}
}
}
return person;
}
}
我们使用spring来配置bean和使用单例类的效果是一样的,在spring中,加载xml配置文件时会自动帮我们加载配置的bean对象,相当于new了一次,这些对象被放在了spring容器中(spring的上下文),当我们使用一个对象时,就从这个容器中取走。
IOC/依赖注入
当某个Java对象需要调用另外一个Java对象的方法时,在传统模式下通常有如下两种做法。
原始做法:调用者主动创建被依赖对象,然后再调用被依赖对象的方法。
简单工厂模式:调用者先找到被依赖对象的工厂,然后主动通过工厂去获取被依赖的对象,最后在调用依赖
对象的方法。
对于第一种方式,由于调用者需要通过形如“new构造器(”的代码创建对象,因此必然导致调用者与被依赖
对象实现类的硬编码耦合,非常不利于项目的升级的维护。
对于简单工厂的方式,大致需要把握三点:1、调用者面向被依赖对象的接口编程;2、将被依赖的对象的创
建交给工厂完成;3、调用者通过工厂来获取被依赖的组件。通过这3点改造,可以保证调用者只需要与被依赖
对象的接口耦合,这就避免了类层次的硬编码耦合。这种方式唯一的缺点是,调用组件需要主动通过工厂去获
取依赖对象,就会带来调用组件与被依赖对象工厂的耦合。
使用Spring框架之后,调用者无须主动获取被依赖对象,调用者只要被动接受Spring容器为调用者的成员变量
赋值即可。由此可见,使用Spring框架之后,调用者获取被依赖对象的方式由原来的主动获取,变成了被动接
受
从Spring容器的角度来看,Spring容器负责将被依赖对象赋值给调用者的成员变量——相当于为调用者注入它
依赖的实例对象
Spring容器 —-Spring (BeanFactory)
Spring 有两个核心接口:BeanFactory 和ApplicationContext,其中ApplicationContext是BeanFactory 的子接口。它们都可以代表 Spring 容器,Spring 容器是生成 Bean 实例的工厂,并管理容器中 Bean。在基于 Spring的Java E应用中,所有的组件都被当成 Bean处理,包括数据源、Hibernate的 SessionFactory、事务管理器等。
应用中的所有组件都处于Spring的管理下,都被Spring以Bean的方式管理,Spring负责创建 Bean实例,并管理其生命周期。Spring里的Bean都是非常广义的概念,任何的Java对象、Java组件都被当成Bean处理,
对于 Spring 而言,一切 Java 对象都是 Bean。
Java程序面向接口编程,无须关注Bean实例的实现类,但Spring容器负责创建Bean实例。因此在Spring配置文件中必须指定Bean实例的实现类。
Spring容器最基本的接口就是BeanFactory。BeanFactory负责配置、创建、管理Bean,它有一个子接口:
ApplicationContext,因此也被称为Spring上下文。Spring容器还负责管理Bean与 Bean之间的依赖关系。 BeanFactory接口包含如下几个基本方法。
(1)boolean containsBean(String name):判断 Spring 容器中是否包含 id 为 name 的 Bean 实例。
(2)
(3)Object getBean(String name):返回容器中 id 为 name 的 Bean 实例。
(4)
(5)Class<?> getType(String name):返回容器中 id 为 name 的 Bean 的实例的类型。
调用者只需要使用getBean()方法即可获得指定 Bean的引l用,无须关心Bean的实例化过程。Bean 实例的创建、初始化以及依赖关系的注入都由Spring容器完成。
BeanFactory 常用的实现类是DefaultListableBeanFactory。
ApplicationContext是Beanfactory的子接口,对于大部分 Java EE应用而言,使用它作为 Spring 容器更方便。其常用实现类是FileSystemXmlApplicationContext、ClassPathXmlApplicationContext和AnnotationConfigApplicationContext。如果在Web应用中使用 Spring 容器.则通常有XMLWebApplicationContext、AnnocationConfigWebApplicationContext 两个实现类。
ApplicationContext
大部分时候,都不会使用BeanFactory实例作为Spring容器,而是使用ApplicationContext实例作为容器,
因此也把 Spring容器称为 Spring上下文。ApplicationContext是BeanFactory接口的子接口,它增强了
BeanFactory 的功能。
ApplicationContext允许以声明式方式操作容器,无须手动创建它。可利用如ContextLoader的支持类,在
Web应用启动时自动创建ApplicationContext。当然也可采用编程方式创建ApplicationContext。
ApplicationContext除了提供BeanFactory所支持的全部功能外,还有如下额外方法:
(1)ApplicationContext默认会预初始化所有的singletionBean.也可通过配置取消预初始化。
(2)ApplicationContext继承MessageSource接口,因此提供国际化支持。
(3)资源访问,比如访问URL和文件。
(4)事件机制。
(5)同时加载多个配置文件。
(6)以声明式方式启动并创建Spring容器。
ApplicationContext包括BeanFactory 的全部功能,因此建议优先使用ApplicationContext。除非对于某些内存非常关键的应用才考虑BeanFactory。当系统创建ApplicationContext容器时,默认会预初始化所有的singletion Bean。也就是说,当ApplicationContext容器初始化完成后,容器会自动初始化所有的singletionBean,包括调用构造器创建该Bean的实例。并根据property元素执行setter方法。这意味着:系统前期创建ApplicationContext时将有较大的系统开销,但一旦ApplicationContext初始化完成,程序后面获取singletionBean实例时将拥有较好的性能。
scope="prototype" 取消单例
事件机制
ApplicationContext的事件机制是观察者设计模式的实现,通过ApplicationEvent类和ApplicationListener 接口,可以实现ApplicationContext 的事件处理。如果容器中有一个ApplicationListener Bean,每当ApplicationContext发布ApplicationEvent时,ApplicationListenerBean将自动被触发。Spring的事件框架有如下两个重要成员。
ApplicationEvent:容器事件,必须有ApplicationContext发布。
ApplicationListener监听器,可由容器中的任何监听器 Bean担任。
实际上,Spring的事件机制与所有的事件机制都基本相似,它们都需要由事件源、事件和事件监听器组成。
只是此处的事件源是ApplicationContext,且事件必须由Javà程序显示触发。下图为Spring容器的事件机制示
意图。

(发布者发布applicationEvent事件到applicationContext,applicationListener监听 applicationContext)
使用
@Getter
@Setter
@ToString
public class MyEvent extends ApplicationEvent {
private String content;
private String target;
public MyEvent(Object source, String content, String target) {
super(source);
this.content = content;
this.target = target;
}
}
public class MsgListener implements ApplicationListener {
@Override
public void onApplicationEvent(ApplicationEvent applicationEvent) {
if (applicationEvent instanceof MyEvent) {
MyEvent myEvent = (MyEvent) applicationEvent;
System.out.println(myEvent);
} else {
System.out.println("其他事件..."+applicationEvent);
}
}
}
<bean class="com.origin.d630.MsgListener"></bean>
MyEvent myEvent = new MyEvent("user1","hhh","user2");
context.publishEvent(myEvent);
系统自带的事件
监听器不仅监听到程序所触发的事件,也监听到容器内置的事件。实际上,如果开发者需要在Spring容器初始化、销毁时回调方法,就可以通过上面的事件监听器来实现。
Spring提供如下几个内置事件。
ContextRefreshedEvent:ApplicationContext容器初始化或刷新触发该事件。此处的初始化是指,所有的Bean被成功加载,后处理的Bean被检测并激活,所有的 singletonBean被预实例化,ApplicationContext容器已就绪可用。
ContextStartedEvent:当使用ConfigurableApplicationContext 接口的 start 方法启动ApplicationContext容器时触发该事件。
ContextClosedEvent:当使用 ConfigurableApplicationContext 接口的 close方法时关闭ApplicationContext容器时触发该事件。
ContextStoppedEvent:当使用ConfigurableApplicationContext接口的 stop 方法使ApplicationContext 停止时触发该事件。
RequestHandlerEvent:Web相关的事件,只能应用于使用DispatcherServlet 的 Web应用中。在使用 Spring作为前端的MVC控制器时,当Spring处理用户请求结束后,系统会自动触发该事件。从 Spring4.0.3 开始, Spring 还新增了SessionConnectedEvent、SessionConnectEvent、SessionDisconnectEvent 这三个事件,它们都用于为Spring新增的WebSocket功能服务。
Bean 获取 Spring 容器
为了让Bean获取它所在的 Spring容器,可以让该Bean实现BeanFactoryAware接口。BeanFactoryAware接口里只有一个方法。
setBeanFactory(BeanFactory factory):该方法有一个参数 factory,该参数指向创建它的BeanFactory。
此方法比较特殊,该方法不需要程序员来处理,直接由Spring调用,Spring调用该方法时会将Spring容器作为参数传入该方法。与该接口类似的还有BeanNameAware、ResourceLoaderAware接口,这些接口里都会提供类似的setter方法,这些方法也由Spring负责调用。
与BeanFactoryAware接口类似的有ApplicationContextAware接口,实现该接口的Bean需要实现setApplication
Context(ApplicationContext ctx):方法———此方法也不是由程序员负责调用,而是由 Spring来调用。当Spring容器调用该方法时,它会把自身作为参数传入该方法。
原理
class XContext{
public X createX(){
X x = new X();
x.setxContext(this);
return x;
}
}
class X{
private XContext xContext;
public void setxContext(XContext xContext) {
this.xContext = xContext;
}
}
使用
public class User implements ApplicationContextAware {
public String name;
public int age;
ApplicationContext applicationContext;
public void f1(){
Object aa = applicationContext.getBean("aa");
System.out.println(aa);
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
public User(String name , int age) {
this.name = name;
this.age = age;
}
}
