day52_Spring

今日内容

零、 复习昨日
一、Spring

零、 复习昨日

一、引言

以前

public class HelleServlet extends HttpServlet{
    UserService service = new UsrServiceImpl();
    void doGet(){
        service.findUser();
    }
}

public interface UserService{
    User findUser();
}
public class UserServiceImpl implements UserService {
    User findUser() {
     // ...   
    }
}

以上这样写有缺点:

1 UserServlet类还是需要和UserService和UserServiceImpl耦合

2 扩展性不好,假如有新的实现类UserServiceImpl2,就需要改动代码


现在需要一种技术,降低耦合且还可以根据运行时状态给属性动态赋值,让方法体现多态性. ==> Spring框架

二、Spring

官网: Spring | Home

中文社区: Spring 中文文档社区 | 中文文档 (gitcode.net)

Spring框架是一个开放源代码的J2EE应用程序框架,由Rod Johnson发起,是针对bean的生命周期进行管理轻量级容器(lightweight container)。 Spring解决了开发者在J2EE开发中遇到的许多常见的问题,提供了功能强大IOC、AOP及Web MVC等功能。Spring可以单独应用于构筑应用程序,也可以和Struts、Webwork、Tapestry等众多Web框架组合使用,并且可以与 Swing等桌面应用程序AP组合。因此, Spring不仅仅能应用于J2EE应用程序之中,也可以应用于桌面应用程序以及小应用程序之中。Spring框架主要由七部分组成,分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。

自己总结一下:

  • bean的生命周期的管理: java对象的创建,使用,销毁等
  • 轻量级: 使用简单
  • 容器: spring可以管理对象,创建好对象,放入spring容器,容器就是存放对象的
  • 组成部分: Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。

day52_Spring_第1张图片

内部结构,自己总结:

  • Spring 集成测试
    • 不当做重点
  • Spring的核心容器
    • 重点!!
  • Spring的AOP技术
    • 重点!!
  • Spring的数据访问技术
    • JDBC,ORM等已经使用Mybatis来替代,不学
    • 主要学习Spring管理事务,mybatis官方推荐的
  • Spring的Web开发
    • 重点!!! 但是这其实就是下面要学习的SpringMVC框架

所以,目前我们学习Spring的重点

  • IOC
  • AOP

三、环境搭建-入门演示

3.1 创建项目

目前只是学习Spring的功能,使用java项目即可,等后续都学完了,再整合在一起创建javaweb开发项目.

创建一个普通的maven-java项目

3.2 加入依赖

Spring的组件有很多,例如核心容器,AOP,DAO,JDBC,TX,Web,MVC等等

但是现在只做入门演示,主要为了学习核心容器,所以只需要导入核心容器相关的依赖

day52_Spring_第2张图片
    <dependencies>
        
        <dependency>
            <groupId>org.springframeworkgroupId>
            <artifactId>spring-contextartifactId>
            <version>5.1.6.RELEASEversion>
        dependency>
        
        <dependency>
            <groupId>junitgroupId>
            <artifactId>junitartifactId>
            <version>4.13version>
            <scope>testscope>
        dependency>
    dependencies>

day52_Spring_第3张图片

3.3 Spring配置文件

Spring的功能大部分都要靠配置文件(XML),配置完成.

名字: 无限制,但是一般有spring.xml,spring-context.xml,beans.xml,applicationContext.xml

位置: src/resources/

内容: (主要关注头文件,不要写错,一般CV的)


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

   

beans>

3.4 测试使用

spring的主要功能是IOC,AOP.今天主要演示IOC(创建对象)

3.4.1 创建类

public class MyClass {

    public void test(){
        System.out.println("测试Spring运行环境..." );
    }

}

3.4.2 使用spring容器管理bean

即使用spring来创建对象. 通过编写applicationContext.xml来完成


<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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

   
   
   
   <bean id="myClass" class="com.qf.MyClass"/>

beans>

