首页 > 其他分享 >spring 基础

spring 基础

时间:2022-12-26 17:55:51浏览次数:59  
标签:xml 容器 spring 配置 基础 class bean public

概述

Spring 是分层的JavaSE/EE应用 full-stack 轻量级开源框架,以Ioc(Inverse Of Control:反转控制)和AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层Spring MVC和持久层Spring JDBC以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多著名的第三方框架和类库。

1、IoC的概念和作用

IoC(inversion of Control):其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源。作为回应,容器适时的返回资源。而应用了IOC之后,则是容器主动地将资源推送给他所管理的组件,组件所要做的仅仅是选择一种合适的方式来接受资源。这种行为也被称为查找的被动形式。

DI(Dependency Injection)——IOC的另一种表述方式:即组件以一些预先定义好的方式(例如setter方法)接受来自如容器的资源注入

1.1、程序间的耦合和解耦

程序的耦合:

  • 耦合:程序间的依赖关系
    包括:
    • 类之间的依赖
    • 方法间的依赖
  • 解耦:
    降低程序间的依赖关系
    实际开发中:
    应该做到:编译期不依赖,运行时才依赖
    解耦的思路:
    第一步:使用反射来创建对象,而避免使用new关键字
    DriverManager.registerDriver(new oracle.jdbc.OracleDriver()); ==> Class.forName("oracle.jdbc.OracleDriver")
    第二步:通过读取配置文件来获取要创建的对象全限定类名

1.2、Spring的IoC原理

1.2.1、手动创建一个简单的Bean工厂解耦

Bean:在计算机英语中,有可重用组件的含义。

JavaBean:用java编写的可重用组件。javaBean的范围远远大于实体类。
编写一个创建bean对象的工厂,利用Bean工厂创建service和dao对象:

  • 需要一个配置文件来配置我们的service和dao
    配置文件的内容为: 唯一标识=全限定类名 (key=value)
  • 通过读取配置文件中配置的内容,反射创建对象
    配置文件可以是xml或properties文件

示例程序:

public class BeanFactory {

    // 定义一个Properties对象
    private static Properties props;

    // 使用静态代码块为Properties对象赋值
    static {
        try {
            // 实例化对象
            props = new Properties();
            // 获取properties文件的流对象;
            // 此处使用BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties")获取路径
            // 获取与class同级目录的resources中的bean.properties文件
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);
        } catch (Exception e) {
            // 抛出一个error错误
            throw new ExceptionInInitializerError("初始化properties失败");
        }
    }

    /**
     * 根据bean名称获取bean对象
     */
    public static Object getBean(String beanName) {
        Object bean = null;
        try {
            String beanPath = props.getProperty(beanName);
            bean = Class.forName(beanPath).newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return bean;
    }
}

在resource文件夹下创建bean.properties配置文件

accountService=com.study.service.impl.AccountServiceImpl
accountDao=com.study.dao.impl.AccountDaoImpl

在需要使用bean的位置,利用BeanFactory创建bean

private IAccountDao accountDao = (IAccountDao) BeanFactory.getBean("accountDao");
IAccountService as = (IAccountService) BeanFactory.getBean("accountService");

1.2.2、使用容器将工厂修改为单例模式

单例模式时:类对象只会被创建一次,从而类中的成员也就只会初始化一次。
多例模式时:类对象会被多次创建,执行效率没有单例对象高。

在bean工厂中创建一个容器。bean初始化执行静态代码块时,为Properties配置文件中所有配置的bean都初始化出一个对应的对象,存储在容器中,后续根据配置取对象时直接从容器中取这个单例的对象。

public class BeanFactory {

    // 定义一个Properties对象
    private static Properties props;

    // 定义一个map,用于存放我们创建的对象。我们把它称为容器
    private static Map<String, Object> beans;

