[Java]Spring-Day 2

[Java]Spring-Day2

学习使用工具

黑马2023新版Java视频教程 https://www.bilibili.com/video/BV1Fv4y1q7ZH?p=8&vd_source=03da0cdb826d78c565cd22a83928f4c2

Java程序员进阶之路 https://tobebetterjavaer.com/overview/java-can-do-what.html

黑马程序员SSM框架教程 https://www.bilibili.com/video/BV1Fi4y1S7ix?p=2&vd_source=03da0cdb826d78c565cd22a83928f4c2

一、数据源对象管理流程(第三方资源配置管理)

  1. 将相关工具先加入pom.xml

  2. 在bean配置文件(applicationContext.xml)中引入bean。由于是第三方库,要先查看源代码中有没有提供构造方法或setter方法,以决定用什么方式进行bean的参数注入。

二、加载properties文件

一些数据并不适合直接写在配置文件中(例如用户名和密码),需要写在properties文件中进行导入。

  1. 在applicationContext.xml中先引入外部properties文件

    1. 开启context命名空间

      <?xml version="1. 0" encoding="UTF-8"?>
      <beans xm1ns="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">
      </beans>
      
      
    2. 使用context空间加载properties文件,location可以加载多个配置文件,以逗号分割,或以classpath:*.properties加载当前类下所有配置文件。classpath*:*.properties可以加载所有jar包下的配置文件。

      <context:properties-placeholder location="jdbc.properties"></context>
      
    3. 将对应的value处改成属性占位符${},读取properties文件中的属性

三、容器补充

  1. 创建容器

    类路径下的XML配置文件:

    ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
    

    文件系统下的XML配置文件,双引号内要使用决定路径。

    ApplicationContext ctx = new FileSystemXmlApplicationContext("applicationContext.xml");
    
  2. 获取bean

    按名称获取

    BookDao bookDao = (BookDao) ctx.getBean("bookDao");
    

    按名称获取,并解决强制类型转换问题

    BookDao bookDao = ctx.getBean("bookDao",BookDao.class);
    

    按类型获取,必须要确保IOC容器中该类型对应的bean对象只能有一个。

    BookDao bookDao = ctx.getBean(BookDao.class);
    

四、IOC/DI注解开发

要想真正简化开发,就需要用到Spring的注解开发,Spring对注解支持的版本历程:

  • 2.0版开始支持注解
  • 2.5版注解功能趋于完善
  • 3.0版支持纯注解开发