3.4.3 创建工厂Bean

工厂bean,即创建工厂对象,由工厂加载配置文件,通过配置文件创建容器,从容器中获得对象

    @Test
    public void test() {
        // 配置文件路径
        String path = "applicationContext.xml";

        // 通过配置文件,创建容器
        ApplicationContext context = new ClassPathXmlApplicationContext(path);

        // 从容器中获得对象(通过标签的id)
        // MyClass myClass = (MyClass) context.getBean("myClass");
        // myClass.test();

        MyClass myClass = context.getBean("myClass", MyClass.class);

        myClass.test();
    }

四、IOC+DI

IOC是Spring框架的核心功能之一,IOC(inversion of control)控制反转

控制: 控制创建对象的能力

反转: 原来创建对象是自己做,反转就是将创建对象的能力交给Spring


IOC(控制反转): 将创建对象的能力反转给Spring,由Spring创建对象

DI(dependency injection) 依赖注入: 属性赋值

4.1 IOC

需求: 项目中需要使用UserServiceImpl和UserDaoImpl对象

public class UserServiceImpl implements UserService {

}

现在创建对象交给Spring来做,代码如下

applicationContext.xml


<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
       https://www.springframework.org/schema/beans/spring-beans.xsd">
   
   <bean id="userService" class="com.qf.service.impl.UserServiceImpl">
   bean>
beans>

测试

/**
 * 现在是使用单元测试,将来这些都会放入服务器中,这些步骤了解
 * 需要明白的是:
 *      我们所需要的bean要从spring容器中获取
 */
@Test
public void testIOC() {
   String path = "applicationContext.xml";
   ApplicationContext context = new ClassPathXmlApplicationContext(path);

   // 获得业务层对象
   UserService userService = context.getBean("userService", UserService.class);
   userService.findUserById();
}

4.2 DI

IOC: 是控制反转,是spring创建对象

DI : 依赖注入,即属性赋值

4.2.0 注入演示

需求: 给UserServiceImpl注入UserDaoImpl属性

UserServiceImpl.java

public class UserServiceImpl implements UserService {

    // 属性
    private UserDao userDao;
    // 需要给属性提供set方法
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    @Override
    public void findUserById() {
        userDao.findUserById();
    }
}

application.xml


<bean id="userService" class="com.qf.service.impl.UserServiceImpl">
    
    
    <property name="userDao" ref="userDao"/>
bean>


<bean id="userDao" class="com.qf.dao.impl.UserDaoImpl"/>

DI(依赖注入|属性赋值)方式有很多

  • set方法注入【重点】
  • 构造方法注入【了解】
  • 自动注入【理解-后续注解就是这个思路】

4.2.1 set方法注入

使用set方法注入不同的类型(int,String,Date,数组,List,Set,Map,对象)

package com.qf;

import java.util.*;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 测试Set方法注入不同类型的测试类
 */
public class TestModel {

    private int id;
    private double money;
    private Integer age;
    private String name;
    private Date birthday;
    private String[] skill;
    private List<String> className;
    private Set<String> phones;
    private Map<String,String> np; // 籍贯

    // set get方法
}


<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
       https://www.springframework.org/schema/beans/spring-beans.xsd">
   
   <bean id="testModel" class="com.qf.TestModel">
      
      
      
      <property name="id" value="1"/>
      <property name="money" value="9999.9"/>
      <property name="age" value="18"/> 
      <property name="name" value="理想"/> 
      <property name="birthday" value="2000/01/01"/> 

      <property name="skill">
         <array> 
            <value>Javavalue>
            <value>H5value>
            <value>Linuxvalue>
         array>
      property>

      <property name="className">
         <list>
            <value>JavaEE2217value>
            <value>JavaEE2217value>
            <value>JavaEE2215value>
            <value>JavaEE2212value>
         list>
      property>

      <property name="phones">
         <set> 
            <value>110value>
            <value>110value>
            <value>120value>
            <value>119value>
         set>
      property>

      <property name="np">
         <map> 
            <entry key="Henan" value="河南"/>
            <entry key="Beijing" value="北京"/>
            <entry key="Hangzhou" value="杭州"/>
         map>
      property>
   bean>