    static {
        try {
            props = new Properties();
            InputStream in = BeanFactory.class.getClassLoader().getResourceAsStream("bean.properties");
            props.load(in);

            // 实例化容器
            beans = new HashMap<String, Object>();
            // 取出配置文件中所有的key
            Enumeration keys = props.keys();
            while(keys.hasMoreElements()) {
                String key = keys.nextElement().toString();
                String beanPath = props.getProperty(key);
                Object value = Class.forName(beanPath).newInstance();
                beans.put(key, value);
            }
        } catch (Exception e) {
            // 抛出一个error错误
            throw new ExceptionInInitializerError("初始化properties失败");
        }
    }

    /**
     * 根据bean名称获取单例的bean对象
     * @param beanName
     * @return
     */
    public static Object getBean(String beanName) {
        return beans.get(beanName);
    }
}

1.2.3、控制反转——Inversion Of Control

控制反转(Inversion Of Control,缩写Ioc):把创建对象的权利交给框架。包括依赖注入(Dependency Injection,缩写DI)和依赖查找(Dependency Lookup)。

在上面的工厂示例中:将原来在具体业务逻辑中可以自主new出来的service和dao对象,改成在工厂中进行控制,具体业务逻辑中直接读取bean工厂中生成的对象。控制权发生了转移,就叫控制反转。

IoC的作用:削减计算机程序间的耦合(解除代码中的依赖关系)。

2、Spring中的IoC

2.1、Spring-framework源码文件结构

  • docs
    spring-framework的说明文档
  • libs
    spring-framework的jar包。
    每个jar包都分为三个:
    • xxx.jar:可以直接引用的jar包
    • xxx-javadoc.jar:该jar的说明文档
    • xxx-sources.jar:源码
  • schema
    xml的schema约束

2.2、Bean工厂示例修改为spring方式

2.2.1、引入spring的pom依赖

引入spring-context的依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
</dependencies>

引入maven依赖后,libraries中会出现6个jar包:

  • spring-aop
    使用注解时需要使用该jar包。如果是手动导入的jar包,在不使用注解时可以不导入该jar包。
  • spring-jcl
    commons-loggin.jar,内容为:org.apache.commons.logging
  • spring-beans、spring-context、spring-core、spring-expression
    spring的核心jar包

2.2.2、编写xml配置文件

在resources文件夹中创建bean.xml配置文件。
bean.xml可以为任意文件名,后期会使用applicationContext.xml。
xml引入的约束可以在spring-framework的doc文档中找到。

<?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的唯一标识和全限定类名 -->
    <bean id="accountService" class="com.study.service.impl.AccountServiceImpl">
    </bean>
    <bean id="accountDao" class="com.study.dao.impl.AccountDaoImpl">
    </bean>
</beans>

2.2.3、在main方法中加载配置创建容器获取bean

使用ApplicationContext创建bean对象

public class Client {
    public static void main(String[] args) {

        // 获取spring的IoC核心容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");

        // 从容器中获取指定id的bean对象
        // 可以进行强制转换,也可以在第二个参数中传入指定要获取的bean的类型
        IAccountService as = (IAccountService) ac.getBean("accountService");
        IAccountDao ad = ac.getBean("accountDao", IAccountDao.class);

        System.out.println(as);
        System.out.println(ad);
    }
}

使用BeanFactory创建对象示例:

Resource resourse = new ClassPathResource("bean.xml");
BeanFactory factory = new XmlBeanFactory(resourse);
IAccountService as = factory.getBean("accountService", IAccountService.class);
IAccountDao ad = factory.getBean("accountDao", IAccountDao.class);
System.out.println(as);
System.out.println(ad);

ApplicationContext常用的三个实现类:

  • ClassPathXmlApplicationContext:从类路径下加载配置文件,要求配置文件必须在类路径下(最常用)
  • FileSystemXmlApplicationContext:从磁盘任意路径加载有访问权限的配置文件(即绝对路径)
  • AnnotationConfigApplicationContext:用于读取注解创建容器

