Spring学习

目录

一、spring文件及注解

1、spring配置主要全部文件

Spring学习笔记_数据源

pom.xml

 	 <dependencies>
        <!--————————————————添加Spring依赖支持————————————————-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-core</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-beans</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-web</artifactId>
            <version>5.3.7</version>
        </dependency>
        <!--————————————————添加Spring测试支持————————————————-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version>5.3.7</version>
        </dependency>
        <!--————————————————添加Spring-MVC视图表现层支持————————————————-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.3.7</version>
        </dependency>
        <!--————————————————添加Spring 数据库事务管理支持————————————————-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.3.7</version>
        </dependency>
        <!--————————————————添加Spring-aop面向切面编程支持————————————————-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aop</artifactId>
            <version>5.3.7</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-aspects</artifactId>
            <version>5.3.7</version>
        </dependency>
    </dependencies>

applicationContext.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:mvc="http://www.springframework.org/schema/mvc"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
		http://www.springframework.org/schema/mvc
		http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd
		http://www.springframework.org/schema/context
		http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx
		http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">


    <bean id="userDao"  class="com.remli.dao.impl.UserDaoImpl"></bean>

    
</beans>

Main.java

    public static void main(String[] args) {
        /*解析application.xml配置文件获取Bean实例(对象)*/
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        /*对象获取并强制转换类型*/
        UserDao userDao = (UserDao) app.getBean("userDao");
        /*对象调用方法*/
        userDao.save();
    }
    
        /*获取文件流*/
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        /*接口*/                      /*接口实现*/

        /*获取对象*/                /*强转对象*/
        UserService userService = (UserService) app.getBean("userService");

        userService.save();

UserDao.java


public interface UserDao {
    /*接口的方法*/
    public void save();
}

UserDaoImpl.java

public class UserDaoImpl implements UserDao {
    /*实现接口的类的方法*/
    public void save() {
        System.out.println("程序启动");
    }
}

2、spring配置主要全部注解

3、Spring重点基础知识

1.名词解释

  1. 类(人类):共同特征的实体的集合、模板、一类事物、抽象、概念、同种属性

实例:一个真实的对象

对象(个人):组成类的元素、类的具体实现、实际执行者

属性:数据(变量/值)

定义:编译器创建对象、分配内存、取名(变量名/对象名)

声明:声明对象(对象名/对象类型)、告知编译器对象/属性的情况

实例化:类创建对象的过程

初始化:为变量分配内存空间、并确定其初始值的过程

构造方法:与类同名的特殊方法、创建对象

构造器:与类同名的特殊方法、创建对象

2.Bean生命周期:1实例化、2属性赋值、3初始化、4使用、5销毁

  1. 实例化前阶段:执行Instantiation Aware Bean PostProcessor Adapter的post Process Before ln station方法

执行Instantiation Aware Bean PostProcessor Adapter的determine Candidate Constructors方法

接口Merged Bean Definition PostProcessor的post Process Merged Bean Definition方法

实例化Bean(执行Bean构造方法)

实例化后阶段:执行Instantiation Aware Bean PostProcessor Adapter的post Process After In station方法。方法返回false的时候, 后续的Bean属性赋值前处理、Bean属性赋值都会被跳过了,

属性赋值前阶段(可在此修改属性的值):执行Instantiation Aware Bean PostProcessor的post Process Properties方法。返回空的时候, 表示这个bean不需要设置属性, 直接返回了, 直接进入下一个阶段。

属性赋值(Populate)

Aware接口

执行Instantiation Aware Bean PostProcessor Adapte的post Process Before ln it i alization方法

自定义初始化方法

执行Instantiation Aware Bean PostProcessor Adapte的post Process After ln it i alization方法

容器创建成功,提供使用

调用自定义销毁方法方法

3.Bean 标签属性

  1. id 属性:唯一性、不可重复
    属性值任意命名,但不可以包含中文以及特殊字符。
    根据 id 属性值得到配置对象。

  2. class 属性:类的全路径名称
    创建对象所在类的全路径名称。

  3. name 属性:不可重复
    功能和 id 一致。已基本不用。
    区别: id 属性值不可以包含特殊字符, name 属性值可以包含。

  4. scope 属性
    bean 作用范围属性值:

取值范围
singleton 单例 默认值、只生成1个实例
prototype 多例 多例的
request WEB项目中, Spring创建一个Bean的对象, 将对象存入到request域中
session WEB项目中, Spring创建一个Bean的对象, 将对象存入到session域中
global session WEB项目中, 应用在Portlet环境, 如果没有Portlet环境那么global Session相当于session
  1. 作用域:scope

     singleton: 单例模式,在整个Spring IoC容器中,singleton作用域的Bean将只生成一个实例。
     prototype: 每次通过容器的getBean()方法获取prototype作用域的Bean时,都将产生一个新的Bean实例。
     request: 对于一次HTTP请求,request作用域的Bean将只生成一个实例,这意味着,在同一次HTTP请求内,程序每次请求该Bean,得到的总是同一个实例。只有在Web应用中使用Spring时,该作用域才真正有效。
     session:该作用域将 bean 的定义限制为 HTTP 会话。 只在web-aware Spring ApplicationContext的上下文中有效。
     global session: 每个全局的HTTP Session对应一个Bean实例。在典型的情况下,仅在使用portlet context的时候有效,同样只在Web应用中有效。
    

