JAVA Spring 学习笔记

Bean 容器

为什么要使用Bean容器

因为希望减少new的操作,这样当我们的类名发生改变时,影响会降到最小

Bean相当于一个管家

原来需要我们自己new的对象现在统统通过Bean来创建

怎么使用Bean?

首先我们需要利用pom.xml来建立对于spring的依赖

关于pom.xml是Maven的知识

这里不做赘述

<!--    Spring 依赖-->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <version>5.2.22.RELEASE</version>
    </dependency>

创建了spring依赖之后

我们还需要创建一个xml文件,这个xml文件就是用来配置Bean容器的

<?xml version="1.0" encoding="UTF-8"?>
<!--该文件配置Maven中的Bean文件-->
<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
        ">

这是xml的基本信息,对于后缀为context的命令现在可以暂时忽略,后续会再介绍

然后就是配置Bean

对于每一个实现类我们都要配置一个Bean来和他对应

例如

    <bean id="userDaoimpl"  class="com.demo.Dao.impl.UserDaoimpl"/>

这里的id是bean 的ID ,后续我们通过bean来创建对象,就是通过这个id来寻找对应的Bean的

class对应的就是具体的实现类,注意一定要是实现类,因为我们创建对象都是实体类对象,没有接口对象

这里bean还有其他参数

例如

scope  这个参数用来表示Bean创建的对象是否是单例对象

如果是单例对象,那么每个bean只能创建一个对象,其余的都是对这个对象的引用

换而言之

就是无论创建多少对象,这些对象有着相同的地址

如果不是单例对象,那么不同对象有着不同的地址

配置好了一个Bean

下面就是如何利用Bean来创建对象

ApplicationContext applicationContext =
              new ClassPathXmlApplicationContext("applicationContext.xml");
        
        UserDao userDao = (UserDaoimpl)applicationContext.getBean("userDaoimpl");
        userDao.setId("123");
        System.out.println(userDao.getId());

有几个需要注意的地方

首先是

ClassPathXmlApplicationContext("applicationContext.xml")里边的参数
这里参数就是我们配置Bean文件的xml文件

其次我们可以用接口来指向实现对象,这是JAVA的内容,这里不做赘述

但是要在接口中声明相应的方法

然后就是getBean("userDaoimpl")  里边的参数就是我们前边提到的bean的id

这样我们通过Bean来创建一个对象就成功了

在实际开发中,我们并不会只单一的创造一个类

实际上是类与类之间有很多依赖关系

例如在UserServiceimpl.java中我们需要用到UserDao对象

这个时候我们不需要在UserServiceimpl利用上述的代码来创建

我们可以在xml中配置UserServiceimpl时配置相应的依赖关系

    <bean id="userServiceimpl" class="com.demo.Sevice.impl.UserServiceimpl">
<!--    为了避免在Service中new Dao对象,需要配置Service和Dao的依赖关系-->
<!--     首先name是指UserServiceimpl中变量的名称   这里的name必须有set方法与之对应-->
<!--     propery表示配置当前bean属性-->
<!--     ref表示参照哪一个bean  相当于一个映射  ref = beanId-->
<!--     可以有多个property  存在多个依赖关系-->
<!--     ref是对类的映射,Value是常规数据类型的设置-->
         <property name="userDao" ref="userDaoimpl"/>

   </bean>

注意一点 ref中的变量是已经配置好的bean的id

然后在UserServiceimpl必须有setName的方法

这是通过set方法来进行配置UserDao对象

我们也可以通过构造器来配置

    <bean id="userServiceimpl" class="com.demo.Sevice.impl.UserServiceimpl">
<!--    为了避免在Service中new Dao对象,需要配置Service和Dao的依赖关系-->
<!--     首先name是指UserServiceimpl中变量的名称   这里的name必须有set方法与之对应-->
<!--     propery表示配置当前bean属性-->
<!--     ref表示参照哪一个bean  相当于一个映射  ref = beanId-->
<!--     可以有多个property  存在多个依赖关系-->
<!--     ref是对类的映射,Value是常规数据类型的设置-->
         <property name="userDao" ref="userDaoimpl"/>
<!--        <property name="name" value="haha"/>-->
<!--        构造方法注入  如果没有set方法 就不用使用ref依赖传值  那么可以通过构造器传值-->
<!--        第一行是通过形参名字传值-->
<!--        第二行是通过数据类型传值-->
<!--        第三行通过参数位置传参-->

<!--        <constructor-arg name="userDao" ref="userDaoimpl"/>-->
<!--        <constructor-arg type="java.lang.String" value="haha"/>-->
<!--        <constructor-arg index="1" value="haha"/>-->

   </bean>

 

