Spring1

Spring 学习(1)

  • 分层架构
  • web 层 ---- Spring MVC | struts
  • service 层 ---- Spring
  • dao 层 ---- Mybatis | JDBCTemplate | hibernate —> Spring-date

Spring 核心

  • Spring 核心是控制反转(Ioc)面向切片(Aop)
  • Ioc
  • Aop

Spring 优点

  • 方便解耦,简化开发(高内聚、低耦合)

Spring 就是大工厂(容器),用于生成Bean

  • Aop 编程的支持

  • 声明式事务的支持

  • 方便程序的测试

  • 方便集成各种优秀的框架

  • 降低JavaEE Api 的使用难度

Spring 体系结构

Spring1_第1张图片

  • 核心容器: beans、core、context、expression

Spring开发:

入门案例:Ioc(控制反转)

  • 导入jar 包和依赖

  • jar 包
spring-expression-4.3.18.RELEASE.jar
spring-context-4.3.18.RELEASE.jar
spring-beans-4.3.18.RELEASE.jar
spring-core-4.3.18.RELEASE.jar

  • 依赖
    commons-logging-1.2.jar

目标类

  • 提供UserService 接口和实现类
  • 获取UserService 实现类的实例
  • 使用Spring 创建实例对象(Ioc 控制反转)

  • UserService 接口
package com.spring1_Ioc;

/**
 * @InterfaceName Userservice
 * @Author 秃头的JJ
 * Date 2019/5/21 0021 20:20
 */
public interface Userservice {

    void springTest();

}


  • UserServiceImpl 实现类
package com.spring1_Ioc.impl;

import com.spring1_Ioc.Userservice;

/**
 * @ClassName UserServiceImpl
 * @Author 秃头的JJ
 * Date 2019/5/21 0021 20:21
 * Version 1.0
 */
public class UserServiceImpl implements Userservice {
    @Override
    public void springTest() {
        System.out.println("Spring Hello");
    }
}

配置文件

  • 配置文件位置任意,在开发中一般在classPath(src)下
  • 配置文件名称任意,开发中常用applicationContext.xml
  • 内容:添加schema 约束

  • applicationContext.xml




    
    

    


测试方法

@Test
    public void springTest(){
        /* 从Spring 容器获取 */

        // 加载容器
        String xmlPath = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath);

        // 从Spring 容器内获取实例
        Userservice us = (Userservice) ac.getBean("userServiceId");
        us.springTest();

    }

入门案例:DI(依赖注入) — 使用 子标签

  • is a:是一个 — 继承
  • has a:有一个 — 成员变量(依赖)
  • 依赖:一个对象需要使用另一个对象
  • 注入:提供setter 方法进行另一个对象实例的设置

目标类

  • 创建两个接口和实现类
  • 配置到xml 文件内

  • Dao 接口
package com.spring2_DI;

/**
 * @InterfaceName Dao
 * @Author 秃头的JJ
 * Date 2019/5/21 0021 21:39
 */
public interface Dao {

    void daoTest();

}


  • Dao 实现类
package com.spring2_DI.impl;

import com.spring2_DI.Dao;

/**
 * @ClassName DaoImpl
 * @Author 秃头的JJ
 * Date 2019/5/21 0021 21:39
 * Version 1.0
 */
public class DaoImpl implements Dao {

    public DaoImpl() {
        System.out.println("Dao Test DaoImpl");
    }

    @Override
    public void daoTest() {
        System.out.println("Dao Test");
    }
}


  • UserService_DI 接口
package com.spring2_DI;

/**
 * @InterfaceName UserService_DI
 * @Author 秃头的JJ
 * Date 2019/5/21 0021 21:37
 */
public interface UserService_DI {

    void DiTest();

}


  • UserService_DI 实现类
package com.spring2_DI.impl;

import com.spring2_DI.Dao;
import com.spring2_DI.UserService_DI;

/**
 * @ClassName UserService_DIImpl
 * @Author 秃头的JJ
 * Date 2019/5/21 0021 21:38
 * Version 1.0
 */
public class UserService_DIImpl implements UserService_DI {
    private Dao dao;
    private String str;

    public void setDao(Dao dao) {
        this.dao = dao;
    }

    public void setStr(String str) {
        this.str = str;
    }

    @Override
    public void DiTest() {
        System.out.println(this.str);
    }
}