核心容器的两个接口引发的问题:

  • ApplicationContext:它在构建核心容器时,创建对象的策略是采用立即加载的方式。也就是说,只要一读完配置文件马上就创建配置文件中配置的对象。单例对象适用。
  • BeanFactory:它在构建核心容器时,创建对象采用的策略是延迟加载的方式。也就是说,什么时候根据id获取对象了,什么时候就真正的创建对象。多例对象适用。

BeanFactory是个顶层接口,实际中更经常使用ApplicationContext。ApplicationContext可以根据我们的配置去自动选择采用延迟或立即加载。

2.3、spring中bean的管理细节

2.3.1、bean的创建方式

  • 使用默认构造函数创建
    在spring的配置文件中使用标签,配以id和class属性之后,且没有其他属性和标签时。采用的就是默认构造函数创建bean对象,此时如果类中没有默认构造函数,则对象无法创建。
  • 使用普通工厂中的方法创建对象
    使用另一个类中的方法创建需要的类的对象,并存入spring容器。
    InstanceFactory.java
    bean.xml
  • 使用工厂中的静态方法创建对象
    使用另一个类中的静态方法创建需要的类的对象,并存入spring容器。
    StaticFactory.java
    bean.xml

2.3.2、bean对象的作用范围调整

bean标签的scope属性:

  • 作用:用于指定bean的作用范围
  • 取值:常用的值为:singleton、prototype
    • singleton:单例的(默认值)
    • prototype:多例的
    • request:作用于web应用的请求范围
    • session:作用于web应用的会话范围
    • global-session:作用于集群环境的会话范围(全局会话范围)。当不是集群环境时,它和session等效。
<!-- 使用多例方式 -->
<bean id="accountService" class="com.study.service.impl.AccountServiceImpl" scope="prototype">
</bean>

2.3.3、bean对象的生命周期

单例对象:

  • 出生:当容器创建时对象出生
  • 活着:只要容器还在,对象一直活着
  • 死亡:容器销毁,对象消亡
  • 总结:单例对象的生命周期和容器相同

多例对象:

  • 出生:当我们使用对象时spring框架为我们创建
  • 活着:对象在使用过程中就一直活着
  • 死亡:当对象长时间不用且没有别的对象引用时,由java的垃圾回收器回收。

示例程序:
AccountSercviceImpl.java

public void saveAccount() {
    System.out.println("service中的saveAccount执行了");
}

public void init() {
    System.out.println("init 方法执行了.");
}

public void  destroy() {
    System.out.println("destroy方法执行了");
}

bean.xml

<!-- init-method:对象创建时执行的方法
	 destroy-method:对象销毁时执行的方法 -->
<bean id="accountService"
      class="com.study.service.impl.AccountServiceImpl"
      init-method="init"
      destroy-method="destroy"
      >
</bean>

Client.java

public static void main(String[] args) {

    // ClassPathXmlApplicationContext有close()方法,
    // 但是接口ApplicationContext没有该方法
    ClassPathXmlApplicationContext ac = 
        new ClassPathXmlApplicationContext("bean.xml");
    IAccountService as = ac.getBean("accountService", IAccountService.class);
    System.out.println(as);

    // 如果不手动关闭容器,程序运行完时main方法进程就关闭了,就看不到容器关闭的打印语句了
    ac.close();
}

2.4、依赖注入

Dependency Injection,简称DI。

依赖关系的管理以后都交给spring维护。在当前类需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明。这种依赖关系的维护就叫做依赖注入。

依赖注入能注入的数据有三类:

  • 基本类型和String
  • 其他bean类型(在配置文件中或注解配置过的bean)
  • 复杂类型/集合类型

依赖注入的方式有三种:

  • 使用构造函数提供
  • 使用set方法提供
  • 使用注解提供

2.4.1、构造函数注入

AccountServiceImpl.java

public class AccountServiceImpl implements IAccountService {

    // 如果是经常变化的数据,并不适用于注入的方式
    private String name;  // String类型
    private Integer age;  // 基本数据类型的包装类型
    private Date birthday;  // 其他bean类型

