spring01

1.  Spring的概述

1.1. 什么是Spring

    Spring分层的、JavaSE/EE一站式(full-stack)轻量级开源框架java

JavaEE分层:JavaEE规范的三层结构体系web

1.表现层(页面数据显示、页面跳转调度),例如jsp/servletspring

2.业务层(业务处理和功能逻辑、事务控制),例如service数据库

3.持久层(数据存取和封装、和数据库打交道),例如dao编程

如图:设计模式

一站式:Spring提供了JavaEE各层的解决方案:数组

表现层:struts1struts2Spring MVC缓存

业务层:IocAOP、事务控制服务器

持久层:JdbcTemplateHibernateTemplateORM框架(对象关系映射)整合架构

 

轻量级Spring的出现取代了EJB的臃肿、低效、繁琐复杂、脱离现实的状况. 并且使用spring编程是非侵入的。

 

1.2.  Spring的体系结构

 Spring框架是一个分层架构,它包含一系列的功能要素并被分为大约20个模块。这些模块分为Core ContainerData Access/IntegrationWebAOPAspect Oriented Programming)、Instrumentation和测试部分

核心容器(Core Container) 包括Core、Beans、Context、EL模块。
1:Core和Beans模块提供了Spring最基础的功能,提供IoC和依赖注入特性。这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的须要,并真正地容许你从程序逻辑中分离出依赖关系和配置。
2:Context模块基于Core和Beans来构建,它提供了用一种框架风格的方式来访问对象,有些像JNDI注册表。Context封装包继承了beans包的功能,还增长了国际化(I18N),事件传播,资源装载,以及透明建立上下文,例如经过servlet容器,以及对大量JavaEE特性的支持,如EJB、JMX。核心接口是ApplicationContext。
3:Expression Language,表达式语言模块,提供了在运行期间查询和操做对象图的强大能力。支持访问和修改属性值,方法调用,支持访问及修改数组、容器和索引器,命名变量,支持算数和逻辑运算,支持从Spring 容器获取Bean,它也支持列表投影、选择和通常的列表聚合等。

数据访问/集成部分(Data Access/Integration)
1:JDBC模块,提供对JDBC的抽象,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。
2:ORM模块,提供了经常使用的"对象/关系"映射APIs的集成层。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封装包,能够混合使用全部Spring提供的特性进行"对象/关系"映射,如简单声明性 事务管理 。
3:OXM模块,提供一个支持Object和XML进行映射的抽象层,其中包括JAXB、Castor、XMLBeans、JiBX和XStream。
4:JMS模块,提供一套"消息生产者、消费者"模板用于更加简单的使用JMS,JMS用于用于在两个应用程序之间,或分布式系统中发送消息,进行异步通讯。
5:Transaction模块,支持程序经过简单声明性 事务管理,只要是Spring管理对象都能获得Spring管理事务的好处,即便是POJO,也能够为他们提供事务。

Web
1:Web模块,提供了基础的web功能。例如多文件上传、集成IoC容器、远程过程访问、以及Web Service支持,并提供一个RestTemplate类来提供方便的Restful services访问
2:Web-Servlet模块,提供了Web应用的Model-View-Controller(MVC)实现。Spring MVC框架提供了基于注解的请求资源注入、更简单的数据绑定、数据验证等及一套很是易用的JSP标签,彻底无缝与Spring其余技术协做。
3:Web-Struts模块, 提供了对Struts集成的支持,这个功能在Spring3.0里面已经不推荐了,建议你迁移应用到使用Struts2.0或Spring的MVC。
4:Web-Portlet模块,提供了在Portlet环境下的MVC实现

AOP
1:AOP模块,提供了符合AOP 联盟规范的面向方面的编程实现,让你能够定义如方法拦截器和切入点,从逻辑上讲,能够减弱代码的功能耦合,清晰的被分离开。并且,利用源码级的元数据功能,还能够将各类行为信息合并到你的代码中 。
2:Aspects模块,提供了对AspectJ的集成。
3:Instrumentation模块, 提供一些类级的工具支持和ClassLoader级的实现,能够在一些特定的应用服务器中使用。