4.Spring核心:

  1. Spring容器接口:ApplicationContext

     ClassPathXmlApplicationContext: 从类加载路径下搜索配置文件,并根据配置文件来创建Spring容器。
     FileSystemXmlApplicationContext: 从文件系统的相对路径或绝对路径下去搜索配置文件,并根据配置文件来创建Spring容器。
    

4、bean实例化:无参、工厂静态、工厂实例

1.无参构造方法实例化:默认

    <!--找无参构造方法-->
    <bean id="userDao"  class="com.remli.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy" scope="prototype"></bean>

/*重写无参构造——修改默认构造方法——对应接口*/
public UserDaoImpl(){
    System.out.println("无参构造修改:UserDaoImpl对象创建...");
}

2.工厂静态方法实例化:直接调用方法

 	<!--找全包名对应内部指定的方法、去返回对应的对象-->
    <bean id="userDao1"  class="com.remli.factory.StaticFactory" scope="prototype" factory-method="getUserDao"></bean>
public class StaticFactory {
    /*对象工厂——对象创建——返回对象*/
    public static UserDao getUserDao() {
        /*返回对象*/
        return new UserDaoImpl();
    }
}

3.工厂实例方法实例化:先有工厂对象再调方法

 	<!--先创建工厂对象-->
    <bean id="factory"  class="com.remli.factory.DynamicFactory" scope="prototype" ></bean>
    <!--从容器当中工厂对象内部的方法获取指定返回的对象-->
    <bean id="userDao2"  factory-bean="factory" factory-method="getUserDao"></bean>
public class DynamicFactory {
    /*对象工厂*/
    public UserDao getUserDao() {
        /*返回对象*/
        return new UserDaoImpl();
    }
}

5、依赖注入DI:注入类型:对象、普通数据、集合数据

1.构造方法注入:有参构造

    <bean id="userService"  class="com.remli.service.impl.UserServiceImpl">
                    <!--参数名-->            <!---->
        <constructor-arg name="userDao" ref="userDao"></constructor-arg>
    </bean>
    public UserServiceImpl(UserDao userDao) {/*有参构造*/
        this.userDao = userDao;
    }

2.set方法注入:

    <!--找无参构造方法-->
    <bean id="userDao"  class="com.remli.dao.impl.UserDaoImpl" init-method="init" destroy-method="destroy" scope="prototype"></bean>

    <!--set依赖注入-->
    <bean id="userService"  class="com.remli.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
    </bean>
    private UserDao userDao;
    public void setUserDao(UserDao userDao) {
        this.userDao = userDao;
    }

    public void save() {
        userDao.save();
    }

3.p命名空间注入:(本质set)

1引入p命名空间:

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

2修改注入方式:

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

6、依赖注入类型:引用数据(对象)、普通数据、集合数据

1.普通数据

    private String username;
    private int age;


    public void setUsername(String username) {
        this.username = username;
    }

    public void setAge(int age) {
        this.age = age;
    }
    <bean id="userDao11"  class="com.remli.dao.impl.UserDaoImpl" >
        <!--属性注入-->
        <property name="username" value="注意空格"/>
        <property name="age" value="2021825"/>
    </bean>
        /*获取文件流*/
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        /*接口*/      /*接口实现*/
        UserDao ud = (UserDao) app.getBean("userDao11");
       /*获取对象*/  /*强转对象*/
       
        Object ud1 = app.getBean("userDao11");
        
        ud.save();

2.引用数据