    // 构造函数中需要传入相关变量
    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    public void saveAccount() {
        System.out.println("service中的saveAccount执行了" + this.toString());
    }

    @Override
    public String toString() {
        return "AccountServiceImpl{" + "name='" + name + '\'' + ", age=" + age + ", birthday=" + birthday + '}';
    }
}


在bean.xml中的标签下使用标签通过构造函数注入相关变量的值:

<constructor-arg>标签:
 
● 出现的位置:<bean>标签的内部
● 标签中的属性: 
  ○ type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个或某些参数的类型。(当构造函数中有多个类型相同的参数时,使用type无法区分)
  ○ index:用于给构造函数中指定索引位置的参数赋值,索引位置从0开始。(使用前要知道该类的构造函数中每个参数的位置,使用不太方方便)
  ○ name:用于给构造函数中指定名称的参数赋值。(经常用)
  ○ value:用于提供基本类型、基本类型包装类型和String类型的数据
  ○ ref:用于指定其他的bean类型数据(在Spring的IoC核心容器中出现过的bean对象)
 
● 也可以在constructor-arg标签内嵌入value标签来赋值
● 如果value值带有特殊符号,使用<![CDATA[]]>包裹起来
● 优势:在获取bean对象时,注入数据是必须的操作,否则对象无法创建。
● 弊端:改变了bean对象的实例化方式,使我们在创建对象时如果用不到这些数据也必须提供。


<bean id="accountService" class="com.study.service.impl.AccountServiceImpl">
    <!-- String类型的name变量可以直接注入值 -->
    <constructor-arg name="name" value="test"></constructor-arg>
    <!-- Integer类型的age变量,Spring会自动将值转换为需要的类型 -->
    <constructor-arg name="age" value="18"></constructor-arg>
    <!-- 复杂类型的变量,需要通过ref映射到容器中出现过的bean对象 -->
    <constructor-arg name="birthday" ref="nowDate"></constructor-arg>
    <constructor-arg name="desc">
        <!-- 属性值可以使用value节点进行配置 -->
        <!-- 赋值带有特殊符号的<shanghai^..>,需要使用<![CDATA[]]>包裹起来 -->
        <value><![CDATA[<shanghai^..>]]></value>
    </constructor-arg>
</bean>

<bean id="nowDate" class="java.util.Date"></bean>

2.4.2、set方法注入

<property>标签:
●  出现的位置:<bean>标签的内部
●  标签的属性:
  ○ name:用于指定注入时所调用的set方法名称(并不关注实际变量名称,只关注set方法名称。如果变量age的set方法为setUseAge(int age),则name应该为userAge)
  ○ value:用于提供基本类型和String类型的数据
  ○ ref:用于指定其他的bean类型数据(在Spring的IoC核心容器中出现过的bean对象)
●  null值可以使用专用的<null/>标签进行赋值 
●  引用类型的变量,可以在标签内再嵌入一个<bean>标签作为内部bean,内部Bean不能在其他地方调用
●  可以使用级联赋值
●  优势:创建对象时没有明确的限制,可以直接使用默认构造函数。
●  弊端:如果有某个成员必须有值,则获取对象时set方法无法保证该成员一定已经赋值。

<property name="car">
    <bean class="com.study.Person">
        <property name="name" value="张三" />
    </bean>
</property>

<!-- 需要先构造car,否则会出现空指针异常 -->
<property ref="car" />
<property name="car.maxSpeed" value="200"/>


2.4.3、注入集合数据

使用属性的setter方法给集合类型的属性注入值。

public class AccountServiceImpl3 implements IAccountService {

    // 数组、Set集合、List集合
    private String[] myStrs;
    private List<String> myList;
    private Set<String> mySet;
    
    // Map集合、Properties键值对
    private Map<String,String> myMap;
    private Properties myProperties;

    public void setMyStrs(String[] myStrs) {
        this.myStrs = myStrs;
    }