Test
1:Test模块,提供对使用JUnit和TestNG来测试Spring组件的支持,它提供一致的ApplicationContexts并缓存这些上下文,它还能提供一些mock对象,使得你能够独立的测试代码。

 

1.3.  Spring的核心

IoCInverse of Control 控制反转):将对象建立权利交给Spring工厂进行管理。好比说:Book book = new Book();  Book book2 = Spring工厂.getBook();

AOPAspect Oriented Programming 面向切面编程),基于动态代理的功能加强方式。

 

1.4.  Spring的优势

Spring 出现为了解决JavaEE 实际问题 
(1)方便解耦,简化开发
Spring就是一个大工厂,它能够将全部对象建立和依赖关系维护,交给Spring管理
(2)AOP编程的支持
Spring提供面向切面编程,能够方便的实现对程序进行权限拦截、运行监控等功能
(3)声明式事务的支持
只须要经过配置就能够完成对事务的管理,而无需手动编程
(3)方便程序的测试
Spring对Junit4支持,能够经过注解方便的测试Spring程序
(5)方便集成各类优秀框架
Spring不排斥各类优秀的开源框架,其内部提供了对各类优秀框架(如:Struts、Hibernate、MyBatis、Quartz等)的直接支持
(6)下降JavaEE API的使用难度
Spring 对JavaEE开发中很是难用的一些API(JDBC、JavaMail、远程调用等),都提供了封装,使这些API应用难度大大下降

关于框架的特性,咱们也会俗称Spring为开发架构的粘合剂

 

1.5.  IoC控制反转

采用IoCInverse of Control,控制反转)的思想解决代码耦合问题。

简单的说就是引入工厂(第三者),将原来在程序中手动建立管理的依赖的UserDaoImpl对象,交给工厂来建立管理。

IoC底层实现:工厂(设计模式)+反射(机制) + 配置文件(xml)。

 

1.1.  DI依赖注入的实现

DIDependency Injection 依赖注入,在Spring框架负责建立Bean对象时,动态的将依赖对象注入到Bean组件(简单的说,能够将另一个bean对象动态的注入到另一个bean中。)

回顾以前的代码:

步骤一:service对象也交给spring容器管理

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"
       xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd">

<!-- bean: spring工厂建立的一个对象(反射机制)
    id/name:对象的名字,能够用来引用或者获取对象, 通常为类名或接口名称的首字母小写
    class:要建立的对象类型的类字符串,类名全路径
 -->
<bean id="userDAO" class="cn.spring.a_quickstart.UserDAOImpl" />

<bean id ="userService" class="cn.spring.a_quickstart.UserServiceImpl">
    <!-- 注入对象 -->
    <!-- property 根据类中的setter方法进行属性注入 -->
    <!-- name:类中setter方法的后缀小写,好比setXxx 对应的name为xxx -->
    <!-- ref:引用哪个bean(对象),值为bean的id/name -->
    <property name="userDAO" ref="userDAO" />
</bean>
</beans>

步骤二:在程序中定义属性提供setter方法:

UserServiceImpl.java

public class UserServiceImpl implements IUserService{
    
    //定义属性
    private IUserDAO userDAO;

    public void setUserDAO(IUserDAO userDAO) {
        this.userDAO = userDAO;
    }