3.集合数据

	/*定义变量、构造方法*/
    private List<String> strList;
    private Map<String , User> userMap;
    private Properties properties;

    public void setStrList(List<String> strList) {
        this.strList = strList;
    }

    public void setUserMap(Map<String, User> userMap) {
        this.userMap = userMap;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }


   	/*实现接口的类的方法*/
    public void save() {
        System.out.println(strList);
        System.out.println(userMap);
        System.out.println(properties);
    }

    private String name;
    private String addr;

    public String getName() {
        return name;
    }

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

    public String getAddr() {
        return addr;
    }

    public void setAddr(String addr) {
        this.addr = addr;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", addr='" + addr + '\'' +
                '}';
    }
    <bean id="userDao222"  class="com.remli.dao.impl.UserDaoImpl" >
        <!--属性注入-->
        <property name="strList">
            <list>
                <value>任</value>
                <value>明</value>
                <value>任</value>
            </list>
        </property>
        <property name="userMap">
            <map><!--key value-->
                <entry key="key1" value-ref="user11"> </entry>
                <entry key="key2" value-ref="user22"> </entry>
            </map>
        </property>
        <property name="properties">
            <props>
                <prop key="1">111</prop>
                <prop key="2">1112</prop>
                <prop key="3">1113</prop>
            </props>
        </property>
    </bean>

    <bean id="user11" class="com.remli.domain.User">
        <property name="name" value="我是"></property>
        <property name="addr" value="中国"></property>
    </bean>
    <bean id="user22" class="com.remli.domain.User">
        <property name="name" value="我是1"></property>
        <property name="addr" value="中国1"></property>
    </bean>
        /*获取文件流*/
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        /*接口*/      /*接口实现*/
        UserDao u2= (UserDao) app.getBean("userDao222");
       /*获取对象*/  /*强转对象*/
       
        Object d2 = app.getBean("userDao222");

        u2.save();
三、引入其他配置文件(分模块开发)

实际开发中,Spring的配置内容非常多,这导致Spring配置很繁杂,使用可以拆分到其它配置文件当
中,而且Spring主配置文件通过import标签加载

1、< import >标签

  <!--主配置文件——引入分模块文件-->
    <import resource="applicationContext-user.xml"></import>
applicationContext.xml
applicationContext-product.xml
applicationContext-user.xml
四、Spring的重点配置

1、< property >标签:属性注入、setter()

property:通过setter对应的方法注入。

<property>标签:属性注入
	name属性:属性名称
	value属性:注入的普通属性值
	ref属性:注入的对象引用值
	<list>标签
	<map>标签
	<properties>标签

1. name属性:属性名称

1. value属性:注入的普通属性值

1. ref属性:注入的对象引用值

1. < set >标签:集合——引用ref

<!-- 给set注入值 不能有相同的对象 -->
<property name="empSets">
	<set>
		<ref bean="emp1" />
		<ref bean="emp2"/>
	</set>
</property>

1. < list >标签:集合——引用ref

<!-- 给list注入值 可以有相同的多个对象 -->
	   <property name="strList">
	      <list>
	            <value>人</value>
	            <value>民</value>
	            <value>人</value>
	       </list>
	   </property>

1. < map >标签:集合——键值对

<!-- 给map注入值 只要map中的key值不一样就可以装配value -->
        <property name="userMap">
            <map><!--key value-->
                <entry key="key1" value-ref="user11"> </entry>
                <entry key="key2" value-ref="user22"> </entry>
            </map>
        </property>

1. < properties >标签:与map类似——键值对

        <property name="properties">
            <props>
                <prop key="1">111</prop>
                <prop key="2">1112</prop>
                <prop key="3">1113</prop>
            </props>
        </property>

2、< constructor-arg >标签:指定构造函数的参数注入

constructor-arg:通过构造函数注入。

    <!--找无参构造方法-->
    <bean id="userDao"  class="com.remli.dao.impl.UserDaoImpl">
    </bean>
    <bean id="userService"  class="com.remli.service.impl.UserServiceImpl">
                    <!--参数名-->            <!---->
        <constructor-arg name="userDao" ref="userDao"></constructor-arg>
    </bean>

constructor-arg属性通过指定type 类型来调用对应的构造函数,


    <constructor-arg name="id" value="1"/>
    
    <constructor-arg name="name" value="student"/>
    
    <constructor-arg name="dream">
        <list>
            <value>soldier</value>
            <value>scientist</value>
            <value>pilot</value>
        </list>
    </constructor-arg>
    
    <constructor-arg name="score">
        <map>
            <entry key="math" value="90"/>
            <entry key="english" value="85"/>
        </map>
    </constructor-arg>

五、SpringAPI

1、ApplicationContext的继承

applicationContext:接口类型,代表应用上下文,可通过其实例获得Spring容器中的Bean对象。

2、ApplicationContext的实现类

1.ClassPathXmlApplicationContext:类 路径 文件类型 应用 上下文——resource下文件(相对)

它是从类的根路径下加载配置文件(常用)
        /*获取文件流*/
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
        /*接口*/                      /*接口实现*/

2.FileSystemXmlApplicationContext:文件 系统 文件类型 应用 上下文——磁盘绝对路径

它是从磁盘路径上加载配置文件,配置文件可以在磁盘的任何位置。
ApplicationContext appp = new FileSystemXmlApplicationContext("C:\\Users\\REMLI\\IdeaProjects\\REM_SSMS\\src\\main\\resources\\applicationContext.xml");

3.AnnotationConfigApplicationContext:注解 配置 应用 上下文——注解开发

当使用注解配置容器对象时,需要使用此类来创建Spring容器。它用来读取注解。