注解开发定义bean用的是2.5版提供的注解,纯注解开发用的是3.0版提供的注解。

  1. 注解开发定义Bean

    • 删除原XML配置

      将配置文件中的<bean>标签删除掉

    <bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"/>
    
    • Dao上添加注解

      在BookDaoImpl类上添加@Component注解

      @Component("bookDao")
      public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ..." );
        }
      }
      

      注意:@Component注解不可以添加在接口上,因为接口是无法创建对象的。@Component注解如果不起名称,会有一个默认值就是当前类名首字母小写,所以也可以按照名称获取。

      对于@Component注解,还衍生出了其他三个注解@Controller@Service@Repository。这三个注解和@Component注解的作用是一样的,方便我们后期在编写类的时候能很好的区分出这个类是属于表现层业务层还是数据层的类。

    • 步骤3:配置Spring的注解包扫描

      为了让Spring框架能够扫描到写在类上的注解,需要在配置文件上进行包扫描

      <?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">
          <context:component-scan base-package="com.itheima"/>
      </beans>
      

      说明:

      component-scan

      • component:组件,Spring将管理的bean视作自己的一个组件
      • scan:扫描

      base-package指定Spring框架扫描的包路径,它会扫描指定包及其子包中的所有类上的注解。

      • 包路径越多[如:com.itheima.dao.impl],扫描的范围越小速度越快
      • 包路径越少[如:com.itheima],扫描的范围越大速度越慢
      • 一般扫描到项目的组织名称即Maven的groupId下[如:com.itheima]即可。
  2. 纯注解开发

    上面已经可以使用注解来配置bean,但是依然有用到配置文件,在配置文件中对包进行了扫描,Spring在3.0版已经支持纯注解开发。

    实现思路为:将配置文件applicationContext.xml删除掉,使用类来替换。

    • 创建配置类

      创建一个配置类SpringConfig

    • 标识该类为配置类:在配置类上添加@Configuration注解,将其标识为一个配置类,替换applicationContext.xml

    • 用注解替换包扫描配置:在配置类上添加包扫描注解@ComponentScan替换<context:component-scan base-package=""/>

      @Configuration
      @ComponentScan("com.itheima")
      public class SpringConfig {
      }
      

      @ComponentScan注解用于设定扫描路径,此注解只能添加一次,多个数据使用数组格式。

      @ComponentScan({com.itheima.service","com.itheima.dao"})
      
    • 创建运行类并执行,这里要将接口替换为纯注解开发使用的接口

      ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class);
      
  3. 注解开发bean作用范围

    默认情况下bean是单例,要想将BookDaoImpl变成非单例,只需要在其类上添加@scope注解。

    @Repository
    //@Scope设置bean的作用范围
    @Scope("prototype")
    public class BookDaoImpl implements BookDao {
    
        public void save() {
            System.out.println("book dao save ...");
        }
    }
    
  4. 注解开发bean的生命周期

    @Repository
    public class BookDaoImpl implements BookDao {
        public void save() {
            System.out.println("book dao save ...");
        }
        @PostConstruct //在构造方法之后执行,替换 init-method
        public void init() {
            System.out.println("init ...");
        }
        @PreDestroy //在销毁方法之前执行,替换 destroy-method
        public void destroy() {
            System.out.println("destroy ...");
        }
    }
    

    在BookDaoImpl中添加两个方法,initdestroy,方法名可以任意,@PostConstruct@PreDestroy`注解分别标识初始化方法和销毁方法。@PostConstruct和@PreDestroy注解如果找不到,需要导入下面的jar包:

    <dependency>
      <groupId>javax.annotation</groupId>
      <artifactId>javax.annotation-api</artifactId>
      <version>1.3.2</version>
    </dependency>
    
  5. 注解开发依赖注入

    Spring为了使用注解简化开发,并没有提供构造函数注入setter注入对应的注解,只提供了自动装配的注解实现。

    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        private BookDao bookDao;
        
    //	  public void setBookDao(BookDao bookDao) {
    //        this.bookDao = bookDao;
    //    }
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    

    @Autowired可以写在属性上,也可也写在setter方法上,最简单的处理方式是写在属性上并将setter方法删除掉。@Autowired是按照类型注入,那么对应BookDao接口如果有多个实现类,就会报错。可以通过给实现类起不同的名称来使自动装配成功。

  6. 注解开发按照名称注入

    当根据类型在容器中找到多个bean,注入参数的属性名又和容器中bean的名称不一致,就需要使用到@Qualifier来指定注入哪个名称的bean对象。

    @Service
    public class BookServiceImpl implements BookService {
        @Autowired
        @Qualifier("bookDao1")
        private BookDao bookDao;
        
        public void save() {
            System.out.println("book service save ...");
            bookDao.save();
        }
    }
    

    @Qualifier注解后的值就是需要注入的bean的名称。@Qualifier不能独立使用,必须和@Autowired一起使用。

  7. 简单数据类型注入

    @Repository("bookDao")
    public class BookDaoImpl implements BookDao {
        @Value("itheima")
        private String name;
        public void save() {
            System.out.println("book dao save ..." + name);
        }
    }
    

    使用@Value注解,将值写入注解的参数中就行了。注意数据格式要匹配,如将"abc"注入给int值,这样程序就会报错。

    实际上跟直接赋值是一个效果,还没有直接赋值简单。

  8. 注解读取properties配置文件

    已有的jdbc.properties配置文件,内容为name=itheima888

    • 使用注解加载properties配置文件,在配置类上添加@PropertySource注解

      @Configuration
      @ComponentScan("com.itheima")
      @PropertySource("jdbc.properties")
      public class SpringConfig {
      }
      
      
    • 使用@Value读取配置文件内容

      @Repository("bookDao")
      public class BookDaoImpl implements BookDao {
          @Value("${name}")
          private String name;
          public void save() {
              System.out.println("book dao save ..." + name);
          }
      }
      

    注意:

    • 如果读取的properties配置文件有多个,可以使用@PropertySource的属性来指定多个

      @PropertySource({"jdbc.properties","xxx.properties"})
      
    • @PropertySource注解属性中不支持使用通配符*,运行会报错

      @PropertySource({"*.properties"})
      
    • @PropertySource注解属性中可以把classpath:加上,代表从当前项目的根路径找文

      @PropertySource({"classpath:jdbc.properties"})
      

五、IOC/DI注解开发管理第三方bean

前面定义bean的时候都是在自己开发的类上面写个注解就完成了,但如果是第三方的类,这些类都是在jar包中,我们没有办法在类上面添加注解。这种方式不能在原始代码上面书写注解,一样能定义bean,这就用到了一个全新的注解@Bean。

  • 导入对应jar包

    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.16</version>
    </dependency>
    
  • 在配置类中添加一个方法,该方法的返回值就是要创建的Bean对象类型

    @Configuration
    public class SpringConfig {
        public DataSource dataSource(){
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
            ds.setUsername("root");
            ds.setPassword("root");
            return ds;
        }
    }
    
  • 在方法上添加@Bean注解,注解的作用是将方法的返回值制作为Spring管理的一个bean对象

    @Configuration
    public class SpringConfig {
    	@Bean
        public DataSource dataSource(){
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
            ds.setUsername("root");
            ds.setPassword("root");
            return ds;
        }
    }
    
  • 从IOC容器中获取对象即可

如果把所有的第三方bean都配置到Spring的配置类SpringConfig中,虽然可以,但是不利于代码阅读和分类管理。对于数据源的bean,我们可以新建一个JdbcConfig配置类,并把数据源配置到该类下。

令这个配置类能被Spring配置类加载到,并在IOC容器中创建DataSource对象的方法:

  1. 使用包扫描引入。在Spring的配置类上添加包扫描,在JdbcConfig上添加配置注解。

    @Configuration
    @ComponentScan("com.itheima.config")
    public class SpringConfig {
    	
    }
    
    @Configuration
    public class JdbcConfig {
    	@Bean
        public DataSource dataSource(){
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
            ds.setUsername("root");
            ds.setPassword("root");
            return ds;
        }
    }
    
  2. 使用@Import引入。不需要为JdbcConfig添加配置注解,只需在Spring配置类中引入:

    @Configuration
    //@ComponentScan("com.itheima.config")
    @Import({JdbcConfig.class})
    public class SpringConfig {
    	
    }
    
    • 扫描注解可以移除
    • @Import参数需要的是一个数组,可以引入多个配置类。
    • @Import注解在配置类中只能写一次。

六、IOC/DI注解开发实现为第三方bean注入资源

  1. 简单数据类型

    public class JdbcConfig {
    	@Bean
        public DataSource dataSource(){
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
            ds.setUsername("root");
            ds.setPassword("root");
            return ds;
        }
    }
    
    • 类中提供四个属性

      public class JdbcConfig {
          private String driver;
          private String url;
          private String userName;
          private String password;
      	@Bean
          public DataSource dataSource(){
              DruidDataSource ds = new DruidDataSource();
              ds.setDriverClassName("com.mysql.jdbc.Driver");
              ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
              ds.setUsername("root");
              ds.setPassword("root");
              return ds;
          }
      }
      
    • 使用@Value注解引入值

      public class JdbcConfig {
          @Value("com.mysql.jdbc.Driver")
          private String driver;
          @Value("jdbc:mysql://localhost:3306/spring_db")
          private String url;
          @Value("root")
          private String userName;
          @Value("password")
          private String password;
      	@Bean
          public DataSource dataSource(){
              DruidDataSource ds = new DruidDataSource();
              ds.setDriverClassName(driver);
              ds.setUrl(url);
              ds.setUsername(userName);
              ds.setPassword(password);
              return ds;
          }
      }
      

    代码中关于数据库的四要素不应该写死在代码中,应该是从properties配置文件中读取。具体方法为:

    1. resources目录下添加jdbc.properties
    2. 配置文件中提供四个键值对分别是数据库的四要素
    3. 使用@PropertySource加载jdbc.properties配置文件
    4. 修改@Value注解属性的值,将其修改为${key},key就是键值对中的键的值
  2. 引用数据类型

    假设在构建DataSource对象的时候,需要用到BookDao对象,该如何把BookDao对象注入进方法内让其使用呢?

    public class JdbcConfig {
    	@Bean
        public DataSource dataSource(){
            DruidDataSource ds = new DruidDataSource();
            ds.setDriverClassName("com.mysql.jdbc.Driver");
            ds.setUrl("jdbc:mysql://localhost:3306/spring_db");
            ds.setUsername("root");
            ds.setPassword("root");
            return ds;
        }
    }
    
    • 在SpringConfig中扫描BookDao

      扫描的目的是让Spring能管理到BookDao,也就是说要让IOC容器中有一个bookDao对象

      @Configuration
      @ComponentScan("com.itheima.dao")
      @Import({JdbcConfig.class})
      public class SpringConfig {
      }
      
    • 在JdbcConfig类的方法上添加参数,引用类型注入只需要为bean定义方法设置形参即可,容器会根据类型自动装配对象。

      @Bean
      public DataSource dataSource(BookDao bookDao){
          System.out.println(bookDao);
          DruidDataSource ds = new DruidDataSource();
          ds.setDriverClassName(driver);
          ds.setUrl(url);
          ds.setUsername(userName);
          ds.setPassword(password);
          return ds;
      }
      
posted @ 2023-03-27 20:59  无机呱子  阅读(18)  评论(0编辑  收藏  举报