Spring基础

发布于 2022-04-08  115 次阅读


一、配置文件

1. Bean标签

scope: 指对象的作用范围

取值范围说明
singleton默认值,单例的,使用同一个对象
prototype多例的,创建多个对象
requestWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 request 域中
sessionWEB 项目中,Spring 创建一个 Bean 的对象,将对象存入到 session 域中
global sessionWEB 项目中,应用在 Portlet 环境,如果没有 Portlet 环境那么globalSession 相当

1)当scope的取值为singleton时

Bean的实例化个数:1个

Bean的实例化时机:当Spring核心文件被加载时,实例化配置的Bean实例

Bean的生命周期:

  • 对象创建:当应用加载,创建容器时,对象就被创建了
  • 对象运行:只要容器在,对象一直活着
  • 对象销毁:当应用卸载,销毁容器时,对象就被销毁了

2)当scope的取值为prototype时

Bean的实例化个数:多个

Bean的实例化时机:当调用getBean()方法时实例化Bean

  • 对象创建:当使用对象时,创建新的对象实例
  • 对象运行:只要对象在使用中,就一直活着
  • 对象销毁:当对象长时间不用时,被 Java 的垃圾回收器回收了演示代码ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao1 = (UserDao) app.getBean("userDao"); UserDao userDao2 = (UserDao) app.getBean("userDao"); System.out.println(userDao1); System.out.println(userDao2);singleton:当Spring核心文件被加载时创建UserDaoImpl被创建 com.ctc.dao.impl.UserDaoImpl@2b662a77 com.ctc.dao.impl.UserDaoImpl@2b662a77prototype:当get时创建UserDaoImpl被创建 UserDaoImpl被创建 com.ctc.dao.impl.UserDaoImpl@436813f3 com.ctc.dao.impl.UserDaoImpl@74fe5c40

2. Bean实例化三种方式

  • 无参构造方法实例化它会根据默认无参构造方法来创建类对象,如果bean中没有默认无参构造函数,将会创建失败<bean id="userDao" class="com.ctc.dao.impl.UserDaoImpl"></bean>
  • 工厂静态方法实例化public class StaticFactory {    public static UserDao getUserDao(){        return new UserDaoImpl();   } }<bean id="userDao" class="com.ctc.factory.StaticFactory" factory-method="getUserDao"></bean>
  • 工厂实例方法实例化public class UserServiceImpl implements UserService { ​    public void save() {        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");        UserDao userDao = (UserDao) app.getBean("userDao");        userDao.save();   } }<bean id="factory" class="com.ctc.factory.DynamicFactory"></bean> <bean id="userDao" factory-bean="factory" factory-method="getUserDao"></bean>

3.Bean的依赖注入

概念:

依赖注入(Dependency Injection):它是 Spring 框架核心 IOC 的具体实现。

在编写程序时,通过控制反转,把对象的创建交给了 Spring,但是代码中不可能出现没有依赖的情况。IOC 解耦只是降低他们的依赖关系,但不会消除。例如:业务层仍会调用持久层的方法。

那这种业务层和持久层的依赖关系,在使用 Spring 之后,就让 Spring 来维护了。简单的说,就是坐等框架把持久层对象传入业务层,而不用我们自己去获取。

依赖注入方式:

  • 构造方法
  • set方法

1)set方法注入

P命名空间注入本质也是set方法注入,但比起上述的set方法注入更加方便,主要体现在配置文件中,如下:

首先,需要引入P命名空间:

xmlns:p="http://www.springframework.org/schema/p"

其次,需要修改注入方式

<bean id="userService" class="com.ctc.service.impl.UserServiceImpl" p:userDao-ref="userDao"></bean>

2)构造方法注入

public class UserServiceImpl implements UserService {
​
    public void save() {
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserDao userDao = (UserDao) app.getBean("userDao");
        userDao.save();
    }
}
<bean id="userDao" class="com.ctc.dao.impl.UserDaoImpl">
<bean id="userService" class="com.ctc.service.impl.UserServiceImpl">
     <property name="userDao" ref="userDao"></property>
</bean>

依赖注入的数据类型

上面的操作,都是注入的引用Bean,处了对象的引用可以注入,普通数据类型,集合等都可以在容器中进行注入。

注入数据的三种数据类型

  • 普通数据类型
  • 引用数据类型
  • 集合数据类型

之前的操作都是对UserDao对象的引用进行注入的,下面将以set方法注入为

