Spring

  • 简化开发:降低企业级开发的复杂性

  • 框架整合 :高效整合其它技术,提高企业级应用开发与运行效率。

优点:

  • Spring是一个开源的免费的框架

  • Spring是一个轻量级的,非入侵式的框架

  • 控制反转(IOC),面向切面编程(AOP)

  • 支持事务的处理,对框架整合的支持。

    总结:Spring就是一个轻量级的控制反转(IOC)和面向切面(AOP)编程的框架!

核心概念

Core :Ioc 容器

IOC 控制反转

  • 使用对象时,由主动new产生对象转换为由外部提供对象, 此过程中对象创建控制权由程序转移到外部,此思想被称为控制反转。

  • Spring提供了一个容器,称为IoC容器,用来充当IOC思想中的“外部”。

  • IOC容器负责对象的创建,初始化等一系列工作,被创建或者被管理的对象在IOC容器中统称为Bean。

DI 依赖注入

在容器中建立bean与bean之间的依赖关系的整个过过程,称为依赖注入。

**目标:充分解耦

  • 使用IOC管理bean(IOC)

  • 在ioc容器内将有依赖关系的bean进行关系绑定。(DI)

最终效果

*使用对象时不仅可以直接从Ioc容器中获取,并且获取到的bean已经绑定了所有的依赖关系。

 

*XML开发

实例化Bean的三种方式

  • 无参构造方法

  • 静态工厂

    1. 要有创建一个静态工厂。

    2. 配置的话class属性是这个工厂类,还需要指明那个方法(了解)

  • 实例化工厂(了解)

  • beanFactory工厂(实用)

package com.yang.factory;

import com.yang.dao.BookDao;
import com.yang.dao.impl.BookDaoImpl;
import org.springframework.beans.factory.FactoryBean;

public class BookDaoFactoryBean implements FactoryBean<BookDao> {
   @Override
   public BookDao getObject() throws Exception {
       return new BookDaoImpl();
  }

   @Override
   public Class<?> getObjectType() {
       return BookDao.class;
  }
}



<bean id ="bookDao1" class="com.yang.factory.BookDaoFactoryBean"/>

 

Bean的生命周期

  • 初始化容器

    1. 创建对象(分配内存)

    2. 执行构造方法

    3. 执行属性注入(set操作)

    4. 执行bean初始化方法

  • 使用bean

    1. 执行业务操作

  • 关闭销毁

    1. 执行bean的销毁方法

    2. 容器关闭前触发bean的销毁

      1. 手动关闭 ConfigurableApplictionContext接口中的close()

      2. 注册钩子 registerShutdownHook()

     

     

依赖注入方式

  • setter 注入

    1. 简单类型

    <?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="userDao" class="com.yang.dao.impl.UserDaoImpl">
           <property name="array">
               <array>
                   <value>100</value>
                   <value>101</value>
                   <value>102</value>
                   <value>103</value>
               </array>
           </property>
           <property name="list">
               <array>
                   <value>woCao</value>
                   <value>woCao1</value>
                   <value>woCao2</value>
                   <value>woCao3</value>
                   <value>woCao3</value>
               </array>
           </property>
           <property name="set">
               <array>
                   <value>woCao</value>
                   <value>woCao1</value>
                   <value>woCao2</value>
                   <value>woCao3</value>
                   <value>woCao3</value>
               </array>
           </property>
           <property name="map">
               <map>
                   <entry key="co" value="1"></entry>
                   <entry key="cd" value="2"></entry>
                   <entry key="cr" value="3"></entry>
               </map>
           </property>
           <property name="pro">
               <props>
                   <prop key="hh">11</prop>
                   <prop key="jj">12</prop>
                   <prop key="kk">13</prop>
               </props>
           </property>
       </bean>
    </beans>

     

    1. 引用类型

    <?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="bookDao" class="com.yang.dao.impl.BookDaoImpl">
           <property name="username" value="zhangSan"/>
           <property name="age" value="100"/>
       </bean>
          <bean id="userDao" class="com.yang.dao.impl.UserDaoImpl"/>

       <bean id="userService" class="com.yang.service.impl.UserServiceImpl">
           <property name="bookDao" ref="bookDao"/>
           <property name="userDao" ref="userDao"/>
       </bean>
    </beans>

     

  • 构造器注入

    1. 简单类型

    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="userDao" class="yang.dao.impl.UserDaoImpl"/>
       
       <!--构造器注入-->
       <!--第一种 name="username" 根据构造器中参数的名字来匹配,耦合度比较高-->
       <!--<bean id="bookDao" class="yang.dao.impl.BookDaoImpl">
           <constructor-arg name="username" value="zhangSan" />
           <constructor-arg name="nums" value="10"/>
       </bean>
       <bean id ="userService" class="yang.service.impl.UserServiceImpl">
           <constructor-arg name="bookDao" ref="bookDao"/>
           <constructor-arg name="userDao" ref="userDao"/>
       </bean>-->
       
       
       <!--第二种:根据构造器中参数的类型来匹配,如果多个类型就不行了-->
       <!--<bean id="bookDao" class="yang.dao.impl.BookDaoImpl">
           <constructor-arg type="java.lang.String" value="zhangSan" />
           <constructor-arg type="int" value="10"/>
       </bean>
       <bean id ="userService" class="yang.service.impl.UserServiceImpl">
           <constructor-arg type="yang.dao.BookDao" ref="bookDao"/>
           <constructor-arg type="yang.dao.UserDao" ref="userDao"/>
       </bean>-->
       <!--第三种,根据构造器中参数的位置来匹配-->
       <bean id="bookDao" class="yang.dao.impl.BookDaoImpl">
           <constructor-arg index="0" value="zhangSan" />
           <constructor-arg index="1" value="10"/>
       </bean>
       <bean id ="userService" class="yang.service.impl.UserServiceImpl">
           <constructor-arg index="0" ref="bookDao"/>
           <constructor-arg index="1" ref="userDao"/>
       </bean>
    </beans>

     

  • 自动装配