beans>

测试

/**
     * 通过set方法注入
     */
@Test
public void testDIBySet() {
    String path = "applicationContext.xml";
    ApplicationContext context = new ClassPathXmlApplicationContext(path);

    TestModel testModel = context.getBean("testModel", TestModel.class);
    System.out.println(testModel );

}

set方法依赖注入总结

  • 属性要有set方法
  • 注入时bean标签内写property标签
  • property标签name写属性名
  • property标签中,给基本类型赋值用value,给引用类型赋值用ref

4.2.2 构造方法注入【了解】

package com.qf.di;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc 测试使用构造方法注入
 */
public class TestModel2 {

    private int age;
    private String name;

    public TestModel2(){}


    public TestModel2(int age){
        this.age = age;
    }

    public TestModel2(String name){
        this.name = name;
    }


    public TestModel2(int age, String name) {
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString() {
        return "TestModel2{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
}
   <bean id="testModel2" class="com.qf.di.TestModel2">
      
      
      
      <constructor-arg name="age" value="28"/>
      <constructor-arg name="name" value="亚杰"/>
   bean>

4.2.3 自动注入【重在理解】

自动注入之前,使用ref给引用类型手动赋值


<bean id="userService" class="com.qf.service.impl.UserServiceImpl">
    
    
    <property name="userDao" ref="userDao"/>
bean>


<bean id="userDao" class="com.qf.dao.impl.UserDaoImpl"/>

上面是使用ref,自己手动关联引用了另外一个类的对象,来给userDao赋值

spring其实支持自动注入,不需要手动写ref关联,也可以注入属性值

演示:

​ HouseService注入HouseDao


<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
       https://www.springframework.org/schema/beans/spring-beans.xsd">
   

   
   <bean id="houseService" class="com.qf.service.impl.HouseServiceImpl" autowire="byName"/>


   <bean id="houseDao" class="com.qf.dao.impl.HouseDaoImpl"/>
   <bean id="houseDao2" class="com.qf.dao.impl.HouseDaoImpl2"/>

beans>

五、Bean的细节

IOC是可以控制创建对象时是: 单列还是多例

单例: 单实例,即单对象,也就是说这个类有且仅有一个对象

多例: 多实例,即多个对象,也就是说这个类可以有多个对象

<bean id="..." class="..." scope="singleton|prototype">


<bean id="myClass" class="com.qf.model.MyClass" scope="prototype">
<property name="age" value="18"/>
<property name="name" value="京超啊"/>
bean>
@Test
public void testIOC(){
    String path = "applicationContext.xml";
    // 通过配置文件,创建出容器
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);

    // 从容器获得对象
    MyClass myClass1 = context.getBean("myClass", MyClass.class);
    System.out.println(myClass1.hashCode());
    // 如果是单例,每次都是同一个地址
    MyClass myClass2 = context.getBean("myClass", MyClass.class);
    System.out.println(myClass2.hashCode());
    // 如果是多例,每次地址都不一样
    MyClass myClass3 = context.getBean("myClass", MyClass.class);
    System.out.println(myClass3.hashCode());
}

六、注解开发IOC【重点】

以前就可以还使用@WebServlet和@WebFilter注解,省去web.xml中写的配置

以后工作实际开发中,都会使用注解开发,效率很高!

IOC今天也要变成注解开发,用来省去在applicationContext.xml中的配置

IOC相关注解

注解 解释
@Controller 创建对象,用在控制层
@Service 创建对象,用在业务层
@Repository 创建对象,用在数据访问层
@Component 创建对象,其他地方用
@Scope 控制对象的单例|多例

以上注解可以取代配置文件中的标签

DI相关注解

注解 解释
@Value 给基本类型注入
@Autowired 给引用类型自动注入(默认按照类型注入)byType
@Resource 给引用类型自动注入(默认按照名字注入)byName
@Qualifier 和@Autowired联用,可以实现按名字注入

以上注解可以取代配置文件中的标签

6.1 对象&属性注入

6.1.1 UserService&UserServiceImpl

public interface UserService {
    void findUserById();
}
@Service // 相对于是标签,默认id是当前类名首字母小写
public class UserServiceImpl implements UserService {

