Maven项目的创建
项目所在路径
    - 项目一
        - 创建Module
        - 添加Webapp(Project Structure)
    - 项目二
Spring简介
分层全栈(各层解决方案)轻量级框架,以IoC和AOP为内核
Spring优势
  • 方便解耦,简化开发
  • AOP编程的支持
  • 声明式事务的支持
  • 方便程序的测试
  • 方便集成各种优秀的框架
  • 降低JavaEE API的使用难度
Spring开发步骤
  • 导入spring坐标

    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.3.20</version>
    </dependency>
    
  • 创建DAO接口

    dao.UserDao

    package com.miaokela.dao;
    
    public interface UserDao {
        public void save();
    }
    
  • 创建Dao接口实现类

    dao.Impl.UserDaoImpl

    package com.miaokela.dao.impl;
    
    import com.miaokela.dao.UserDao;
    
    public class UserDaoImpl implements UserDao {
        public void save(){
            System.out.println("save running...");
        }
    }
    
  • 创建Spring配置文件

    resources.applicationContext

    <?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 id="userDao" class="com.miaokela.dao.impl.UserDaoImpl"></bean>
    </beans>
    
  • 从容器中获取实现类对象

    demo.UserDaoDemo

    package com.miaokela.demo;
    
    import com.miaokela.dao.UserDao;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class UserDaoDemo {
        public static void main(String[] args) {
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
            UserDao userDao = (UserDao) app.getBean("userDao");
            userDao.save();
        }
    }
    
Spring配置文件
  • Bean标签的基本配置

    • 基本属性

      默认情况下调用的是类中的无参构造函数
      id: 容器唯一标识
      class: Bean标签的基本配置全限定名
      
    • 范围配置

      scope 对象作用范围
          - singleton 默认值,单例的
          - prototype 多例的
          - request request域
          - session session域
          - global session 全局session域
      
    • Bean创建时间与销毁时间

      • singleton

        加载配置文件时创建
        容器在,对象在
        销毁容器时,对象销毁

      • prototype

        getBean的时候创建
        对象一直使用中存在
        对象长时间不用,被垃圾回收

  • Bean的生命周期

    • init-method

      指定类中初始化方法名称

    • destroy-method

      指定类中销毁方法名称

    自定义实现方法

    package com.miaokela.dao.impl;
    
    import com.miaokela.dao.UserDao;
    
    public class UserDaoImpl implements UserDao {
        public void save() {
            System.out.println("save running...");
        }
    
        public void init() {
            System.out.println("初始化方法");
        }
    
        public void destroy() {
            System.out.println("销毁方法");
        }
    }
    

    绑定实现方法

    <?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 id="userDao" class="com.miaokela.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy"></bean>
    </beans>
    
  • Bean实例化的三种方式

    • 无参构造

    • 工厂静态方法

      需要配置 factory-method

    • 工厂实例方法

      需要配置 factory-bean、factory-method

依赖注入