<?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">

   <!--autowire="byType" 自动装配用于引用类型装配
                 byType:相同类型的bean的唯一,即class相同
                 byName: 按照名称,属性的名称或者set方法的称-->
   <bean id="bookDao" class="com.yang.dao.impl.BookDaoImpl"/>
   <bean id="userDao" class="com.yang.dao.impl.UserDaoImpl"/>

   <bean id="userService" class="com.yang.service.impl.UserServiceImpl" autowire="byType"/>
</beans>

 

查看类的继承关系

快捷键 ctrl+H

容器类层次结构图

  • BeanFactory 顶层接口

  • ApplicationContext 常用接口

  • CofigurableApplicationContext 提供关闭容器的功能close

  • ClassPathXmlApplicationContext 常用实现类。

 

第三方数据源

applicationContext.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">


   <!--读取配置文件
      1.添加context命名空间-->
   <!--context的添加属性占位符 来加载文件-->
   <!--system-properties-mode="NEVER" 意思是不加载系统属性-->
   <context:property-placeholder location="jdbc.properties" system-properties-mode="NEVER"/>
<!--   <context:property-placeholder location="jdbc.properties,mysql.properties"/>-->
   <!--加载properties的标准格式-->
   <context:property-placeholder location="classpath:*.properties"/>
   <!--根据情况选择-->
   <!--从类路径或jar包中搜索并加载.properties-->
   <context:property-placeholder location="classpath*:*.properties"/>

   <!--配置第三方资源 DruidDataSource-->
   <!--${} 属性占位符-->
   <bean class="com.alibaba.druid.pool.DruidDataSource">
       <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>
   <!--导入c3p0数据源-->
   <!-- <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/spring_db"/>
        <property name="user" value="root"/>
        <property name="password" value="123456"/>
    </bean>-->
   <bean id="userDao" class="com.yang.dao.impl.UserDaoImpl">
       <property name="name" value="${jdbc.driver}"/>
   </bean>

</beans>

 

jdbc.properties

jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://127.0.0.1:3306:spring_db
jdbc.username=root
jdbc.password=123456

 

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <parent>
      <artifactId>spring</artifactId>
      <groupId>org.example</groupId>
      <version>1.0-SNAPSHOT</version>
  </parent>
  <modelVersion>4.0.0</modelVersion>

  <artifactId>springDataScoures</artifactId>

  <dependencies>
      <dependency>
          <groupId>org.springframework</groupId>
          <artifactId>spring-context</artifactId>
          <version>5.2.10.RELEASE</version>
      </dependency>
      <dependency>
          <groupId>com.alibaba</groupId>
          <artifactId>druid</artifactId>
          <version>1.1.12</version>
      </dependency>
      <dependency>
          <groupId>c3p0</groupId>
          <artifactId>c3p0</artifactId>
          <version>0.9.1.2</version>
      </dependency>
      <dependency>
          <groupId>mysql</groupId>
          <artifactId>mysql-connector-java</artifactId>
          <version>5.1.45</version>
      </dependency>
  </dependencies>

</project>

Spring Ioc容器

<?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">