    @Autowired  // 相对于是autowire=byType属性
    private UserDao userDao;

    public void findUserById() {
        System.out.println("UserServiceImpl--->业务层执行" );
        userDao.findUserById();
    }
}

6.1.2 UserDao&UserDaoImpl

public interface UserDao {
    void findUserById();
}

@Repository // 相对于写bean标签,spring就会创建对象
public class UserDaoImpl implements UserDao {
    public void findUserById() {
        System.out.println("UserDaoImpl --> 查询数据库");
    }
}

6.1.3 配置文件开启注解扫描


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

    
    <context:component-scan base-package="com.qf"/>

beans>

6.1.4 测试

@Test
public void testIOCandDIByAnno(){
    String path = "applicationContextByAnno.xml";
    // 通过配置文件,创建出容器
    ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext(path);

    // 使用注解,默认id即对象名,是类名首字母小写
    UserService userService = context.getBean("userServiceImpl", UserService.class);
    userService.findUserById();
}

6.2 注解使用细节

  1. IOC创建对象的注解,四个功能一样,都可以创建对象,只不过建议不同的位置使用不同的注解,见名知意

  2. 加上创建对象的注解后,默认对象名是类名首字母小写,即需要通过类名首字母小写从容器中获得对象

  3. 其实可以在注解中设置参数,给对象取名.例如@Service(“aaa”),以后就用aaa从容器中取值

  4. 自动注入时@Autowired ,默认按照类型注入

  5. 但是如果容器中有两个该类型的bean,自动注入就会失败,此时可以按名字注入

    @Resource(name="userDaoImpl2")
    
  6. 如果不使用@Resource按名字注入,也可以使用@Qualifier("userDaoImpl2")配合@Autowired一起实现,按照名字注入

  7. 可以给类加@Scope(“prototype|singleton”) 来控制单例多例

6.3 基本类型注入【了解】

package com.qf.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
@Component
public class User {

    @Value("20")
    private int age;
    @Value("靖凯")
    private String name;
    @Value("2000/01/01")
    private Date birthday;

    // set get
}

作业

今天重点重复练: 
	依赖要记住
	配置文件
	set方法注入
	自动注入
需要理解: 面试常问IOC,DI

mybatis完成house表的crud,完成合同和房屋及租户的多表联查

SQL题: 牛客网

sql题完成

----------------------------
java基础- 集合
html,js(jq),css
	写登录页面
	写一个表单校验

有时间预习: AOP概念,动态代理概念 (菜鸟教程)

(“prototype|singleton”) 来控制单例多例

6.3 基本类型注入【了解】

package com.qf.model;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.Date;

/**
 * --- 天道酬勤 ---
 *
 * @author QiuShiju
 * @desc
 */
@Component
public class User {

    @Value("20")
    private int age;
    @Value("靖凯")
    private String name;
    @Value("2000/01/01")
    private Date birthday;

    // set get
}

作业

今天重点重复练: 
	依赖要记住
	配置文件
	set方法注入
	自动注入
需要理解: 面试常问IOC,DI

mybatis完成house表的crud,完成合同和房屋及租户的多表联查

SQL题: 牛客网

sql题完成

----------------------------
java基础- 集合
html,js(jq),css
	写登录页面
	写一个表单校验

有时间预习: AOP概念,动态代理概念 (菜鸟教程)

你可能感兴趣的:(#,Java2307,spring,java,struts)