通过控制反转,把对象的创建给Spring,降低依赖关系,通过Spring来维护业务层和持久层的依赖关系

  • 业务流程

    UserDao -> UserService -> UserController

  • 依赖注入方法

    • set方法

      service.impl.UserServiceImpl

      package com.miaokela.service.impl;
      
      import com.miaokela.dao.UserDao;
      import com.miaokela.service.UserService;
      
      public class UserServiceImpl implements UserService {
      
          private UserDao userDao;
      
          public void setUserDao(UserDao userDao) {
              this.userDao = userDao;
          }
      
          public void save() {
      //        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
      //        UserDao userDao = (UserDao) app.getBean("userDao");
              userDao.save();
          }
      }
      

      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 id="userDao" class="com.miaokela.dao.impl.UserDaoImpl"></bean>
          <bean id="userService" class="com.miaokela.service.impl.UserServiceImpl">
              <property name="userDao" ref="userDao"></property>
          </bean>
      </beans>
      

      demo.UserController
      可以使用p命名空间注入

      package com.miaokela.demo;
      
      import com.miaokela.service.UserService;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class UserController {
          public static void main(String[] args) {
              // 调用业务层方法
              ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
              UserService userService = (UserService) app.getBean("userService");
              userService.save();
          }
      }
      
    • 构造方法

      service.impl.UserServiceImpl

      package com.miaokela.service.impl;
      
      import com.miaokela.dao.UserDao;
      import com.miaokela.service.UserService;
      
      public class UserServiceImpl implements UserService {
      
          private UserDao userDao;
      
      //    public void setUserDao(UserDao userDao) {
      //        this.userDao = userDao;
      //    }
          public UserServiceImpl(UserDao userDao) {
              this.userDao = userDao;
          }
      
          public void save() {
      //        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
      //        UserDao userDao = (UserDao) app.getBean("userDao");
              userDao.save();
          }
      }
      

      applicationContext

      <?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 id="userDao" class="com.miaokela.dao.impl.UserDaoImpl"></bean>
          <bean id="userService" class="com.miaokela.service.impl.UserServiceImpl">
      <!--        <property name="userDao" ref="userDao"></property>-->
              <constructor-arg name="userDao" ref="userDao"></constructor-arg>
          </bean>
      </beans>
      

      demo.UserController

      package com.miaokela.demo;
      
      import com.miaokela.service.UserService;
      import org.springframework.context.ApplicationContext;
      import org.springframework.context.support.ClassPathXmlApplicationContext;
      
      public class UserController {
          public static void main(String[] args) {
              // 调用业务层方法
              ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
              UserService userService = (UserService) app.getBean("userService");
              userService.save();
          }
      }
      
  • 依赖注入的三种数据类型

    • 普通数据类型

      applicationContext

      <bean id="userService" class="com.miaokela.service.impl.UserServiceImpl">
          <property name="username" value="zhangsan"/></properties>
          <property name="age" value="20"/></properties>
      </bean>
      
    • 引用数据类型

      前面的注入方式

    • 集合数据类型

      数据模型

      public class User {
          private String name;
          private String addr;
      
          // Getter/Setter
      
          // toString()
      }
      

      实现类

      private List<String> strList;
      private Map<String, User> userMap;
      private Properties properties;
      // setter
      

      applicationContext

      <bean id="userDao" class="com.miaokela.service.impl.UserDaoImpl">
          <property name="strList"/>
              <list>
                  <value>1</value>
                  <value>2</value>
                  <value>3</value>
              </list>
          </property>
          <property name="strList"/>
              <map>
                  <entry key="u1" value-ref="user1"></entry>
                  <entry key="u2" value-ref="user2"></entry>
              </map>
          </property>
          <property name="properties"/>
              <props>
                  <prop key="p1">ppp1</entry>
                  <prop key="p2">ppp2</entry>
              </props>
          </property>
      </bean>
      <bean id="user1" class="com.miaokela.domain.User">
          <property name="name" value="zhangsan"/></properties>
          <property name="addr" value="shanghai"/></properties>
      </bean>
      <bean id="user2" class="com.miaokela.domain.User">
          <property name="name" value="lisi"/></properties>
          <property name="addr" value="shanghai"/></properties>
      </bean>
      
分模块开发

引入其他配置文件

<import resource="applicationContext-xxx.xml"/>
Spring相关Api
  • ApplicationContext继承体系
    FileSystemXmlApplicationContext
    ClassPathXmlApplicationContext
    AnnotationConfigApplicationContext
    
  • getBean()方法的使用
    String id的方式
    Class<T> requiredType 字节码类型的方式(UserService.class)
    