<!--1.导入spring坐标,spring-context-->
<!--2.配置bean class配置的是它的实现类,因为这个是要创建对象的-->
<!--*<bean>标签表示配置bean
*id属性是给bean起个名字
*class属性表示bean定义类型-->
<!--bean的作用范围scope:
默认是单类的 singleton:就是创建一个对象
prototype:非单类的,容器其实管理的是可复用的bean。
如果是非单类的,每次用一次造一个,会无穷无尽。对容器也有很大的压力。
哪一些bean适合交给容器:
表现层对象
业务层对象
数据层对象
工具类对象
不适合交给容器的bean
封装了实体域的对象(状态类对象)
-->
<bean id ="bookDao" class="com.yang.dao.impl.BookDaoImpl" scope="singleton"/>

<bean id ="bookService" class="com.yang.service.impl.BookServiceImpl">
<!--property bean中属性即serviceImpl中定义的dao属性
name即是属性名称
ref指的是将id ="bookDao"的bean通过set()方法注入到这个bean里面-->
<property name="dao" ref="bookDao"/>
</bean>
</beans>

获取容器并得到Bean

package com.yang;

import com.yang.dao.BookDao;
import com.yang.service.BookService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class App1 {
public static void main(String[] args) {
//3.获取容器ApplicationContext , 并读取配置文件(配置了bean)
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
BookDao bookDao = (BookDao) ac.getBean("bookDao1");
bookDao.save();
//4.获取对象getBean()
// BookService bookService = (BookService) ac.getBean("bookService");
// bookService.save();
}
}

 

package com.yang.service.impl;

import com.yang.dao.BookDao;
import com.yang.dao.impl.BookDaoImpl;
import com.yang.service.BookService;

public class BookServiceImpl implements BookService {
//5.准备DI注入,删除dao层的实现,提供一个dao层属性
private BookDao dao;
@Override
public void save() {
System.out.println("book service dao...");
dao.save();
}

//6.给容器提供一个入口方法即set(),容器调用这个方法,并注入对象
public void setDao(BookDao dao) {
this.dao = dao;
}
}

*注解开发

Auto自动装配

config

package com.yang.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;

@Configuration
@ComponentScan("com.yang")
@PropertySource("jdbc.properties")//这个不允许使用通配符
public class SpringConfig {
}

Dao

package com.yang.dao.impl;

import com.yang.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

@Repository("userDao")
public class UserDaoImpl implements UserDao {
//基本类型注入
@Value("${name}")
private String name;
@Override
public void save() {
System.out.println("userDao..."+","+name);
}
}

Service

package com.yang.Service.Impl;

import com.yang.Service.UserService;
import com.yang.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl implements UserService {

//按类型装配
//@Autowired 可以放在属性上,也可以放在Set()方法上,
// 注意:自动装配是基于反射中对于私有的 *暴力反射*,所以无需set()方法。
//@Qualifier 注解无法单独使用,必须配合@Autowired一起使用,按byName注入,如果没有,则byType注入
@Autowired
@Qualifier("userDao")
private UserDao userDao;
@Override
public void save() {
System.out.println("userService...");
userDao.save();
}
}

作用域和生命周期

package com.yang.dao.Impl.UserDaoImpl;

import com.yang.dao.UserDao;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Repository;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

//@Component("UserDao")
@Repository()
//bean的作用域
//@Scope("prototype")
@Scope("singleton")
public class UserDaoImpl implements UserDao {
@Override
public void save() {
System.out.println("userDao...");
}
//构造方法之前
@PostConstruct
public void init(){
System.out.println("init...");
}
//在彻底销毁之前
@PreDestroy
public void destroy(){
System.out.println("destroy...");
}
}

加载

package com.yang;

import com.yang.config.SpringConfig;
import com.yang.dao.UserDao;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class App2 {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
UserDao bean = ac.getBean(UserDao.class);
UserDao bean1 = ac.getBean(UserDao.class);
System.out.println(bean);
System.out.println(bean1);
ac.close();
}
}

第三方Bean

config第三方Bean类

package com.yang.config;

import com.alibaba.druid.pool.DruidDataSource;
import com.yang.dao.UserDao;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;

import javax.sql.DataSource;
//管理第三方Bean
public class DataSourceConfig {
//简单类型注入
@Value("com.mysql.jdbc.Driver")
private String driver;
@Value("jdbc:mysql://localhost:3306/spring_db")
private String url;
@Value("123456")
private String password;
@Value("root")
private String username;

//引用类型注入
//dataSource() 在括号中加入参数,容器会根据类型自动装配
@Bean
public DataSource dataSource(UserDao userDao){
System.out.println(userDao);
DruidDataSource ds = new DruidDataSource();
ds.setPassword(password);
ds.setUsername(username);
ds.setUrl(url);
ds.setDriverClassName(driver);
return ds;
}
}

Config配置类

package com.yang.config;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@ComponentScan("com.yang.dao.Impl")
@Import(DataSourceConfig.class)
public class SpringConfig {
}