    public void setMyList(List<String> myList) {
        this.myList = myList;
    }

    public void setMySet(Set<String> mySet) {
        this.mySet = mySet;
    }

    public void setMyMap(Map<String, String> myMap) {
        this.myMap = myMap;
    }

    public void setMyProperties(Properties myProperties) {
        this.myProperties = myProperties;
    }

    public void saveAccount() {}

}
<bean id="accountService3" class="com.study.service.impl.AccountServiceImpl3">
    <property name="myStrs">
        <array>
            <value>aaa</value>
            <value>bbb</value>
            <value>ccc</value>
        </array>
    </property>
    <property name="myList">
        <list>
            <value>aaa</value>
            <value>bbb</value>
            <value>ccc</value>
        </list>
    </property>
    <property name="mySet">
        <set>
            <value>aaa</value>
            <value>bbb</value>
            <value>ccc</value>
        </set>
    </property>
    <property name="myMap">
        <map>
            <!-- map标签下的entry标签,value可以作为标签属性,也可以作为子标签 -->
            <entry key="key1" value="aaa"></entry>
            <entry key="key2">
                <value>bbb</value>
            </entry>
            <entry key="key3" value="ccc"></entry>
        </map>
    </property>
    <property name="myProperties">
        <props>
            <prop key="key1">aaa</prop>
            <prop key="key2">bbb</prop>
            <prop key="key3">ccc</prop>
        </props>
    </property>
</bean>
<set>、<list>、<array>三种类型的数据的结构相同,三个标签可以任意互换;
<map>、<props>标签的数据结构相同,这两个标签可以互换使用。

3、基于注解的IoC配置

注解配置和xml配置实现的功能是一样的,都是为了降低程序间的耦合,只是配置的形式不一样。

3.1、配置xml扫描指定包

要使用注解,需要在xml中配置容器扫描指定包里面的类上的注解
该项配置所需的标签不在beans的约束中,而是一个名称为context的名称空间的约束中。该约束可以从spring官方文档中复制
bean.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"
       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">

    <!--  告知spring在创建容器时要扫描的包,但是这个配置所需的标签不在beans的约束中,而是一个名称为context名称空间约束中  -->
    <context:component-scan base-package="com.study"></context:component-scan>
</beans>

3.2、用于创建对象的注解

这些注解的作用和在xml中配置标签的作用一样。

  • @Component
    作用: 用于将当前类对象存入Spring容器中
    属性:value属性用于指定存入spring容器中的bean的id,不配置时默认为:当前类的类名首字母转小写
  • @Controller
    一般用在表现层。
    作用、属性同@Component完全一样。
  • @Service
    一般用在业务层。
    作用、属性同@Component完全一样。
  • @Repository
    一般用在持久层。
    作用、属性同@Component完全一样。

@Controller、@Service、@Repository三个注解的作用、属性同@Component完全一样。
他们三个只是Spring框架为我们提供明确的三层,使我们的三层对象更清晰。

@Service("accountService")
public class AccountServiceImpl implements IAccountService {

    private IAccountDao accountDao;

    public void saveAccount() {
        accountDao.saveAccount();
    }
}

3.3、用于注入数据的注解