Spring配置数据源
  • 连接池的作用

    1.提高程序性能
    2.实现初始化部分连接资源
    3.从数据源中获取连接资源
    4.使用后归回连接资源
    
  • 常见数据源

    DBCP
    C3P0
    BoneCP
    Druid
    
  • 开发步骤

    • 导入坐标

      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>8.0.28</version>
      </dependency>
      <dependency>
          <groupId>c3p0</groupId>
          <artifactId>c3p0</artifactId>
          <version>0.9.1.2</version>
      </dependency>
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.2.4</version>
      </dependency>
      
    • 测试数据源

      test.java.com.miaokela.DataSourceTest
      c3p0

      package com.miaokela;
      
      import com.mchange.v2.c3p0.ComboPooledDataSource;
      import org.testng.annotations.Test;
      
      import java.beans.PropertyVetoException;
      import java.sql.Connection;
      import java.sql.SQLException;
      
      public class DataSourceTest {
          @Test
          public void test1() throws PropertyVetoException, SQLException {
              ComboPooledDataSource dataSource = new ComboPooledDataSource();
              dataSource.setDriverClass("com.mysql.jdbc.Driver");
              dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
              dataSource.setUser("root");
              dataSource.setPassword("123456");
      
              Connection connection = dataSource.getConnection();
              System.out.println(connection);
              connection.close();
          }
      }
      

      druid

      package com.miaokela;
      
      import com.alibaba.druid.pool.DruidDataSource;
      import com.alibaba.druid.pool.DruidPooledConnection;
      import org.testng.annotations.Test;
      
      import java.sql.SQLException;
      
      public class DataSourceTest {
          @Test
          public void test2() throws SQLException {
              DruidDataSource dataSource = new DruidDataSource();
              dataSource.setDriverClassName("com.mysql.jdbc.Driver");
              dataSource.setUrl("jdbc:mysql://localhost:3306/test");
              dataSource.setUsername("root");
              dataSource.setPassword("123456");
      
              DruidPooledConnection connection = dataSource.getConnection();
              System.out.println(connection);
              connection.close();
          }
      }
      
  • 配置数据源文件

    resource.jdbc.properties

    jdbc.driver=com.mysql.jdbc.Driver
    jdbc.url=jdbc:mysql://localhost:3306/test
    jdbc.username=root
    jdbc.password=123456
    

    读取配置文件 连接

    package com.miaokela;
    
    import com.mchange.v2.c3p0.ComboPooledDataSource;
    import org.testng.annotations.Test;
    
    import java.sql.Connection;
    import java.util.ResourceBundle;
    
    public class DataSourceTest {
        @Test
        public void test2() throws Exception {
            // 读取配置文件
            ResourceBundle rb = ResourceBundle.getBundle("jdbc"); // 不需要扩展名
            String driver = rb.getString("jdbc.driver");
            String url = rb.getString("jdbc.url");
            String username = rb.getString("jdbc.username");
            String password = rb.getString("jdbc.password");
    
            // 创建数据源对象 设置连接参数
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setDriverClass(driver);
            dataSource.setJdbcUrl(url);
            dataSource.setUser(username);
            dataSource.setPassword(password);
    
            Connection connection = dataSource.getConnection();
            System.out.println(connection);
            connection.close();
        }
    }
    
  • 通过Spring配置数据源

    将DataSource的创建权由Spring容器去完成
    applicationContext
    先引入context命名空间,再引入properties

    <?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">
    
        <context:property-placeholder location="classpath:jdbc.properties"/>
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driver}"></property>
            <property name="jdbcUrl" value="${jdbc.url}"></property>
            <property name="user" value="${jdbc.username}"></property>
            <property name="password" value="${jdbc.password}"></property>
        </bean>
    </beans>
    

    DataSourceTest

    package com.miaokela;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    import org.testng.annotations.Test;
    
    import javax.sql.DataSource;
    import java.sql.Connection;
    
    public class DataSourceTest {
        @Test
        public void test1() throws Exception {
            // 从容器对象中导入配置
            ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
            DataSource dataSource =  app.getBean(DataSource.class);
            Connection connection = dataSource.getConnection();
            System.out.println(connection);
            connection.close();
        }
    }
    
Spring注解开发
  • 原始注解