3、getBean()方法的使用

1.强转类型

一个是通过id来获取:某一个类型可存在多个,获取后需要强转。
        UserDao u111= (UserDao) appp.getBean("userDao222");

2.直接获取类对象:类文件直接指定

一个通过返回值来获取:一种类型只能有一个,获取后不需要强转。
        UserDao userDao = app.getBean(UserDao.class);

3.通过java对象获取

        Object d111 = appp.getBean("userDao222");
六、配置数据源

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

1.提高程序性能

2.事先实例化数据源、初始化部分连接资

3.使用连接资源时从数据源中获取

4.使用完毕后将连接资源归还给数据源

常见数据源:DBCP,C3P0,BoneCP、Druid等

2 、引入相关坐标依赖

<dependencies>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context-support</artifactId>
        <version>5.3.7</version>
    </dependency>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <version>8.0.19</version>
    </dependency>
    <!--添加Druid依赖-->
    <dependency>
        <groupId>com.alibaba</groupId>
        <artifactId>druid</artifactId>
        <version>1.1.10</version>
    </dependency>
    <dependency>
        <groupId>c3p0</groupId>
        <artifactId>c3p0</artifactId>
        <version>0.9.1.2</version>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
    </dependency>
</dependencies>

3、手动创建C3P0数据源:一定要注意空格、注意名称正确

    @Test
    /*测试手动创建c3p0数据源*/
    public void test1() throws Exception {
        /*创建数据源*/
        /*康波坡尔*/
        /*注意一个问题保证mysql语句的正确、Mysql 8.0.19和以前版本连接语句略微不同*/
        /*实例化对象*/
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        /*对象调用方法——并set方法赋值*/
        /*赋值驱动类数据库连接信息*/
        dataSource.setDriverClass("com.mysql.cj.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/remli?useSSL=false&serverTimezone=UTC");
        dataSource.setUser("root");
        dataSource.setPassword("2020");
        
        /*创建对象获取连接信息*/
        Connection connection = dataSource.getConnection();
        
        /*打印对象信息*/
        System.out.println("\n地址:"+connection);
        
        /*连接关闭、归还资源*/
        connection.close();

    }

4、手动创建Druid数据源:一定要注意空格、注意名称正确

    @Test
    /*测试手动创建druid数据源*/
    /*如果找不到DruidDataSource请在maven里清理clean里面的jar包*/
    public void test2() throws Exception {
        /*创建数据源*/
        /*注意一个问题保证mysql语句的正确、Mysql 8.0.19和以前版本连接语句略微不同*/
        /*实例化对象*/
        DruidDataSource dataSource = new DruidDataSource();
        
        /*对象调用方法——并set方法赋值*/
        /*赋值驱动类数据库连接信息*/
        dataSource.setDriverClassName("com.mysql.cj.jdbc.Driver");/*存在耦合*/
        dataSource.setUrl("jdbc:mysql://localhost:3306/remli?useSSL=false&serverTimezone=UTC");/*存在耦合*/
        dataSource.setUsername("root");/*存在耦合*/
        dataSource.setPassword("2020");/*存在耦合*/
        
        /*创建对象获取连接信息*/
        DruidPooledConnection connection = dataSource.getConnection();
       
        /*打印对象信息*/
        System.out.println(connection);
        
        /*连接关闭、归还资源*/
        connection.close();
    }

5、手建C3P0(加载properties配置文件):注意空格、名称正确

1.创建代码:

    @Test
    /*测试手动创建c3p0数据源(加载properties配置文件)*/
    public void test3() throws Exception {
    
        /*读取配置文件*/
        ResourceBundle rb = ResourceBundle.getBundle("jdbc");
        String driver = rb.getString("jdbc.driver");
        String url = rb.getString("jdbc.url");
        String username = rb.getString("jdbc.username");
        String password = rb.getString("jdbc.password");

        /*创建数据源对象、设置连接参数*/
        /*康波坡尔*/
        /*注意一个问题保证mysql语句的正确、Mysql 8.0.19和以前版本连接语句略微不同*/
        /*实例化对象*/
        ComboPooledDataSource dataSource = new ComboPooledDataSource();

        /*对象调用方法——并set方法赋值*/
        /*赋值驱动类数据库连接信息*/
        /*注意值不能加双引号*/
        dataSource.setDriverClass(driver);
        dataSource.setJdbcUrl(url);
        dataSource.setUser(username);
        dataSource.setPassword(password);

        /*创建对象获取连接信息*/
        Connection connection = dataSource.getConnection();

        /*打印对象信息*/
        System.out.println("\n地址:"+connection);

        /*连接关闭、归还资源*/
        connection.close();

    }

2.配置文件jdbc.properties:注意语句正确、空格、名称