这些注解的作用和xml配置的标签下的标签的作用是一样的。

  • @Autowired
    作用:
    自动按照类型注入,只要容器中有唯一的一个bean对象类型和要注入的变量类型匹配,就可以注入成功。
    如果IoC容器中没有任何bean的类型和要注入的变量的类型匹配,则报错。
    如果IoC容器中该类型的bean存在多个,则将要注入的变量的变量名作为bean的id进行二次匹配:
    如果根据变量名可以找到唯一的bean,则进行注入。
    如果根据变量名匹配不到,则报错。
    出现位置:可以使变量上,也可以是方法上。
    细节:在使用注解进行注入时,变量的setter方法就不是必须的了。

  • @Qualifier
    作用:
    在按照类型匹配的基础上,再按照名称匹配注入。
    它在给类的成员变量注入时,不能单独使用,要和@Autowired配合使用。
    它在给方法参数进行注入时,可以单独使用。
    属性:
    value:用于指定要注入的bean的id。

  • @Resource
    作用:直接按照bean的id进行注入。它可以独立使用。
    属性:
    name:用于指定bean的id。

  • @Value
    作用:用于注入基本类型和String类型的变量
    属性:
    value:用于指定数据的值。可以配置:字面量、${key}(从环境变量、配置文件中获取值)、使用Spring中的SpEL(Spring中的EL表达式:#{表达式})。

@Autowired、@Qualifier、@Resource三个注解只能注入bean类型的数据,不能注入基本数据类型和String类型。

集合类型的注入只能使用xml来实现。

@Service("accountService")
public class AccountServiceImpl implements IAccountService {

    @Resource(name = "accountDao")
    private IAccountDao accountDao;

    public void saveAccount() {
        accountDao.saveAccount();
    }
}

3.4、用于改变作用范围的注解

这些注解的作用和xml配置的标签的scope属性的作用一样。

  • @Scope
    作用:用于指定bean的作用范围。
    属性:
    value:指定范围的取值。常用取值:singleton、prototype。(不配置时默认为singleton)
@Service("accountService")
@Scope("prototype")
public class AccountServiceImpl implements IAccountService {

    @Resource(name = "accountDao")
    private IAccountDao accountDao;

    public void saveAccount() {
        accountDao.saveAccount();
    }
}

3.5、和生命周期相关的注解

这些注解的作用和xml配置的标签的init-method、destroy-method属性作用相同。

  • @PreDestroy
    作用:用于指定销毁方法。
  • @PostConstruct
    作用:用于指定初始化方法。
@Service("accountService")
public class AccountServiceImpl implements IAccountService {

    @Resource(name = "accountDao")
    private IAccountDao accountDao;

    public void saveAccount() {
        accountDao.saveAccount();
    }

    @PostConstruct
    public void init() {
        System.out.println("初始化方法");
    }

    @PreDestroy
    public void destroy() {
        System.out.println("销毁方法");
    }
}

3.6、在配置类中利用java方法创建bean

当我们需要在程序中使用commons-dbutils去操作数据库时,需要创建DataSource、QueryRunner对象存入Spring的容器。创建对象、存入容器的过程可以放在一个配置类中,将创建对象的方法返回值作为bean存入容器。

  • @Configuration
    作用:指定当前类为一个配置类
    细节:当该类作为AnnotationConfigApplicationContext对象创建的参数时,该注解可以不写。
  • @ComponentScan
    作用:指定Spring在创建容器时要扫描的包。作用和xml中配置的context:component-scan一样。
    属性:value/basePackages:两个属性的作用一样,都是指定创建容器时要扫描的包。属性的值为数组。
  • @Bean
    作用:将方法的返回值作为一个bean对象,存入Spring的IoC容器中。
    属性:value/name:两个属性的作用一样,用于指定bean的id。不配置该属性时,默认以方法名作为id。
    细节:当我们给方法配置@Bean注解时,如果方法有参数,Spring会去容器中查找有无可用的bean对象。查找的方式和@Autowired相同。
  • @Import
    作用:用于导入其他的配置类。
    属性:value:用于指定要导入的其他配置类的字节码文件。当使用@Import的注解之后,有@Import注解的就是主配置类,而导入的都是子配置类。

设置配置类的不同方式:

  1. 在AnnotationConfigApplicationContext构造方法中传参:
  2. 使用@Configuration注解声明配置类:(需要在主配置类中使用@ComponentScan注解扫描到该配置类所在的包
  3. 使用@Import注解导入其他配置
ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class,JdbcConfiguration.class);

@Configuration
public class SpringConfiguration {
  // ....
}
@Configuration
public class JdbcConfiguration {
  // ....
}

@Configuration
@Import(JdbcConfig.class)
public class SpringConfiguration {
	// ...
}

示例:
使用dbutils需要在pom中指定依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>5.0.2.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>commons-dbutils</groupId>
        <artifactId>commons-dbutils</artifactId>
        <version>1.4</version>
    </dependency>
    <dependency>
        <groupId>com.oracle</groupId>
        <artifactId>ojdbc6</artifactId>
        <version>12.1.0.1-atlassian-hosted</version>
    </dependency>
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
</dependencies>

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"
       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.study"></context:component-scan>

    <!-- QueryRunner配置成多例模式,保证每次使用的都是重新创建的。避免相互干扰 -->
    <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="oracle.jdbc.driver.OracleDriver">
        </property>
        <property name="jdbcUrl" value="jdbc:oracle:thin:@127.0.0.1:1521/orcl">
        </property>
        <property name="user" value="springtest"></property>
        <property name="password" value="tiger"></property>
    </bean>
</beans>

改成java配置类的形式:

@Configuration
@ComponentScan("com.study")
public class SpringConfiguration {

    @Bean("runner")
    @Scope("prototype")  // Spring容器的bean默认为单例,为避免不同数据库操作之间的干扰,此处应该使用Scope将runner指定为多例
    public QueryRunner createQueryRunner(DataSource dataSource) {
        return new QueryRunner(dataSource);
    }

    @Bean("dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setDriverClass("oracle.jdbc.driver.OracleDriver");
            dataSource.setJdbcUrl("jdbc:oracle:thin:@127.0.0.1:1521/orcl");
            dataSource.setUser("springtest");
            dataSource.setPassword("tiger");
            return dataSource;
        } catch (PropertyVetoException e) {
            throw new RuntimeException(e);
        }
    }
}