配置文件

   property: 依赖注入所使用的标签
        name: 所要输入的属性名称 ===== 要与实例化的类内的属性名称保持一致
        ref: 指代需要传入的实例化对象的bean 的id
        value: 注入到属性的具体值
    -->
    
        
        
    

    

测试方法

package com.spring2_DI.test;

import com.spring2_DI.impl.UserService_DIImpl;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @ClassName MainTest
 * @Author 秃头的JJ
 * Date 2019/5/21 0021 20:31
 * Version 1.0
 */
public class MainTest {
    private static ApplicationContext ac;
    @BeforeAll
    public static void init(){

        // 加载容器
        String xmlPath = "applicationContext.xml";
        ac = new ClassPathXmlApplicationContext(xmlPath);
    }

    @Test
    public void springTest(){
        /* 从Spring 容器获取 */
        // 从Spring 容器内获取实例
        UserService_DIImpl us = (UserService_DIImpl) ac.getBean("UserService_DIImpl");
        us.DiTest();

    }

}

核心API

  • BeanFactory

用于生成任意Bean

  • ApplicationContext
  • 采用延时加载,在第一次调用getBean() 时才会初始化Bean

是BeanFactory 的子接口,功能更加强大(国际化处理、事件传递、Bean 自动装配、各种不同应用层的Context 实现)

  • ClassPathXmlApplicationContext 用于记载classPath(src) 下的指定的XML 文件
  • FileSystemXmlApplicationContext 用于记载指定盘符下的指定XML 文件

基于XMl 的装配Bean

Bean 的实例化方式

  • 三种Bean 的实例化方式:默认构造、静态工厂、实例工厂
  • 默认构造
  • 必须提供默认构造
  • 静态工厂
  • 常用于Spring 整合其他框架(工具)
  • 用于生产实例,所有方法必须是static
  • 实例代码

  • applicationContext.xml

    

  • 自定义工厂类
package com.spring3_static_factory;

/**
 * @ClassName User
 * @Author 秃头的JJ
 * Date 2019/5/22 0022 10:14
 * Version 1.0
 */
public class Factory {

    private static final Dao dao = new Dao();

    public static Dao createDao(){
        return dao;
    }

}


  • 工厂实现类
package com.spring3_static_factory;

/**
 * @ClassName Dao
 * @Author 秃头的JJ
 * Date 2019/5/22 0022 10:14
 * Version 1.0
 */
public class Dao {

    public void print(){
        System.out.println("Hello Static Fatory");
    }

}


  • 测试方法
@Test
    public void staticFactoryTest(){

        String xmlPath = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath);
        Dao dao = ac.getBean("staticFactoryTest", Dao.class);
        dao.print();
    }
  • 实例工厂
  • 必须先有工厂实例对象,通过实例对象创建对象。提供的所有方法都是非静态的

  • applicationContext.xml

    
    
    
    

  • Factory 工厂类
package com.spring4_factory;

/**
 * @ClassName Factory
 * @Author 秃头的JJ
 * Date 2019/5/22 0022 10:55
 * Version 1.0
 */
public class Factory {

    private final Dao dao = new Dao();

    public Dao createDao(){
        return dao;
    }

}


  • 待实现类
package com.spring4_factory;

/**
 * @ClassName Dao
 * @Author 秃头的JJ
 * Date 2019/5/22 0022 10:55
 * Version 1.0
 */
public class Dao {

    public void print(){
        System.out.println("Hello Factory");
    }

}


  • 测试方法
 @Test
    public void factoryTest(){

        String xmlPath = "applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath);
        Dao dao = ac.getBean("dao", Dao.class);
        dao.print();

    }

Bean 的种类

普通Bean
  • Spring 会直接创建class 对应类型的实例,并返回
FactoryBean
  • 是特使的Bean ,具有工厂生产对象的能力,但是只能生产特点的对象.
    Bean 必须实现FactoryBean 接口, 该接口提供了getObject() 方法获取特点的Bean
  • 先创建FactoryBean 实例,在调用getObject() 方法,并返回方法的返回值
  • 类比于
FactoryBean fb = new FactoryBean();
return fb.getObject();
注:
  • BeanFactory 和FactoryBean 的区别
  1. BeanFactory : 工厂,生产任意Bean
  2. FactoryBean : 是一个特殊Bean, 生产一个特定的Bean(过去代理对象的实例 AOP是使用)

