Spring框架的学习

Spring

Spring概要

**概述:**它是轻量级的开源的JavaEE框架

轻量级:它的体积小,依赖的jar包比较少,并且不需要额外依赖其他的组件

开源:免费提供源代码

框架:可以简化我们构建软件的过程

**目的:**为了解决企业级应用的复杂性

核心:

IOC:控制反转,把创建对象的过程交给Spring进行管理

AOP:面向切面编程–不修改源码进行功能增强

优点:

方便解耦,简化开发

对AOP编程的支持

方便程序的测试

方便整合其他各种的框架

方便进行事务开发

降低API成本

入门案例

IOC容器

概述:

控制反转

综上所述:控制反转就是把创建对象,和对象的调用过程交给Spring来管理。目的是为了降低类与类之间的耦合性

底层原理:

XML解析

工厂模式

反射

原理图解:
在这里插入图片描述

几个重要的概念:

1.IOC容器:IOC的实现,依赖于IOC容器,而IOC容器本质就是对象工厂

2.IOC容器的实现:

​ BeanFactory:是最底层的接口,它只提供了最简单的容器功能:加载配置文件和创建对象

​ 当加载配置文件时,不会创建被配置的对象,只有在使用时,对象才会创建。

​ 好处:节省内存

​ 坏处:因为在服务器运行的时候去创建对象,会影响执行效率

​ ApplictionComtext :应用上下文,它是继承了BeanFactory。它是Spring更高级的一个容器接口,它提供了更多有用的功能

​ 当加载配置文件的时候,会同时创建被配置的对象

​ 好处:效率高,将复杂的创建过程在服务器启动时完成

​ 坏处:耗费资源

  1. ApplictionComtext的两个实现类:

    ClassPathXmlApplicationContext:从项目中的resources文件中加载配置文件

    FileSystemXmlApplicationContext:从文件系统读取配置文件(需要访问权限)

    AnntationConfigApplicationContext:读取注解配置

    IOC操作-Bean管理

    **概念:**IOC操作—Bean管理是指两个操作:1.Spring创建对象2.Spring注入属性

    实现方式:

    1.XML方式

    2.注解方式

    基于XML方式-创建对象

    该方式与入门案列方式相同

    bean标签中的常用属性

    id:唯一表示,通过该属性可以找到对应的Bean标签

    class:类的全限定类名

    注意事项:

    创建对象是,默认执行无参构造来完成对象的创建(反射)

    基于XML方式-注入属性

    **DI:**依赖注入,它是IOC的一个具体操作

    分类:

    1.使用Set方法进行注入

    2.使用构造器进行注入

演示:

​ 属性注入通过

​ name:实体类属性名

​ value:属性值

构造方法注入

构造方法注入通过

P命名空间的注入

P命名空间的注入

xmlns:p="http://www.springframework.org/schema/p" 引入约束
<bean id="book" class="com.wdzl.pojo.Book" p:name="Java入门宝典" p:author="Tong"/>

特殊符号注入

1.null

<property name="name">
    <null></null>
</property>

2.使用转译字符

3.CDATA

<property name="author">
    <value><![CDATA[<Tong>]]></value>
</property>

外部bean

1.兴建Muole,在pom.xml中添加相关依赖

2.按照三层架构创建:Dao service web 在dao层中添加一个方法,在Service层中添加对Dao层的依赖(dao成员变量,对应的set方法)

3.配置对象信息

在这里插入图片描述

内部bean
1.在上一个演示案例的基础上,创建两个实体类Emp和Dept 其中Emp包含一个Dept对象属性

2.配置对象信息

在这里插入图片描述

级联操作

数组,集合属性的注入
基本数据类型

1.创建一个实体类

import java.util.Arrays;
import java.util.List;
import java.util.Map;

public class Demo {
    private String[] strings;
    private List<String> list;
    private Map<String, String> map;

    public Demo() {
    }

    public Demo(String[] strings, List<String> list, Map<String, String> map) {
        this.strings = strings;
        this.list = list;
        this.map = map;
    }

    public String[] getStrings() {
        return strings;
    }

    public void setStrings(String[] strings) {
        this.strings = strings;
    }