将main方法由读取xml配置改为读取配置类的配置:

    @Test
    public void testFindAll(){
        // 读取配置类中的配置(如果有多个配置类,也可以传入多个配置类)
        ApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfiguration.class);
        IAccountService as = ac.getBean("accountService", IAccountService.class);
        as.findAllAccount().forEach(System.out::println);
    }

3.7、从properties配置文件中获取配置

将jdbc的相关信息配置在properties配置文件中。
在SpringConfig.java中声明properties文件的位置。
在JdbcConfig.java中获取properties中配置的信息。

如果使用xml配置,则用<context:property-placeholder location="classpath:person.properties">配置

  • @PropertySource
    作用:用于指定properties配置文件的位置。
    属性:value:指定文件的名称和路径。value中需要使用classpath关键字声明该配置文件位于class路径的resources文件夹中。如果properties文件位于包里,可以带上包名(value = "classpath:com/study/jdbcConfig.properties")。

编写jdbcConfig.properties配置文件:

jdbc.driver=oracle.jdbc.driver.OracleDriver
jdbc.url=jdbc:oracle:thin:@127.0.0.1:1521/orcl
jdbc.username=springtest
jdbc.password=tiger

在SpringConfig.java中配置properties文件的位置:

@Configuration
@ComponentScan({"com.study","com.config"})
@PropertySource("classpath:jdbcConfig.properties")
public class SpringConfiguration {

}

在JdbcConfig.java中获取properties文件中的配置信息

@Configuration
public class JdbcConfig {

    @Value("${jdbc.driver}")
    private String jdbcDriver;
    @Value("${jdbc.url}")
    private String jdbcUrl;
    @Value("${jdbc.username}")
    private String jdbcUser;
    @Value("${jdbc.password}")
    private String jdbcPassword;

    @Bean("dataSource")
    public DataSource createDataSource() {
        try {
            ComboPooledDataSource dataSource = new ComboPooledDataSource();
            dataSource.setDriverClass(jdbcDriver);
            dataSource.setJdbcUrl(jdbcUrl);
            dataSource.setUser(jdbcUser);
            dataSource.setPassword(jdbcPassword);
            return dataSource;
        } catch (PropertyVetoException e) {
            throw new RuntimeException(e);
        }
    }
}