jdbc.driver=com.mysql.cj.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/remli?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=2020
七、Spring配置数据源:DataSource——.set方法注入
将DataSource创建权——交给Spring容器完成
DataSource有无参构造方法——Spring默认通过无参构造方法实例化对象
使用DataSource获取数据库的连接对象——需通过set方法设置数据库连接信息——Spring可通过set方法进行字符串注入

1、application配置文件:配置连接信息——com.mchange.v2.c3p0.ComboPooledDataSource

1.注意一个问题:&会报错——写成&amp

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--set方法注入参数-->
		<!--这里的名称是java里面的首字母小写-->
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/remli?useSSL=false&amp;serverTimezone=UTC"></property>
        <property name="user" value="root"></property>
        <property name="password" value="2020"></property>
    </bean>

2、代替ComboPooledDataSource——>ClassPathXmlApplicationContext

    @Test
    /*测试Spring容器产生数据源对象(加载application.xml配置文件)*/
    public void test4() throws Exception {
        /*读取配置文件*/
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        /*创建数据源对象、设置连接参数*/
        /*实例化对象*/
        DataSource dataSource4 = app.getBean(DataSource.class);

        /*创建对象获取连接信息*/
        Connection connection4 = dataSource4.getConnection();

        /*打印对象信息*/
        System.out.println("\n地址:"+connection4);

        /*连接关闭、归还资源*/
        connection4.close();

    }
八、Spring单独配置数据源:xml加载properties文件——分开数据库与Spring
properties的键值对写法需要注意不要有键名相同!!!
各自的数据库——加载——对应properties文件

1、spring加载properties文件步骤:

1.引入context命名空间和约束路径:

applicationContext.xml加载jdbc.properties配置文件——获得连接信息
首先引入context命名空间和约束路径:

1命名空间:xmlns:context="http://www.springframework.org/schema/context"

context命名空间中有组件扫描和加载外部.properties文件的标签
加载到IOC中的.properties文件可以通过spring el表达式获取,格式为:${键名}

<context:component-scan />:配置组件扫描,可以扫描指定包下的注解
<context:property-placeholder />:加载外部的.properties文件到spring容器当中,
可以通过spel,即${}获取到值,例如配置数据库连接参数
       xmlns:context="http://www.springframework.org/schema/context"

2约束路径:http://www.springframework.org/schema/context

约束路径1:http://www.springframework.org/schema/context                      
约束路径2:http://www.springframework.org/schema/context/spring-context.xsd

spring启动时需验证xml文档,约束的作用就是来验证配置文件的xml文档语法的正确性。
		http://www.springframework.org/schema/context/spring-context.xsd

2.加载配置文件标签:< context:property-placeholder location="xx.properties"/ >

<context:property-placeholder />:加载外部的.properties文件到spring容器当中,
可以通过spel,即${}获取到值,例如配置数据库连接参数
    <!--加载外部properties配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

3.< property name="" value="${key}"/ >:spr语言——EL

获取key值——获取properties对应名称值

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--set方法注入参数-->
        <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>

4.DataSource.class

    <!--解耦合-->
    <!--这个地方可以更换数据源-->
    <!--加载外部properties配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <!--set方法注入参数-->
        <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>
    @Test
    /*测试Spring容器产生数据源对象(加载application.xml配置文件)*/
    public void test4() throws Exception {
        /*读取配置文件*/
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        /*创建数据源对象、设置连接参数*/
        /*实例化对象*/
        DataSource dataSource4 = app.getBean(DataSource.class);

        /*创建对象获取连接信息*/
        Connection connection4 = dataSource4.getConnection();

        /*打印对象信息*/
        System.out.println("\n地址4:"+connection4);

        /*连接关闭、归还资源*/
        connection4.close();

    }

5.DruidDataSource.class

    <!--解耦合-->
    <!--这个地方可以更换数据源-->
    <!--加载外部properties配置文件-->
    <context:property-placeholder location="classpath:jdbc.properties"/>

    <bean id="druidDataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <!--set方法注入参数-->
        <property name="driverClassName" value="${jdbc.driver}"/>
        <property name="url" value="${jdbc.url}" />
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>
    @Test
    /*测试Spring容器产生数据源对象(加载application.xml配置文件)*/
    public void test5() throws Exception {
        /*读取配置文件*/
        ApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");

        /*创建数据源对象、设置连接参数*/
        /*实例化对象*/
        DruidDataSource dr = app.getBean(DruidDataSource.class);

        /*创建对象获取连接信息*/
        Connection connection5 = dr.getConnection();

        /*打印对象信息*/
        System.out.println("\n地址5:"+connection5);

        /*连接关闭、归还资源*/
        connection5.close();

    }
2者不能同时开启、会相互报错