    public List<String> getList() {
        return list;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public Map<String, String> getMap() {
        return map;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    @Override
    public String toString() {
        return "Demo{" +
                "strings=" + Arrays.toString(strings) +
                ", list=" + list +
                ", map=" + map +
                '}';
    }
}

2.配置对象信息

<?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="demo" class="com.wdzl.pojo.Demo">
    <!--字符串数组-->
        <property name="strings">
            <array>
                <value>你好</value>
                <value>Hello</value>

            </array>
        </property>
        <!--list集合-->
        <property name="list">
            <list>
                <value>Hello</value>
                <value>Spring</value>
            </list>
        </property>
        <!--map集合-->
        <property name="map">
            <map>
                <entry key="hello" value="你好"></entry>
                <entry key="Spring" value="春天"></entry>
            </map>
        </property>

引用数据类型:
1.创建实体类:城市类和省类

/**
 * 城市类
 */
public class City {
    private String cityName;

    public City() {
    }

    public City(String cityName) {
        this.cityName = cityName;
    }

    public String getCityName() {
        return cityName;
    }

    public void setCityName(String cityName) {
        this.cityName = cityName;
    }

    @Override
    public String toString() {
        return "City{" +
                "cityName='" + cityName + '\'' +
                '}';
    }
}

/**
 * 省类
 */
public class Province {
    private List<String> cities;

    public Province() {
    }

    public Province(List<String> cities) {
        this.cities = cities;
    }

    public List<String> getCities() {
        return cities;
    }

    public void setCities(List<String> cities) {
        this.cities = cities;
    }

    @Override
    public String toString() {
        return "Province{" +
                "cities=" + cities +
                '}';
    }
}

2.配置对象信息

<?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:util="http://www.springframework.org/schema/util"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/util
        http://www.springframework.org/schema/util/spring-util.xsd">
  <!-- <bean id="province" class="com.wdzl.pojo.Province">
       <property name="cities">
           <list>
               <ref bean="city1"></ref>
               <ref bean="city2"></ref>
           </list>
       </property>
   </bean>
    <bean id="city1" class="com.wdzl.pojo.City">
        <property name="cityName" value="西安"></property>
    </bean>
    <bean id="city2" class="com.wdzl.pojo.City">
        <property name="cityName" value="长沙"></property>
    </bean>-->

    <util:list id="cityList">
        <value>西安</value>
        <value>长沙</value>
        <value>北京</value>
    </util:list>
    <bean id="province" class="com.wdzl.pojo.Province">
        <property name="cities" ref="cityList"></property>
    </bean>
</beans>

FactoryBean:

**概述:**Spring中有两种类型的bean,一种是普通bean,一种是工厂bean

  • 普通bean:在配置文件中定义的bean类型就是返回类型

  • 工厂bean:在配置文件中配置bean类型与返回值类型不同

    演示:

/**
 * 工厂bean类型
 */
public class MyBean implements FactoryBean<String> {


    /**
     * 返回对象:此方法中定义了注入MyBean时,真正返回的对象
     * @return
     * @throws Exception
     */
    @Override
    public String getObject() throws Exception {
        return "我是字符串";
    }

    /**
     * 返回对象类型
     * @return
     */
    @Override
    public Class<?> getObjectType() {
        return null;
    }

    /**
     * 是否是单例
     * @return
     */
    @Override
    public boolean isSingleton() {
        return false;
    }
}
<?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="myBean" class="com.wdzl.pojo.MyBean">

  </bean>
</beans>
Bean的作用域

**概述:**在Spring中,设置创建Bean类型是单例还是多例。默认情况下,Bean实例是单例的

注意:

  • Singleton 和 prototype的区别:

1.Singleton :在加载配置文件时,对象便会创建,并且,只创建一个对象

2.prototype:在加载配置文件时,并不创建对象,在调用getBean方法时,才会创建对象,并且每次调用都会创建

bean的生命周期

概述:
一个对象从创建到销毁的过程

过程:

  1. 通过构造器创建Bean实例
  2. 为Bean的属性设置值或引用其他Bean(调用set方法)
  3. 调用Bean的初始化方法
  4. Bean的对象获取
  5. 容器关闭,调用Bean的销毁方法

演示:

package com.wdzl.pojo;

/**
 * 用户类
 */
public class User {
    private String name;

    public User() {
        System.out.println("第一步:通过构造器创建对象");
    }

    public void setName(String name) {
        System.out.println("第二步:为Bean的属性设置值");
        this.name = name;
    }

    public void init() {
        System.out.println("第三步:调用初始化方法");
    }

    public void destroy() {
        System.out.println("第五步:调用销毁额方法");
    }
}


import com.wdzl.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        User user = context.getBean("user", User.class);
        System.out.println("第四步:获取对象");
        ( (ClassPathXmlApplicationContext)context).close();
    }
}