当然为了简化开发

spring提供了自动依赖

    <bean id="userServiceimpl" class="com.demo.Sevice.impl.UserServiceimpl" autowire="byType"/>
通过byType来建立依赖  那么只需要有对应的类的bean
通过bYName来建立依赖 那么对应的类的Bean的id一定要和变量名相同
例如:UserServiceimpl有一个 private UserDao userDao 那么UserDao对应的实现类的id一定要为userDao

现在自己创建的类的Bean以及如何建立相互的依赖我们已经清楚了
下面介绍怎么创建别人写好的类bean
回到一开始我们说的xml文件中的context
实际上就是一个新的命名空间,为了防止命名重复问题(个人理解哈)
然后我们创建相应的Bean就可以了
以链接数据库为例
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql:///"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

 然后和创建Dao对象一样

根据id来创建就可以了

当然我们也可以把property写在同一个文件中中 然后在xml中加载就可以了

<!--加载context命名空间-->
<!--    使用context命名加载propert配置文件-->
<!--    System   是否加载系统的properties
-->
    <context:property-placeholder location="classpath*:*.property" system-properties-mode="NEVER"/>
<!--    注意配置component-scan是在context中配置-->

到这里 关于bean的基础用法就说完了

下面会介绍纯注解开发

然后上边说的这一堆都没用了

 注解开发

可以在对应的类中配置Bean

具体方法如下:

利用@Component 来声明当前类为Bean

@Component("userDaoimpl")
//Reposity和component效果一样
//spring 对于不同的层提供了不同的方法
//@Repository
public class UserDaoimpl implements UserDao {
    private String id;
    private String password;
}

同时要在xml文件中配置相关的说明这是一个Bean

<context:component-scan base-package="com.demo.Dao.impl"/>

也就是这样

这样会自动装填Imp目录下所有的Component

如果在Component中没有说明当前类对应的名称

则利用getBean()方法创建对象时,参数为对应的类

spring提供了@Component的三个衍生注解

分别对应三个不用的层次

@Controller 用于表现层Bean定义

@Service    用于业务层Bean定义

@Repository 用于数据层Bean定义

 纯注解开发

通过Java类来代替xml文件

我们首先定义一个配置类

名字随便

我这里叫做springConfig

然后我们利用注解来说明这是一个配置类

@Configuration
@Configuration
@ComponentScan("com.demo")
public class SpringConfig {
}
@ComponentScan("com.demo")
这个相当于搜索com.demo下的所有Bean
如果要搜索多个
需要用{}圈起来即可
@Configuration
@ComponentScan({"com.demo",“xxxxx”})
public class SpringConfig {
}

 


因为xml被取代了
所以我们不再通过xml来获得
ApplicationContext对象
而是通过
AnnotationConfigApplicationContext方法来获得
代码如下
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(SpringConfig.class);

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

        UserDao userDao = (UserDaoimpl)applicationContext.getBean("userDaoimpl");

如果运行时有

Failed to read candidate component class: file [ ]; nested exception is org.springframework.core.NestedIOException报错

那是因为spring版本太低无法与JDK相兼容导致的

所以要升高spring版本

利用注解完成自动依赖注入

在Service中需要用到Dao对象

刚开始我们是通过New来创建

后来通过xml文件来实现bean的依赖

现在取消了xml文件

我们通过注解来完成依赖

只需要通过@Autowired来完成依赖即可

    @Autowired
    //利用注释加入依赖 根据类型自动装填
    private UserDao userDao;

以上是利用类型自动装配

也可以通过名称来完成装配

    
  @Autowired

  //利用名称完成依赖 前提必须有Autowired
    @Qualifier("userDaoimpl")
    private UserDao userDao;

使用@Value 能够完成简单类型的注入

同样的我们可以把所有的数据放在property文件中

然后在我们的配置类里

利用注解加载property文件即可

例如:

@PropertySource("Jdbc.property")

利用注解管理第三方Bean
以数据库为例首先我们要建立一个Java类让这个类中的方法返回我们想要的类型
public class JdbcConfig {
    //首先我们定义一个方法来获得要管理的对象
    //然后我们通过@Bean来表示当前方法是的返回值是一个Bean
    @Bean
    public DataSource getDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://");
        dataSource.setUsername("root");
        dataSource.setPassword("");
        return dataSource;
    }
}

然后在我们的配置文件中导入这个类

@Configuration
@ComponentScan("com.demo")
@PropertySource("Jdbc.property")
@Import(JdbcConfig.class)
public class SpringConfig {
}

然后在Main函数中根据类名来通过Bean创建相应的对象就可以了