总结:命名空间修改方法,赋值xmlns后的url,将beans改为context,然后建立新的xmlns:context。
复制前一段xsi:schemaLocation将所有的beans都改为context添加在后面。
引入文件路径,classpath表示class文件路径,resource文件默认保存在classpath文件下,
所以路径为"classpath:jdbc.properties"。
在xml中调用properties文件,使用EL表达式。

问题记录:
	导入properties后,Druid报错:
		[create connection SQLException, 
		url:jdbc:mysql://localhost:3306/demo, errorCode 1045, state 28000]

错误原因:properties配置文件中的名字与Driud属性名冲突。

修改前:
	driver=com.mysql.cj.jdbc.Driver
	url=jdbc:mysql://localhost:3306/remli?useSSL=false&serverTimezone=UTC
	username=root
	password=2020

修改后:
	jdbc.driver=com.mysql.cj.jdbc.Driver
	jdbc.url=jdbc:mysql://localhost:3306/remli?useSSL=false&serverTimezone=UTC
	jdbc.username=root
	jdbc.password=2020
九、Spring注解开发
语义化:见名知意

1、 Spring原始注解

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

@Component——id——实例化——随便那个——无语义

使用在类上用于实例化Bean
该组件用于Spring生成一个bean——>Component:组件
Component:组件 ByID
@Component("userDao")/*相当于配置文件id、定位类*/
@Component("userService")/*相当于配置文件id、定位类*/

@Controller——Web层控制类实例化——语义化

使用在web层类上用于实例化Bean
该控制器用于Spring生成一个bean

@Service——Service层服务类实例化——语义化

使用在service层类上用于实例化Bean
该业务逻辑类用于Spring生成一个bean
@Service("userService")/*相当于配置文件id、定位类*/

@Repository——id——Dao层数据存储类实例化——语义化

使用在dao层类上用于实例化Bean
该Dao类用于Spring生成一个bean——>repository:贮藏室 数据封装基地
Repository:贮藏室 ByID
@Repository("userDao")/*相当于配置文件id、定位类*/
@Controller
@Service
@Repository
@Component
4者无本质区别
他们存在是为区分开web、service、dao层
方便代码阅读。

@Autowired——无需Setter——字段按类型注入——可单独使用

类型
使用在字段上用于根据类型依赖注入
作用:自动封装该属性、或者字段
可不用Setter方法接收

单个类:独自使用
    @Autowired
    //单个使用——按照数据类型从Spring容器中匹配进行注入、注意单个数据类可以、多个就识别确定不了
结合@Qualifier使用:
    @Autowired
    	//单个使用——按照数据类型从Spring容器中匹配进行注入、
    	//注意单个数据类可以、多个就识别确定不了
    @Qualifier("userDao")
		//按照id从容器中进行匹配
		//但是此处需要结合@Autowired一起使用

@Qualifier——name/id——@Autowired+按名称注入——必须配合使用

id+name
结合@Autowired一起使用用于根据名称进行依赖注入
根据提供的修饰语 @Qualifier('xxx')——>匹配该xxx属性,
使用该注解,必须配合AutoWire一起使用,
Qualifier:修饰语 ByName
	@Autowire 
	@Qualifier("user") 
	意义:封装user注解的bean为本类对象的成员,根据名称注入 ByName,设置在字段上. 

	@Qualifier常用在参数赋值上
	如: String getUsername(@Qualifier("user")User user){}


结合@Qualifier使用:
    @Autowired
    	//单个使用——按照数据类型从Spring容器中匹配进行注入、
    	//注意单个数据类可以、多个就识别确定不了
    @Qualifier("userDao")
	    //按照id从容器中进行匹配
   		//但是此处需要结合@Autowired一起使用
    @Autowired
    @Qualifier("userDao")

@Resource——按名称注入=@Autowired+@Qualifier——J2EE提供

相当于@Autowired+@Qualifier, 按照名称进行注入
Resource是Aotuwire注解和Qualifier注解的结合体.@Resource("user"),标注为user的bean

@Resource("user") 封装user注解的bean为奔雷对象的成员 	== 
	@Autowire 
	@Qualifier
	
默认根据名称依赖注入,

默认Resource() = Resource like Resource(name = "XXX")——>体现面向对象思想
应该设置在字段上

可以手动设置为根据类型注入Resource(type = User.class)——>体现面向对象思想
应该设置在set方法上
    @Resource(name="userDao")
    	//相当于 @Autowired+@Qualifier("userDao")

@Value——注入普通属性

注入普通属性
@Value("xxx");为修饰字段赋值;
	通常配合SpEL(Spring Expression Language)使用

@Value("${jdbc.url}") private String url; 为url赋值
	——> (Spring中引入的properties后缀文件中的jdbc.url对应的值) 
	——>或者{PropertySrouce注解中的jdbc.url值}
    @Value("value注入成功")//属性值注入
    private String vals;


    @Value("${jdbc.driver}")//数据库属性值注入
    private String sjk;

@Scope——Bean作用范围

标注Bean的作用范围
常用 : 	@Scope("singleton") 声明从spring容器获得的该类的bean
				有且只有一个(单例模式)
				
		@Scope("prototype") 声明从spring容器获得的该类的bean
				有多个(标准Bean模式)
@Scope("prototype")//多例
//@Scope("singleton")//单例

@PostConstruct——Bean初始化方法——构造后

使用在方法上标注该方法是Bean的初始化方法
注解使用在用户定义的初始化方法前,
声明该方法是该类的初始化方法
@PostConstruct :意为执行在构造方法后,构造方法创建对象,对象调用该初始化方法
    @PostConstruct
    public void init(){
        System.out.println("Service对象初始化方法");
    }

@PreDestroy——Bean销毁方法——销毁前

使用在方法上标注该方法是Bean的销毁方法
注解使用在用户自定义的结束方法前,
声明该方法是该类的结束方法,
当前对象被销毁前调用该方法
@PreDestroy ;Spring容器被销毁的时候,执行.
   @PreDestroy
    public void destory(){
        System.out.println("Service对象销毁方法");
//        /*读取配置文件*/
//        /*子类实现销毁方法——手动关闭*/
//        ClassPathXmlApplicationContext apps = new ClassPathXmlApplicationContext("applicationContext.xml");
//
//        /*创建数据源对象、设置连接参数*/
//        /*实例化对象*/
//        XXX drs = app.getBean(XXX.class);
//
//        /*手动关闭*/
//        drs.close();
    }

@Order——注入对象引用集合

注入对象引用的集合的时候使用:
@Order(1) 
@Order(2) 表示该类生成的bean将会存储在某个List<该类型>中,并按照顺序插入List

如果是Map<String,T> 那么order的顺序没有任何关系,
但是该Map必须定义为<String,T> String接收对应对象的id值(id唯一 ——> key唯一);

此处的List和Map可以通过@Autowired或@Resource注入;

2、组件扫描:component-scan

注意:注解开发时需在applicationContext.xml中配置组件扫描
作用::指定哪一个包及其包下的Bean需要扫描以便识别使用注解配置的类和方法
包:基础包+包括里面的子包
    <!--注解开发——需要配置组件扫描-->
    <!--组件扫描——扫描指定文件夹下的包-->
    <context:component-scan base-package="com.remli"/>

3、2种配置/注解方式对比:

1.原始xml配置方式

    <!--xml配置-->
    <bean id="userDao" class="com.remli.dao.impl.UserDaoImpl"></bean>
	
    <bean id="userService" class="com.remli.service.impl.UserServiceImpl">
        <property name="userDao" ref="userDao"></property>
     </bean>
public interface UserDao {
    public void start();
}
public class UserDaoImpl implements UserDao {
    public void start(){
        System.out.println("启动程序1·····");
    }
}
public interface UserService {
    public void start();
}
public class UserServiceImpl implements UserService {

    private UserDao userDao;

    /*Setter方法*/
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }
    
    public void start(){
        System.out.println("程序启动2·····");
    }
}
public class UserController {