作用域

  • 作用域:用于确定Spring 所创建的Bean 的实例的个数
类别 说明
singleton*(单例,默认的) 在Spring Ioc 容器内中仅存在一个Bean 实例,Bean 以单例方式存在,默认值
prototype*(多例) 每次从容器中调用Bean 时,都会返回一个新的实例
request 每次HTTP 请求都会创建一个新的Bean ,该作用域仅适用于WebApplicationContext 环境
session 同一个HTTP session 共享一个Bean, 不同Session 使用不同的Bean ,仅适用于WebApplicationContext 环境
globalSession 一般使用在Portlet 应用环境,仅适用于WebApplicationContext 环境
  • 配置信息


  • applicationContext.xml



  • ScopTest 测试类
package com.spring5_scope;

/**
 * @ClassName ScopTest
 * @Author 秃头的JJ
 * Date 2019/5/22 0022 16:03
 * Version 1.0
 */
public class ScopTest {

    public void print(){
        System.out.println(this.hashCode());
    }

}


  • 测试方法
@Test
    public void factoryTest(){

        String xmlPath = "com/spring5_scope/applicationContext.xml";
        ApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath);
        ScopTest st = ac.getBean("scopTest", ScopTest.class);
        ScopTest st1 = ac.getBean("scopTest", ScopTest.class);
        System.out.println(st);
        System.out.println(st1);

    }

生命周期

  • Spring 生命周期(11个步骤)

Spring 生命周期

  1. instantiate Bean 对象实例化
  2. populate properties 封装属性
  3. 如果Bean 实现BeanNameAware 执行setBeanName
  4. 如果Bean 实现BeanfactoryAware 或者 ApplicationContextAware 设置工厂setBeanFactory 或者上下文对象setApplicationContext
  5. 如果存在类实现BeanPostProcessor(后处理Bean), 执行postProcessBeforeInitialization
  6. 如果Bean 实现执行Initialization 执行afterPropertiesSet
  7. 调用 指定初始化方法
  8. 如果存在类实现BeanPostProcessor(处理Bean), 执行执行postProcessAfterInitialization
  9. 执行业务处理
  10. 如果Bean 实现DisposableBean 执行destory(销毁)
  11. 调用 指定销毁的方法
初始化和销毁
  • 在目标方法执行前和执行后,进行初始化和销毁

  • 销毁方法执行条件1、必须调用Close 方法;2、必须时单例

  • applicationContext.xml




  • LifeCycleBean 测试Bean
package com.spring6_lifecycle;

/**
 * @ClassName LifeCycleBean
 * @Author 秃头的JJ
 * Date 2019/5/22 0022 16:45
 * Version 1.0
 */
public class LifeCycleBean {

    private void init(){
        System.out.println("初始化方法");
    }

    public void print(){
        System.out.println("Hello Life Cycle Bean");
    }

    private void destory(){
        System.out.println("销毁");
    }
}


  • 测试方法
@Test
public void lifeCycleTest() throws Exception {

    String xmlPath = "com/spring6_lifecycle/applicationContext.xml";
    ClassPathXmlApplicationContext ac = new ClassPathXmlApplicationContext(xmlPath);
    LifeCycleBean lcb = ac.getBean("lifecycle", LifeCycleBean.class);
    lcb.print();

    /* 使用反射调用 close 方法 */
//   ac.getClass().getMethod("close").invoke(ac);

    ac.close();

}
BeanPostProcessor 后处理Bean
  • Spring 提供的一种机制,需要实现此接口BeanPostProcessor,并将实现类提供给Spring
    容器, Spring 容器自动执行,在初始化方法执行前执行befor(), 在初始化方法执行之后执行
    after()
  • Spring 提供工厂钩子,用于修改实例对象,可以生产代理对象,时AOP 的底层
    Spring1_第2张图片

  • applicationContext.xml

    

    
    

  • BeanPostProcessor 实现类
package com.spring7_BeanPostProcessor.pojo;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;

/**
 * @ClassName BeanPostPrecessorTest
 * @Author 秃头的JJ
 * Date 2019/5/22 0022 19:13
 * Version 1.0
 */
public class BeanPostProcessorTest implements BeanPostProcessor {


    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessBeforeInitialization 执行了");
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("postProcessAfterInitialization 执行了");
        return bean;
    }
}


  • TestBean 测试类