对于第三方Bean中如果有对其他类的依赖

那么@Bean方法会自动装入

Spring整合Mybatis

首先看一下项目目录

 

 

 因为以前所有的知识点都在一个模块里,而且目录比较混乱

所以对模块重构了一下

首先我们要在pom.xml文件中声明所需要的依赖

新增这两个依赖

    <!--    利用spring操作数据库依赖  -->
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-jdbc</artifactId>
      <version>5.3.23</version>
    </dependency>
    <!--mybaties 与spring整合的依赖-->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>2.0.6</version>
    </dependency>

然后介绍一下各个类的作用

Domain是对应数据库的类实体,这个类不需要声明为Bean

package com.demo.Domain;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class User {
    private int id;
    private String Password;
}

 

然后是config文件,里边是各种配置类

SpringConfig配置类

 

 

package com.demo.config;

import org.springframework.context.annotation.*;
//声明这是一个配置类
@Configuration
//扫描所有的Bean文件 @ComponentScan(
"com.demo") //@PropertySource("Jdbc.property")

//引用其他的配置类,各个配置类分开 @Import({JdbcConfig.class, MybatisConfig.class}) public class SpringConfig { }

JdbcConfig配置类

package com.demo.config;

import com.alibaba.druid.pool.DruidDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

import javax.sql.DataSource;

//@Configuration
public class JdbcConfig {
    //首先我们定义一个方法来获得要管理的对象
    //然后我们通过@Bean来表示当前方法是的返回值是一个Bean
    @Bean
    public DataSource getDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://127.0.0.1:3306/mp");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }
}

为什么要提供一个DataSource的Bean

因为利用Spring链接数据库是我们要创建一个SqlSeesionFactoy对象

原来是通过xml文件来配置相关的信息

现在我们直接通过DataSource就能创建SqlSeesionFactoy对象

package com.demo.config;

import com.demo.Dao.UserDao;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.mapper.MapperScannerConfigurer;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;

public class MybatisConfig {
    //在spring中 如果想要动用第三方类形成的Bean
    //我们直接利用形参传入即可
    //因为spring会自动扫描所需的依赖
    //前提是已经把第三方类声明为bean类型
    //mybitas通过sqlSessionFactor来创建sqlsession对象
    //sqlSession是操作数据库的类
   //Spring提供了SqlSessionFactoryBean来简化这个过程
  //我们只需要传入一个DataSource对象就可完成创建
  //同时还要说明数据库查询方法对应的接口
@Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){ SqlSessionFactoryBean sessionFactoryBean = new SqlSessionFactoryBean(); sessionFactoryBean.setTypeAliases(User.class); sessionFactoryBean.setDataSource(dataSource); return sessionFactoryBean; }
  //设置Mapper对应的类 @Bean
public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer mapperScannerConfigurer = new MapperScannerConfigurer(); mapperScannerConfigurer.setBasePackage("com.demo.Dao"); return mapperScannerConfigurer; } }

Config各个类介绍完毕

然后Dao是我们实现数据库查询的接口

也是利用注解开发的

UserDao

package com.demo.Dao;

import com.demo.Domain.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.springframework.stereotype.Component;

import java.util.List;

@Mapper
public interface UserDao {
    @Select("select * from user")
    public List<User> getAll();
 }

@Mapper 也是把这个接口声明为一个Bean 同时也说明这是一个Mapper类

然后就是服务层Service

首先是接口

package com.demo.Service;

import com.demo.Dao.UserDao;
import com.demo.Domain.User;

import java.util.List;

public interface UserService {
    public List<User> getAll();
}

然后是实现类

@Service说明这也是一个Bean

@Autowired  自动装填

因为我们已经把UserDao声明为一个Bean了

package com.demo.Service.impl;

import com.demo.Dao.UserDao;
import com.demo.Domain.User;
import com.demo.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;
    public List<User> getAll() {
        return userDao.getAll();
    }
}

最后是测试类

package com.testDemo;

import com.demo.Domain.User;
import com.demo.Service.UserService;
import com.demo.Service.impl.UserServiceImpl;
import com.demo.config.SpringConfig;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import java.util.List;

public class Test {
    @org.junit.Test
    public void test(){
        ApplicationContext applicationContext =
                new AnnotationConfigApplicationContext(SpringConfig.class);
        UserService userService = (UserService) applicationContext.getBean(UserServiceImpl.class);
        List<User> userList = userService.getAll();
        for(User user:userList){
            System.out.println(user.getId()+" "+user.getPassword());
        }
    }
}

 

 

 



posted @ 2022-09-20 21:57  zzRh_5479  阅读(26)  评论(0编辑  收藏  举报