    public static void main(String[] args) {

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

        UserService userService = app.getBean(UserService.class);

        userService.start();
    }

}

2.注解@方式!!!

    <!--注解开发——需要配置组件扫描-->
    <!--组件扫描——扫描指定文件夹下的包-->
    <context:component-scan base-package="com.remli"/>

public interface UserDao {
    public void start();
}
/*xml配置定位类文件位置*/
/*
<bean id="userDao" class="com.remli.dao.impl.UserDaoImpl"></bean>
*/

/*注解*/
/*
@component
*/

@Component("userDao")/*相当于配置文件id、定位类*/
public class UserDaoImpl implements UserDao {
    public void start(){
        System.out.println("启动程序1·····");
    }
}
public interface UserService {
    public void start();
}
/*xml配置定位类文件位置*/
/*
<bean id="userService" class="com.remli.service.impl.UserServiceImpl"></bean>
*/


/*注解*/
/*
@component
*/

@Component("userService")/*相当于配置文件id、定位类*/
public class UserServiceImpl implements UserService {

    /*xml配置注入属性*/
    /*
    <property name="userDao" ref="userDao"></property>
    */

    /*注解——注入*/
    /*
    @Autowired
    @Qualifier("userDao")
    */

    @Autowired
    @Qualifier("userDao")
    private UserDao userDao;

    /*Setter方法*/
    public void setUserDao(UserDao userDao){
        this.userDao=userDao;
    }

    public void start(){
        System.out.println("程序启动2·····");
    }
}
public class UserController {

    public static void main(String[] args) {

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

        UserService userService = app.getBean(UserService.class);

        userService.start();
    }

}

2、Spring新注解

@Configuration——指定类为Spring配置类

用于指定当前类是一个Spring配置类,当创建容器时会从该类上加载注解