例,演示普通数据类型和集合数据类型的注入

        <bean id="userDao" class="com.ctc.dao.impl.UserDaoImpl">
                <property name="stringList">
                        <list>
                                <value>aaa</value>
                                <value>bbb</value>
                                <value>ccc</value>
                        </list>
                </property>
                <property name="userMap">
                        <map>
                                <entry key="user1" value-ref="user1"></entry>
                                <entry key="user2" value-ref="user2"></entry>
                        </map>
                </property>
                <property name="properties">
                        <props>
                                <prop key="p1">p</prop>
                                <prop key="p2">pp</prop>
                                <prop key="p3">ppp</prop>
                        </props>
                </property>
        </bean>
        
        <bean id="user1" class="com.ctc.domain.User">
                <property name="name" value="tom"></property>
                <property name="addr" value="beijing"></property>
        </bean>
        <bean id="user2" class="com.ctc.domain.User">
                <property name="name" value="lucy"></property>
                <property name="addr" value="tianjing"></property>
        </bean>
​
​
        <bean id="userService" class="com.ctc.service.impl.UserServiceImpl" p:userDao-ref="userDao"></bean>
​

4.引入其他配置文件

实际开发中,Spring的配置内容非常多,这就导致Spring配置很繁杂且体积很大,所以,可以将部分配置拆解到其他配置文件中,而在Spring主配置文件通过import标签进行加载

<import resource="applicationContext-xxx.xml"/>

二、配置数据源

1. 数据源(连接池)的作用

  • 数据源(连接池)是提高程序性能如出现的
  • 事先实例化数据源,初始化部分连接资源
  • 使用连接资源时从数据源中获取
  • 使用完毕后将连接资源归还给数据源

常见的数据源(连接池):DBCP、C3P0、BoneCP、Druid

2.Spring配置数据源

可以写在property中

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="user" value="root"></property>
        <property name="password" value="ctc20020327"></property>
    </bean>

也可以加载jdbc.properties配置文件获得连接信息

首先,需要引入context命名空间和约束路径:

    <!-- 加载外部的jdbc.properties文件-->  
    <context:property-placeholder location="classpath:jdbc.properties"/>
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

三、注解开发

1.Spring原始注解

Spring是轻代码而重配置的框架,配置比较繁重,影响开发效率,所以注解开发是一种趋势,注解代替xml配置文件可以简化配置,提高开发效率。

Spring原始注解主要是替代<Bean>的配置

注解说明
@Component使用在类上用于实例化Bean
@Controller使用在web层类上用于实例化Bean
@Service使用在service层类上用于实例化Bean
@Repository使用在dao层类上用于实例化Bean
@Autowired使用在字段上用于根据类型依赖注入
@Qualifier结合@Autowired一起使用用于根据名称进行依赖注入
@Resource相当于@Autowired+@Qualifier,按照名称进行注入
@Value注入普通属性
@Scope标注Bean的作用范围
@PostConstruct使用在方法上标注该方法是Bean的初始化方法
@PreDestroy使用在方法上标注该方法是Bean的销毁方法

注意:

使用注解进行开发时,需要在applicationContext.xml中配置组件扫描,作用是指定哪个包及其子包下的Bean需要进行扫描以便识别使用注解配置的类、字段和方法。

    <!-- 使用注解,需要配置组件扫描 -->
    <context:component-scan base-package="com.ctc"/>

2.Spring新注解

使用上面的注解还不能全部替代xml配置文件,还需要使用注解替代的配置如下:

注解说明
@Configuration用于指定当前类是一个 Spring 配置类,当创建容器时会从该类上加载注解
@ComponentScan用于指定 Spring 在初始化容器时要扫描的包。 作用和在 Spring 的 xml 配置文件中的<context:component-scan base-package="com.itheima"/>一样
@Bean方法上,标注将该方法的返回值存储到 Spring 容器中
@PropertySource用于加载.properties 文件中的配置
@Import用于导入其他配置类

四、Spring集成Junit

1.现存问题

在测试类中,每个测试方法都有以下两行代码:

ApplicationContext app = new ClassPathXmlApplicationContext("bean.xml");
IAccountService as = app.getBean("accountService",IAccountService.class);

这两行代码的作用是获取容器,如果不写的话,直接会提示空指针异常。所以又不能轻易删掉。

上述问题解决思路

  • 让SpringJunit负责创建Spring容器,但是需要将配置文件的名称告诉它
  • 将需要进行测试Bean直接在测试类中进行注入

2.Spring集成Junit步骤

  1. 导入spring集成Junit的坐标
       <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13.1</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.18</version>
        </dependency>

2. 使用@Runwith注解替换原来的运行期

@RunWith(SpringJUnit4ClassRunner.class)
public class SpringJunitTest {
}

3. 使用@ContextConfiguration指定配置文件或配置类

@RunWith(SpringJUnit4ClassRunner.class)
//@ContextConfiguration("classpath:applicationContext.xml")  // xml
@ContextConfiguration(classes = {SpringCofiguration.class})  // 全注解
public class SpringJunitTest {
​
}

4. 使用@Autowired注入需要测试的对象

   @Autowired
    private UserService userService;

5. 创建测试方法进行测试

    @Test
    public void test1() throws SQLException {
        userService.save();
        System.out.println(dataSource.getConnection());
    }