    public void login() {
         System.out.println("UserServiceImpl-service层方法调用了");
         
         //ioc:依赖注入
         userDAO.findUserByUsernameAndPassword();
        
    }

步骤:Dao

//dao的实现类
public class UserDaoImpl implements IUserDao {
    @Override
    public void findByUsernameAndPassword() {
        System.out.println("UserDaoImpl-dao层被调用了");
    }
}

步骤:测试运行,此时获取对象必须从spring工厂获取(spring容器配置中才有依赖注入,本身建立的对象没有注入依赖关系)

public class SpringTest {
    //测试
    @Test
    public void test(){
        //建立service的示例
        //IUserService userService = new UserServiceImpl();
        //userService.login();
        
        //建立spring工厂,获取spring管理的对象
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        IUserService userService = (IUserService) ac.getBean("userService");
    
        userService.login();
    }
}

小结:

IOC:控制反转,将对象建立管理的权利交给spring容器,获取对象经过spring工厂建立

DI:spring容器中建立管理多个对象,经过 property标签将对象注入到须要依赖的对象中

 

【扩展】

Bean获取的两种方式:

    @Test
    public void getBean(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        
        //获取bean的两种方式
        //1.经过spring容器中bean的id/name获取
        //IUserService userService = (IUserService) ac.getBean("userService");
        
        //2.根据bean的类型或者bean接口的类型获取,通常使用接口类型
        IUserService userService = (IUserService) ac.getBean(IUserService.class);
        userService.login();
    }

经常使用根据名称获取(id/name,即第一种方式,使用spring容器中的标识获取对象

方式二的弊端:若是根据类型获取,配置了多个类型的话,则抛出异常:

applicationContext.xml

<bean id ="userService1" class="cn..spring.a_quickstart.UserServiceImpl">
    <property name="userDAO" ref="userDAO" />
</bean>

<bean id ="userService2" class="cn.spring.a_quickstart.UserServiceImpl">
    <property name="userDAO" ref="userDAO" />
</bean>

 

2.  IoC容器装配Bean_基于XML配置方式

2.1.  实例化Bean的四种方式 (了解)

第一种方式 无参数构造器 (最经常使用)

第一步:建立Bean1.java

//1。默认构造器(spring在建立bean的时候自动调用无参构造器来实例化,至关于new Bean1())
public class Bean1 {
}

第二步:在spring容器applicationContext.xml中配置

<!-- 实例化 bean的四种方式 -->
    <!-- 1.默认构造器实例化对象 -->
    <bean id ="bean1" class="cn.spring.b_xmlnewbean.Bean1" />

第三步:建立测试类获取bean对象

SpringTest.java:

public class SpringTest {
    @Test
    public  void test(){
        //建立spring工厂
        ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
        //1.默认构造器获取bean对象
        Bean1 bean1 = (Bean1) ac.getBean("bean1");
        System.out.println(bean1);
    }
}

【错误演示】:

public class Bean1 {
    //错误演示
    private String name;
    
    public Bean1(String name) {
        this.name = name;
    }
}

 静态工厂方法、 实例工厂方法、FactoryBean方式这三种方式在这里就不演示了,第一种是最经常使用的

 

2.2.  Bean的做用域 

spring建立的bean对象在什么状况下有效。

项目开发中一般会使用:singleton 单例、 prototype多例

Singleton: 在一个spring容器中,对象只有一个实例。(默认值

Prototype: 在一个spring容器中,存在多个实例,每次getBean 返回一个新的实例

 

第一步:建立类SingletonBean.javaPrototypeBean.java

建立类SingletonBean.java

//单例bean
public class SingletonBean {
    public SingletonBean() {
        System.out.println("SingletonBean:初始化了单例");
    }
}

建立类PrototypeBean.java

//多例bean
public class PrototypeBean {
    public PrototypeBean() {
        System.out.println("--PrototypeBean初始化了多例的");
    }
}

第二步:applicationContext配置文件:

   <!-- 
        bean的做用范围
        scope:配置做用范围的,默认值就是singleton单例
     -->
    <!-- 单例 -->
    <bean id="singletonBean" class="cn.spring.c_xmlscope.SingletonBean" scope="singleton"/> 
    <bean id="singletonBean" class="cn.spring.c_xmlscope.SingletonBean"/>
    <!-- 多例 -->
    <bean id="prototypeBean" class="cn.spring.c_xmlscope.PrototypeBean" scope="prototype"/>

第三步:测试代码,建立SpringTest.java

//newbean的方式
public class SpringTest {
    
    @Test
    public void test(){
        //先构建实例化获取spring的容器(工厂、上下文)
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
        //目标1:看看屡次获取bean的时候,是否是同一个
        //目标2:看看bean何时初始化的
        //获取单例的bean:应该是同一个
        //单例:每次从spring容器中获取的对象,是同一个对象
        //单例初始化:是在spring容器初始化的时候,就初始化了
        //即这一步new ClassPathXmlApplicationContext("applicationContext.xml")就初始化单例了
        SingletonBean singletonBean1=(SingletonBean)applicationContext.getBean("singletonBean");
        SingletonBean singletonBean2=(SingletonBean)applicationContext.getBean("singletonBean");
        System.out.println(singletonBean1);
        System.out.println(singletonBean2);
        //获取多例的bean:
        //多例:每次从spring容器中获取的对象,不是同一个对象
        //多例初始化:是在getBean的时候初始化,至关于每次getbean就是在new Bean()
        PrototypeBean prototypeBean1=(PrototypeBean)applicationContext.getBean("prototypeBean");
        PrototypeBean prototypeBean2=(PrototypeBean)applicationContext.getBean("prototypeBean");
        System.out.println(prototypeBean1);
        System.out.println(prototypeBean2);
    }
}

【注意】

单例是默认值,若是须要单例对象,则不须要配置scope

 

3.  IoC容器装配Bean_基于注解配置方式

第二步 编写ServiceDAO 的注册

 xml作法 : <bean id=”customerService” class=”…” />,用<bean>的方式建立对象

注解作法 spring2.5引入 @Component 注解 若是放置到类的上面,至关于在spring容器中定义<bean id=”” class=””>

建立类:CustomerService.java

/**
 * @Component注解放置到类上
 * 至关于spring容器中定义:<bean id="customerService" class="cn.spring.a_ioc.CustomerService">
 * @Component(value="customerService")  //能够自定义bean的id名字
   若是不写value值,默认value值为类名的首字母小写,即customerService
 * 至关于spring容器中定义:<bean id="customer" class="cn.spring.a_ioc.CustomerService">
 */

//注意:只有value一个属性时,能够写做@Component("customerService"),也能够写做@Component
@Component(value="customerService")
public class CustomerService {
    //保存业务方法
    public void save(){
        System.out.println("CustomerService业务层被调用了。。。");
    }
}

第三步: 配置注解开启和注解Bean的扫描。配置的示例以下:配置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">
    
    <!-- 开启spring的注解功能 :让注解有效了,识别注解-->
    <context:annotation-config/>

    <!-- 配置注解bean扫描 
            context:component-scan:专门扫描含有@Component注解的类,自动将其做为bean
            base-package:要扫描包的路径,cn.itcast.spring全部子包下的全部类定义注解都有效
            注意:配置注解ean扫描时,会自动开启注解功能,全部若是配置注解扫描能够不配置开启注解功能
    -->
    <context:component-scan base-package="cn.itcast.spring"/>
</beans>

扩展优化:

1.注解扫描配置

配置注解扫描时,会自动开启注解功能,全部若是配置注解扫描能够不配置开启注解功能

2.衍生注解的问题

实际开发中,使用的是@Component三个衍生注解(“子注解”)

子注解的做用:有分层的意义(分层注解)。

Spring3.0为咱们引入了组件自动扫描机制,它能够在类路径底下寻找标注了@Component、@Service、@Controller、@Repository注解的类,
并把这些类归入进spring容器中管理。
除了@Component外,Spring提供了3个功能基本和@Component等效的注解

功能介绍
@Service用于标注业务层组件(如Service层)
@Controller用于标注控制层组件(如struts中的action层)
@Repository用于标注数据访问组件,(如DAO层组件)。
而@Component泛指组件,当组件很差归类的时候,咱们可使用这个注解进行标注。(好比测试类)
相关文章
相关标签/搜索