@ComponentScan——指定Spring初始化容器扫描包

用于指定Spring在初始化容器时要扫描的包
作用和在Spring的xml配置文件中的

<context:component-scan base-package=”com.code_g”/>一样

ComponentScan:组件扫描 ByPackage ComponentScan:在使用全注解的时候,非常重要.如果未配置,那么Spring的IoC容器默认不会扫描任何包,就不会有任何Bean.

@Bean——方法返回值存储到Spring容器中

使用在方法上,标注将该方法的返回值存储到Spring容器中

@PropertySource——加载properties文件配置

用于加载.properties文件中的配置

@Import——导入其他类配置

用于导入其他配置类

3、Spring对象创建——实例化——找到类创建对象——所在位置

@Component——随便

定义Bean, 不好归类时使用

@Controller——web视图控制层

@Controller("Bean的名称")
定义控制层Bean,如Action

@Service——Service业务服务层

@Service("Bean的名称")
定义业务层Bean

@Repository——Dao数据持久化层

@Repository("Bean的名称")
定义DAO层Bean

4、Spring注入

1.对象注入:依据、bean(id)=name、类、属性注入

@Resource:默认按名称byName注入——(J2EE提供注解)——需添加其依赖

Spring将@Resource注解的name属性解析为bean的名字,而type属性则解析为bean的类型。
默认是按照名称来装配注入的,只有当找不到与名称匹配的bean才会按照类型来注入。
它有两个属性是比较重要的:
如果想减少对 Spring 的依赖建议使用 @Resource 方法。
	<!--Resource注解依赖-->
    <!-- https://mvnrepository.com/artifact/javax.annotation/javax.annotation-api -->
    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>javax.annotation-api</artifactId>
        <version>1.3.2</version>
    </dependency>
    <!-- Javax Annotation -->
    <dependency>
        <groupId>javax.annotation</groupId>
        <artifactId>jsr250-api</artifactId>
        <version>1.0</version>
    </dependency>
1name: Spring 将 name 的属性值解析为 bean 的名称, 使用 byName 的自动注入策略
2type: Spring 将 type的属性值解析为 bean 的类型,使用 byType 的自动注入策略
3反射—— byName 自动注入策略
如果既不指定 name 属性又不指定 type 属性,Spring这时通过反射机制使用 byName 自动注入策略


@Resource 装配顺序:
	如果同时指定了 name 属性和 type 属性,那么 Spring 将从容器中找唯一匹配的 bean 进行装配,找不到则抛出异常
	如果指定了 name 属性值,则从容器中查找名称匹配的 bean 进行装配,找不到则抛出异常
	如果指定了 type 属性值,则从容器中查找类型匹配的唯一的 bean 进行装配,找不到或者找到多个都会抛出异常
	如果都不指定,则会自动按照 byName 方式进行装配, 如果没有匹配,则回退一个原始类型进行匹配,如果匹配则自动装配

@Autowried:默认按类型byType注入

默认是按照类型进行装配注入,
默认情况下,它要求依赖对象必须存在,如果允许 null 值,可以设置它 required 为false。
如果我们想要按名称进行装配的话,可以添加一个 @Qualifier 注解解决。

@Autowired 接口只能有一个实现类,通过byType方式注入
默认情况下必须要求依赖对象必须存在,如果要允许null值,可以设置它的required属性为false,如:@Autowired(required=false)
	@Autowried
	@Qualifier("adminDAO")
	private AdminDAO adminDAO;

@Qualifier:默认类名

spring的注解,按名字注入 一般当出现两个及以上bean时,不知道要注入哪个,作为@Autowired()的修饰用
@Qualifier 接口可以有多个实现类,可以按实现类的类名进行注入

2.普通属性注入:——Value

通常不直接赋值,而是调用引入的properties文件赋值。
只要核心类或者引入的子类引入了properties文件就可以直接用EL表达式。
引入格式为EL表达式

使用@Value将外部值动态的注入到Bean中,使用情况:
	注入普通字符串
	注入操作系统属性
	注入表达式结果
	注入其他Bean属性:注入beanInject对象的属性another
	注入文件资源
	注入URL资源
	@Value("${jdbc.username}")
	private String name;
@Value("normal")
    private String normal; // 注入普通字符串

    @Value("#{systemProperties['os.name']}")
    private String systemPropertiesName; // 注入操作系统属性

    @Value("#{ T(java.lang.Math).random() * 100.0 }")
    private double randomNumber; //注入表达式结果

    @Value("#{beanInject.another}")
    private String fromAnotherBean; // 注入其他Bean属性:注入beanInject对象的属性another,类具体定义见下面

    @Value("classpath:com/hry/spring/configinject/config.txt")
    private Resource resourceFile; // 注入文件资源

    @Value("http://www.baidu.com")
    private Resource testUrl; // 注入URL资源