4、动态代理分析

4.1、为service层的QueryRunner添加事务支持

4.2、基于接口的动态代理

4.3、基于子类的动态代理

4.4、使用动态代理重构带有事务的service示例

5、Spring的AOP

5.1、基于接口的动态代理

5.2、AOP的相关概念

5.3、基于xml的aop配置示例

5.4、spring四种通知(不含环绕通知)的xml配置

5.5、xml中通用化切入点表达式配置

5.6、xml中环绕通知的配置和写法

5.7、基于注解的AOP配置

6、Spring中的JdbcTemplate

6.1、JdbcTemplate概述

6.2、JdbcTemplate的CRUD操作

6.2.1、使用IoC管理JdbcTemplate

6.2.2、新增

6.2.3、更新

6.2.4、删除

6.2.5、查询获取List

6.2.6、查询一个

6.2.7、查询一个值(聚合函数)

6.3、编写JdbcDaoSupport去除dao层重复代码

7、Spring的声明式事务控制

7.1、Spring中的事务控制API

7.1.1、PlatformTransactionManager

7.1.2、TransactionDefinition

7.1.3、TransactionStatus

7.2、基于xml的声明式事务配置

7.3、基于注解的声明式事务配置

7.4、纯注解配置的声明式事务配置

8、Spring的编程式事务控制

9、Spring如何在web应用中使用

9.1、需要额外导入的jar包

9.2、配置文件

9.3、如何创建IOC容器

9.4、示例代码

9.5、Spring提供的Listener

转载于尚硅谷:https://www.yuque.com/tmfl/spring/of3mbz#3e4ec32a

标签:xml,容器,spring,配置,基础,class,bean,public
From: https://www.cnblogs.com/cc-boy/p/17006340.html

相关文章

  • VueX基础篇
    1.VueX是什么:“Vuex是一个专为Vue.js应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。”......
  • Linux基础二
    目录1.文件命名规则2.Linux常用命令(续)3.文件层级系统4.重定向与管道5.bash字符串处理1.文件命名规则长度不能超过255个字符;不能使用/当文件名;严格区分大小写......
  • Linux基础一
    目录1.Linux基本原则2.bash特性2.1shell2.2bash特性2.2.1bash支持的引号2.2.2bash常用操作3.命令3.1命令格式3.2命令类型3.3基础命令3.4如何获取命令帮助1.L......
  • 【UE官方培训】(四)UE光影基础
                                                         ......
  • Python基础 | 01 走进Python的世界
    导读“人生苦短,我用Python”,Python语言越发火热,科技飞速发展的现在,何不使用Python快速解决问题。本篇文章,让我们一起来了解什么是Python,Python有哪些优缺点?Python作为解释......
  • spring-boot前端参数单位转换
     importjava.text.ParseException;importjava.text.SimpleDateFormat;importjava.util.Date;importjava.util.Locale;publicclassOldFormat{publicstaticvoid......
  • java基础学习
    数据类型强类型语言要求变量的使用要严格符合规定,所有变量必须先定义再使用java基本数据类型基本类型(primitivetype)数值类型整型byte,short,int,long;......
  • Spring JDBC
    SpringJDBC  *Spring框架对JDBC的简单封装。提供了JDBCTemplate对象简化JDBC的开发    1.导入jar包(下载地址MavenRepository:Spring-tx(mvnrepository.com)) ......
  • 每天一点基础K8S--K8S中的daemonset
    daemonset1、背景有时需要在集群中的所有node上运行一个pod的副本。当有节点加入集群时,也会为他们新增一个Pod。当有节点从集群移除时,这些Pod也会被回收。删除Dae......
  • elasticsearch基础入门
    本文由简悦SimpRead转码,原文地址blog.csdn.net小伙伴们,你们好呀,我是老寇,跟我一起学习es7.6.2注:请点击我,获取源码目录一、引入依赖配置pom.xml二、配置app......