<?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="user" class="com.wdzl.pojo.User" init-method="init" destroy-method="destroy">
       <property name="name" value="唐康"></property>
   </bean>
</beans>

  • 在Bean的生命周期中,如果配置了后置处理,生命周期会额外的增加两步

    过程:

    1. 通过构造器创建Bean实例
    2. 为Bean的属性设置值或引用其他Bean(调用set方法)
    3. 执行后置处理
    4. 调用Bean的初始化方法
    5. 执行后置处理
    6. Bean的对象获取
    7. 容器关闭,调用Bean的销毁方法

​ 演示:

package com.wdzl.pojo;

/**
 * 用户类
 */
public class User {
    private String name;

    public User() {
        System.out.println("第一步:通过构造器创建对象");
    }

    public void setName(String name) {
        System.out.println("第二步:为Bean的属性设置值");
        this.name = name;
    }

    public void init() {
        System.out.println("第四步:调用初始化方法");
    }

    public void destroy() {
        System.out.println("第七步:调用销毁额方法");
    }
}


import com.wdzl.pojo.User;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class UserTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        User user = context.getBean("user", User.class);
        System.out.println("第六步:获取对象");
        ( (ClassPathXmlApplicationContext)context).close();
    }
}

<?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="user" class="com.wdzl.pojo.User" init-method="init" destroy-method="destroy">
       <property name="name" value="唐康"></property>
   </bean>
    <bean id="myBeanLast" class="com.wdzl.pojo.MyBeanLast">

    </bean>
</beans>

XML方式-自动装配

概述:
根据指定的装配规则(属性名称,属性类型),Spring自动将匹配的属性进行注入

实现:
借助标签里‘autowire’属性来实现自动装配,该属性有两个值:

  • byName:根据属性名称注入
  • byTYpe:根据属性类型注入

注意:

  • byType:如果有多个class属性相同的bean标签,自动装配会报错
引入外部配置文件
<!--引入外部配置文件-->
    <context:property-placeholder location="jdbc1.properties"/>
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${druid.driverClassName}"></property>
        <property name="url" value="${druid.url}"></property>
        <property name="username" value="${druid.username}"></property>
        <property name="password" value="${druid.password}"></property>
    </bean>
基于注解方式–创建对象

**注解概述:**注解是代码的特殊标记

注解格式:@注解名称 (属性名=属性值,属性名2=属性值…)

**注解应用:**它可以简化XML的配置,注解可以用在类上,属性上,方法上

Spring针对注解创建对象提供了4个注解

  • @Component:普通类使用

  • @Service:Service层使用

  • Controller:web层使用

  • @Repository:Dao层使用

    这四个注解功能是相同的,都可以用来创建Bean实例

步骤:

  1. 新建Moudule,添加依赖

  2. 创建UserDao,在该类上添加注解

    package com.wdzl.dao;
    
    import org.springframework.stereotype.Repository;
    
    /**
     *
     */
    
    @Repository(value = "userDao")//相当与id属性
    public class UserDao {
        public void addUser() {
            System.out.println("UserDao:addUser....");
        }
    
    }
    

3.在配置文件中开启组件扫描

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

</beans>

4.测试

import com.wdzl.dao.UserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class DemoTest {
    @Test
    public void test() {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        UserDao userDao = context.getBean("userDao", UserDao.class);
        System.out.println(userDao);
    }
}

基于注解方式–属性注入
  1. @AutoWired:根据属性类型进行自动装载
  2. @Qualifier:根据属性名进行注入
  3. @Resource:根据类型注入,也可以根据名称注入
  4. @Value:基本数据类型的注入

演示:

@AutoWired:

@Qualifier:

  • 要与@AutoWired同时使用
  • 同时使用的目的是为了解决根据属性类型无法自动装载的情况:比如BookDao有多个实现类

@Resource:

JDBCTemplate

概述:

​ Spring对JDBC的封装,使用它可以方便的去操作数据库

依赖

事务

事务环境搭建
  1. 新建一个Moudule,添加相关依赖

  2. 缩写配置wenjian

    • 配置JdbcTemplate

      • 注入数据源
    • 开启组件扫描

  3. 缩写Dao层接口,service层接口,及相应的实现类

  4. 测试

事务操作

  1. 事务应该添加到三层架构中的service层
    • 因为Service负责组装业务

​ 2.在Spring中进行事务管理

​ 编程式事务

​ 声明式事务

​ 3.声明式事务管理

基于注解方式