@Compoment
@Controller
@Service
@Repository
@Autowired
@Qualifier
@Resource
@value
@Scope
@PostContruct
@PreDestroy
  • 注解替代xml的Bean标签

    • Bean的创建与注入

      dao.impl.UserDaoImpl

      @Compoment("userDao")
      public class UserDaoImpl implements UserDao {
          pubic void save() {
              System.out.println("save running...")
          }
      }
      

      dao.service.impl.UserServiceImpl

      public class UserServiceImpl implements UserService {
          // @Autowired // 注入 单独使用时,从Spring容器中进行匹配
          // @Qualifier("userDao") // Bean id
          @Resource(name="userDao") // 根据名称注入,相当于Autowired+Qualifier
          private UserDao userDao;
          public void setUserDao(UserDao userDao) {
              this.userDao = userDao;
          }
      }  
      
    • 配置组件扫描

      <context:compoment-scan base-backage="com.miaokela"/>
      
  • 衍生注解

    Controller  web层
    Service     service层
    Repository  dao层
    
  • 普通类型的注入

    @Value("${jdbc.driver}")
    private String driver
    
  • 单独设置单例模式

    @Service("userService")
    @Scope("singleton")
    public class UserServiceImpl implements UserService {
        @Value("${jdbc.driver}")
        private String driver;
    }
    
  • Spring新注解

    旧的不能替代xml的注解

    1.非自定义的Bean配置 <bean></bean>
    2.加载properties文件配置 <context:property-placeholder></context:property-placeholder>
    3.组件扫描位置 <context:compoment-scan></context:compoment-scan>
    4.引入其他文件 <import>
    
    • 新注解
      @Configuration // 配置容器时加载配置
      @ComponentScan // Spring初始化容器扫描的包
      @Bean // 存储容器
      @PropertySource // 加载properties文件
      @Import // 导入其他配置
      
  • Spring配置

    解决不能替代xml注解的问题
    config.SpringConfiguration

    @Configuration
    @ComponentScan("com.miaokela") // 3.组件扫描
    @Import({DataSourceConfiguration.class})  // 4.import分模块
    public class SpringConfiguration {
    }
    

    config.DataSourceConfiguration

    @PropertySource("classpath:jdbc.properties") // 2.加载properties文件
    public class SpringConfiguration {
        @Value("${jdbc.driver}")
        private String driver;
    
        @Value("${jdbc.url}")
        private String url;
    
        @Value("${jdbc.username}")
        private String username;
    
        @Value("${jdbc.password}")
        private String password;
    
        @Bean("dataSource") // 1.非自定义的Bean Spring会将当前方法的返回值以指定名称存储到Spring容器中
        public DataSource getDataSource() {
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setDriverClass(driver);
            dataSource.setJdbcUrl(url);
            dataSource.setUser(username);
            dataSource.setPassword(password);
            return dataSource
        }
    }
    

    测试

    public class DataSourceTest {
        @Test
        public void test1() throws Exception {
            // 从容器对象中导入配置
            ApplicationContext app = new AnnotationConfigApplicationContext("SpringConfiguration.class");
            UserService userService = app.getBean(UserService.class);
            userService.save();
        }
    }
    
  • Spring整合Junit

    让SpringJunit负责创建Spring容器,需要将配置文件名称告诉它
    注入需要测试的Bean
    

    步骤

    1.导入Spring继承Junit坐标
    2.使用@Runwith注解替换原来的运行期
    3.使用@ContextConfiguration之顶不过配置文件或配置类
    4.使用@Autowire注入需要测试的对象
    5.创建测试方法进行测试
    
    • 导入坐标

      <dependency>
          <groupId>junit</groupId>
          <artifactId>junit</artifactId>
          <version>3.8.1</version>
          <scope>test</scope>
      </dependency>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-test</artifactId>
          <version>5.3.20</version>
      </dependency>
      
    • 实现整合

      需要测试什么 直接注入

      package com.miaokela;
      
      import com.miaokela.service.UserService;
      import org.junit.Test;
      import org.junit.runner.RunWith;
      import org.springframework.beans.factory.annotation.Autowired;
      import org.springframework.test.context.ContextConfiguration;
      import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
      
      import javax.activation.DataSource;
      
      @RunWith(SpringJUnit4ClassRunner.class)
      //@ContextConfiguration("classpath:applicationContext.xml") // 配置文件方式
      @ContextConfiguration(classes={SpringConfiguration.class}) // 注解方式
      public class SpringJunitTest {
      
          @Autowired
          private UserService userService;
      
          @Autowired
          private DataSource dataSource;
      
          @Test
          public void test1() throws Exception {
              userService.save();
              System.out.println(dataSource.getConnection());
          }
      }
      
posted on 2022-09-19 16:11  _tiny_coder  阅读(21)  评论(0编辑  收藏  举报