package com.spring7_BeanPostProcessor.pojo;

/**
 * @ClassName TestBean
 * @Author 秃头的JJ
 * Date 2019/5/22 0022 19:13
 * Version 1.0
 */
public class TestBean {

    private void init(){
        System.out.println("初始化方法执行了");
    }

    public void print(){
        System.out.println("BeanPostPrecessorTest Say HelloWorld");
    }

    private void destory(){
        System.out.println("销毁方法执行了");
    }

}


  • 测试方法
 private static ApplicationContext ac;

    @BeforeAll
    public static void init(){
        String xmlPath = "com/spring7_BeanPostProcessor/applicationContext.xml";
        ac = new ClassPathXmlApplicationContext(xmlPath);
    }

    @Test
    public void beanPostProcessorTest(){
        TestBean tb = ac.getBean("testBean", TestBean.class);
        tb.print();
    }

属性的依赖注入

属性依赖注入 — 构造方法(定义了有参构造器需要再定义无参构造器避免错误发生)
  • applicationContext.xml 内Bean 方法配置


    
    
    



    
    
    
    

属性依赖注入 — setter 方法(待实例化类内必须含有setter 方法)
  • applicationContext.xml


    
    
        12138
    
    



    
    
    
    

属性依赖注入 — P命名空间
  • 对setter 方法注入进行简化,替换了
    而是使用
  • 使用前提:需要添加命名空间
  • 在命名空间内加入:xmlns:p="http://www.springframework.org/schema/p"

  • applicationContext.xml



    
    
        
            
                HelloWorld1
                HelloWorld2
                HelloWorld3
                HelloWorld4
                HelloWorld5
                HelloWorld6
            
        
    

    
        
        
        
        
    
属性依赖注入 — SpEL
  • 对 进行同样编程,所有内容都使用value

#{123}、#{‘String’} ----> 数字、字符串
#{beanID} ----> 引用另一个bean
#{beanID.propName} ----> 操作属性
#{beanID.toString()} ----> 执行方法
#{T(静态类).字段或者方法} ----> 静态方法或字段的使用

属性依赖注入 — 集合注入

  • 数组
  • List
  • Set
  • Map — 键值对 使用 子标签
  • Properties (Props)

集合的注入都是使用 的子标签


  • applicationContext.xml
 
        
            
            
                欧阳铁柱
                上官翠花
                孙秃子
                李狗蛋
            
        
        
            
                1
                2
                3
                4
            
        
        
        
            
            
                欧阳铁柱
                上官翠花
                孙秃子
                李狗蛋
            
        
        
        
            
            
                欧阳铁柱
                上官翠花
                孙秃子
                李狗蛋
            
        
        
        
            
            
                map Test
                
                
                
                
                
            
        
        
            
            
                欧阳铁柱
                欧阳铁柱
                欧阳铁柱
                欧阳铁柱
            
        
    

装配Bean 基于annotation (注解)

  • 注解: 实际上是一个Class ,使用 @注解名 来实现
  • 注解的作用就是简化开发,替代XML 配置文件
  • 使用注解的前提

Spring1_第3张图片

IOC 控制反转 ---- 创建Bean
  • @Component(“id”) 取代
  • 注解使用时,要添加命名空间,让Spring 扫描含有注解的Class
  • 在web 开发中,提供了3个 @Component 衍生注解(功能是一样的)
* @Repository --- Dao 层
* @Service --- service 层
* Controller --- 控制层(WEB 层)
DI 依赖注入 ---- 对Bean 内参数进行赋值
  • 可以个私有字段设置值,也可以使用setter 方法进行设置
  • 普通值: @Value(“值”)
  • 引用值:
  • 使用类型注入
  • @Autowired
  • 使用名称注入 (两种注入方式)
@Autowired
@Qualifier("名称")
  • @Resource(name = “名称”)
生命周期
  • 初始化:@PostConstruct
  • 销毁:@PreDestroy
作用域
  • @Socpe(“prototype”) ---- 多例

Spring1_第4张图片

XML 和注解配合使用

  • 一般是将所有Bean 配置在XML 内
  • 将所有依赖通过@Autowired 实现

注:
1、默认情况这样配置无效,需要在xml 内配置
2、 不同时出现

你可能感兴趣的:(Spring)