​ 基于XML方式

4.在Spring中进行声明式事务管理使用AOP原理

5.Spring针对不同的框架使用不同的API

基于注解方式的事务管理

@Transactional常见属性:

- propagation :事务传播行为
- isolation: 事务隔离级别
- timeout:超时时间
- readOnly:是否只读
- rollbackFor:回滚
- noRollbackFor:不回滚

1.创建实体类

package com.wdzl.pojo;

/**
 * 账户类
 */
public class Account {
    private int id ;
    private String name;
    private double money;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(double money) {
        this.money = money;
    }

    @Override
    public String toString() {
        return "Account{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", money=" + money +
                '}';
    }
}

2.数据库连接配置类

package com.wdzl.jdbc;

import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import javax.sql.DataSource;

/**
 * 数据库连接配置类
 */
public class JdbcConfig {
    @Bean//将DataSource注入Spring中
    public DataSource getDataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&amp;characterEncoding=utf-8");
        dataSource.setUsername("root");
        dataSource.setPassword("wangbiwu0412....");
        return dataSource;
    }

    @Bean//将SqlSessionFactory注入到Spring容器中
    public SqlSessionFactoryBean create(DataSource dataSource) {
        SqlSessionFactoryBean sqlSessionFactory = new SqlSessionFactoryBean();
        sqlSessionFactory.setDataSource(dataSource);
        Resource resource = new ClassPathResource("SqlMapConfig");
        sqlSessionFactory.setConfigLocation(resource);
        return sqlSessionFactory;
    }
}

3.配置类

/**
 * 配置类
 */
@Configuration//配置类
@ComponentScan(basePackages = "com.wdzl")//组件扫描
@Import(value = {JdbcConfig.class, TransactionConfig.class})//引入其他配置类
@EnableTransactionManagement//开启事务
public class SpringConfig {
}

4.事务管理类

public class TransactionConfig {
    @Bean
    public PlatformTransactionManager createTransactionManager(DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

}

5.dao层实现类

public interface AccountDao {
    /**
     * 根据用户名查询账户信息
     * @param name
     * @return
     */
    @Select("select * from account where name=#{name}")
    Account findAccountByName(String name) ;


    /**
     * 跟踪账户信息
     * @param account
     */
    @Update("update account set name=#{name},money=#{money} where id=#{id}")
    void updateAccount(Account account);


}
/**
 * 账户接口实现类
 */
@Repository
public class AccountDaoImpl implements AccountDao {
    //注入sqlSession工厂
    @Autowired
    private SqlSessionFactory sqlSessionFactory;

    @Override
    public Account findAccountByName(String name) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        return accountDao.findAccountByName(name);
    }

    @Override
    public void updateAccount(Account account) {
        SqlSession sqlSession = sqlSessionFactory.openSession();
        AccountDao accountDao = sqlSession.getMapper(AccountDao.class);
        accountDao.updateAccount(account);

    }
}

6.service层及其实现类

public interface AccountService {
    /**
     *转账业务
     */
    void transfer(String sourceName, String targetName, double money);
}
@Service
@Transactional
public class AccountServiceImpl implements AccountService {
    @Autowired
    private AccountDao accountDao;

    @Override
    public void transfer(String sourceName, String targetName, double money) {
        //查询转出账户对象
        Account source = accountDao.findAccountByName(sourceName);
        //查询注入账户对象
        Account target = accountDao.findAccountByName(targetName);

        //判断账户是否存在
        if (source !=null && target != null) {
            //设置转出转入金额
            source.setMoney(source.getMoney() - money);
            target.setMoney(target.getMoney() + money);

            //更新账户信息
            accountDao.updateAccount(source);
            //System.out.println(1/0);

            accountDao.updateAccount(target);



        }
    }
}

7.账户控制层

@Controller
public class AccountController {
    @Autowired
    private AccountService accountService;

    public void transfer(String sourceName, String targetName, double money) {
        try {
            accountService.transfer(sourceName, targetName, money);
            System.out.println("转账成功");
        } catch (Exception e) {
            System.out.println("转账失败");
        }


    }
}

8.编写配置类

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <mappers>

        <mapper class="com.wdzl.dao.AccountDao"></mapper>
    </mappers>
</configuration>

9.测试

public class AccountTest {
    @Test
    public void test() {
        ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class);
        AccountController accountController = context.getBean("accountController", AccountController.class);
        accountController.transfer("bobo", "tong",500);
        accountController.transfer("王必武","唐康",500.00);
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值