spring从入门到精通(一)

1.IOC容器

  • ioc不是什么技术,而是一种设计思想,就是将原本在程序手中创建对象的权力,交给spring框架来管理。
  • 以往的思路:若使用某个对象,需要自己负责对象的创建;
  • 反转的思路:若使用某个对象,需要从spring容器中获取需要使用的对象,不关心对象的创建过程,也就是把创建对象的控制权转给了spring框架;
  • 好莱坞法则:Don’t call me,I’ll call you

下面以家政服务为例:
过年了,家里想要打扫卫生,想要请一个家政服务帮你打扫卫生,由以下两种做法:
(1)自己主动打电话,询问查找,自己谈价钱;
(2)直接打电话给家政公司,提出要求即可。

那会有人问了,那家政公司从哪里来啊!
1.自行构建
我们可以使用配置文件,或者注解的方式定义下咱们自己容器里面存放的东西。
2.使用别人的
一定会有很多有钱人,成立自己的各类公司,他们的这些服务都可以继承在咱们的容器里,为我们提供很多强大的功能,比如spring自带的很多template模板类。

1.1代码示例

1.新建maven工程
pom文件添加

<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>spring-study</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency> <!-- 引入web直接会将所有的依赖项全部依赖过来 -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>5.2.6.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.12</version>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.1</version>
                <configuration>
                    <source>1.8</source> <!-- 源代码使用的JDK版本 -->
                    <target>1.8</target> <!-- 需要生成的目标class文件的编译版本 -->
                    <encoding>UTF-8</encoding><!-- 字符集编码 -->
                </configuration>
            </plugin>
        </plugins>
    </build>


</project>

2.新建user实体类
在这里插入图片描述
3.新建beans.xml配置文件
在这里插入图片描述
4.新建测试类
在这里插入图片描述

1.2详细说说其中的几个对象

1.2.1ApplicationContext

ApplicationContext是spring继BeanFactory之外的另一个核心接口或容器,允许容器通过应用程序上下文环境创
建、获取、管理bean。为应用程序提供配置的中央接口。在应用程序运行时这是只读的。
一个ApplicationContext提供:

public interface ApplicationContext extends EnvironmentCapable, ListableBeanFactory, HierarchicalBeanFactory, MessageSource, ApplicationEventPublisher, ResourcePatternResolver {
    
     }
  • 访问应用程序组件的Bean工厂方法。从org.springframework.beans.factory.ListableBeanFactory继承
  • 以通用方式加载文件资源的能力。继承自ResourcePatternResolver 接口
  • 向注册侦听器发布事件的能力。继承自ApplicationEventPublisher接口。
  • 解析消息的能力,支持国际化。继承自MessageSource接口
1.2.2ConfigurableApplicationContext
public interface ConfigurableApplicationContext extends ApplicationContext, Lifecycle, Closeable {
    
     }

ClassPathXmlApplicationContext是ConfigurableApplicationContext的一个实现,
该类提供了很多记载资源的方式,该类可以加在类路劲下的xml资源文件,当然如果想加在其他地方的资源,可以使用FileSystemXmlApplicationContext这个类

 /**
     * Create a new ClassPathXmlApplicationContext, 
     * loading the definitions * from the given XML file and automatically refreshing the context. 
     * @param configLocation resource location * @throws BeansException if context creation failed
     */
    public ClassPathXmlApplicationContext (String configLocation) throws BeansException {
    
    
        this (new String[]{
    
    configLocation}, true, null);
    }

2.DI依赖注入

对象是有属性的,属性是需要赋值的。通常的方式是:(new对象,set赋值,get取值)

	Student student = new Student (); 
    student.setName("张三"); 
    student.setAge(23);
    Teacher teacher = new Teacher (); 
    student.setTeacher(teacher);

归根结底,都需要我们自己去赋值。
而控制反转(IOC)也叫依赖注入(DI)的核心思想是,构建对象(包括初始化和赋值)都不需要人为操作,而是将
这个权利交付给容器来进行。

3.IOC好处

  • 第一、USB设备作为电脑主机的外部设备,在插入主机之前,与电脑主机没有任何的关系,只有被我们连接在
    一起之后,两者才发生联系,具有相关性。所以,无论两者中的任何一方出现什么的问题,都不会影响另一
    方的运行。这种特性体现在软件工程中,就是可维护性比较好,非常便于进行单元测试,便于调试程序和诊
    断故障。代码中的每一个Class都可以单独测试,彼此之间互不影响,只要保证自身的功能无误即可,这就是 组件之间低耦合或者无耦合带来的好处。
  • 第二、USB设备和电脑主机的之间无关性,还带来了另外一个好处,生产USB设备的厂商和生产电脑主机的厂
    商完全可以是互不相干的人,各干各事,他们之间唯一需要遵守的就是USB接口标准。这种特性体现在软件
    开发过程中,好处可是太大了。每个开发团队的成员都只需要关心实现自身的业务逻辑,完全不用去关心其
    它的人工作进展,因为你的任务跟别人没有任何关系,你的任务可以单独测试,你的任务也不用依赖于别人
    的组件,再也不用扯不清责任了。所以,在一个大中型项目中,团队成员分工明确、责任明晰,很容易将一
    个大的任务划分为细小的任务,开发效率和产品质量必将得到大幅度的提高。
  • 第三、同一个USB外部设备可以插接到任何支持USB的设备,可以插接到电脑主机,也可以插接到DV机,
    USB外部设备可以被反复利用。在软件工程中,这种特性就是可复用性好,我们可以把具有普遍性的常用组件
    独立出来,反复利用到项目中的其它部分,或者是其它项目,当然这也是面向对象的基本特征。显然,IOC不
    仅更好地贯彻了这个原则,提高了模块的可复用性。符合接口标准的实现,都可以插接到支持此标准的模块 中。
  • 第四、同USB外部设备一样,模块具有热插拔特性。IOC生成对象的方式转为外置方式,也就是把对象生成放
    在配置文件里进行定义,这样,当我们更换一个实现子类将会变得很简单,只要修改配置文件就可以了,完 全具有热插拨的特性。

4.依赖注入的方式

4.1构造器注入

1.新建Dog实体类
在这里插入图片描述
2.新建dogBean.xml
在这里插入图片描述
3.测试类
在这里插入图片描述

4.2set方法注入

注意:
(1)要求被注入的属性 , 必须有set方法
(2)set方法的方法名由set + 属性首字母大写
(3)如果属性是boolean类型 , 没有set方法 , 是 is + 属性首字母大写

1.新建Address.java(采用lombok的@Data注解,自动生成get和set方法)
在这里插入图片描述
2.新建user2.java
在这里插入图片描述
3.新建user2Bean.xml(演示多种类型参数注入)
在这里插入图片描述
完整的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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="address" class="com.wshy.example.entity.Address">
        <property name="addressInfo" value="珠琳旺角大厦"/>
    </bean>
    <bean id="user" class="com.wshy.example.entity.User2"> 
    	<!-- 基本属性注入 -->
        <property name="name" value="wshy"/> 
        <!-- 引用类型注入 -->
        <property name="address" ref="address"/> 
        <!-- 数组注入 -->
        <property name="hobbies">
            <array>
                <value>写程序</value>
                <value></value>
                <value></value>
                <value>漂亮姑娘</value>
                <value>赢钱</value>
            </array>
        </property> <!-- list注入 -->
        <property name="duties">
            <list>
                <value>IT老师</value>
                <value>我儿子的爸爸</value>
            </list>
        </property> <!-- set注入 -->
        <property name="carts">
            <set>
                <value>纸尿裤</value>
                <value>玩具</value>
            </set>
        </property> <!-- map注入 -->
        <property name="familyTies">
            <map>
                <entry key="father" value="张某某"/>
                <entry key="mather" value="钟某某"/>
            </map>
        </property> <!-- property注入 -->
        <property name="workExperience">
            <props>
                <prop key="first">电厂职工</prop>
                <prop key="second">java开发工程师</prop>
                <prop key="third">java讲师</prop>
            </props>
        </property> <!-- null注入 -->
        <property name="daughter">
            <null/>
        </property>
    </bean>
</beans>

4.测试类
在这里插入图片描述

5.Bean的作用域

Spring IOC容器创建一个Bean实例时,可以为Bean指定实例的作用域,作用域包括singleton(单例模式,默认)、
prototype(原型模式)、request(HTTP请求)、session(会话)、global-session(全局会话)。

5.1Singleton

当一个bean的作用域为Singleton
那么Spring IoC容器中只会存在一个共享的bean实例,并且所有对bean的请求,只要id与该bean定义相匹配,则
只会返回bean的同一实例。Singleton是单例类型,就是在创建起容器时就同时自动创建了一个bean的对象,不管
你是否使用,他都存在了,每次获取到的对象都是同一个对象。注意,Singleton作用域是Spring中的缺省作用
域。要在XML中将bean定义成singleton,可以这样配置:

<bean id="userServiceImpl" class=""com.xinzhi.service.UserServiceImpl">

1.默认为单例
在这里插入图片描述
2.创建两个示例对象,判断是否相等,两个引用类型使用“==”,比较的是引用指向的地址。
返回true表示为同一个实例对象,即单例。
在这里插入图片描述

5.2Prototype

当一个bean的作用域为Prototype,表示一个bean定义对应多个对象实例。
Prototype作用域的bean会导致在每次对该bean请求(将其注入到另一个bean中,或者以程序的方式调用容器的
getBean()方法)时都会创建一个新的bean实例。Prototype是原型类型,它在我们创建容器的时候并没有实例
化,而是当我们获取bean的时候才会去创建一个对象,而且我们每次获取到的对象都不是同一个对象。根据经
验,对有状态的bean应该使用prototype作用域,而对无状态的bean则应该使用singleton作用域。在XML中将
bean定义成prototype,可以这样配置:

<bean id="account" class="com.xinzhi.entity.User" scope="prototype"/>

1.scop设置为prototype
在这里插入图片描述
2.结果为false,s说明两个对象指向不同的地址,为多例。
在这里插入图片描述

5.3Request

当一个bean的作用域为Request
表示在一次HTTP请求中,一个bean定义对应一个实例;即每个HTTP请求都会有各自的bean实例,它们依据某个
bean定义创建而成。该作用域仅在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义:

<bean id="loginAction" class="com.xinzhi.entity.User" scope="request"/>

针对每次HTTP请求,Spring容器会根据loginAction bean的定义创建一个全新的LoginAction bean实例,且
该loginAction bean实例仅在当前HTTP request内有效,因此可以根据需要放心的更改所建实例的内部状态,而其
他请求中根据loginAction bean定义创建的实例,将不会看到这些特定于某个请求的状态变化。当处理请求结束,
request作用域的bean实例将被销毁。

5.4Session

(4)当一个bean的作用域为Session,表示在一个HTTP Session中,一个bean定义对应一个实例。该作用域仅
在基于web的Spring ApplicationContext情形下有效。考虑下面bean定义:

<bean id="userPreferences" class="com.xinzhi.entity.User" scope="session"/>

针对某个HTTP Session,Spring容器会根据userPreferences bean定义创建一个全新的userPreferences
bean实例,且该userPreferences bean仅在当前HTTP Session内有效。与request作用域一样,可以根据需要放
心的更改所创建实例的内部状态,而别的HTTP Session中根据userPreferences创建的实例,将不会看到这些特定
于某个HTTP Session的状态变化。当HTTP Session最终被废弃的时候,在该HTTP Session作用域内的bean也会被
废弃掉。

6.自动注入

spring作为长期以来java最火的框架,其IOC做的十分的健全,以上情况都是我们手动装配,但是我们也说了
spring及其灵活的帮助我们完成了解耦工作,如果所以的类都是自己手动完成注入,他的解耦能力就不会体现的那
么强烈了,于是spring还为我们提供了自动装配的能力
只要我们的Beans满足bean之间的依赖,且这些bean都存在于容器,且唯一,那么我么就可以按照约定进行bean
的自动装配。同时还能大量的减少配置文件的数量。

6.1按名称自动装配(byName)

过程:
1.从javabean的set方法获取名字,如setAddress,就去spring容器中找名字为address的bean。
2. 如果有,就取出注入;如果没有,就不注入。

1.修改bean.xml,增加一个属性 autowire=“byName”,user2中有一个属性为address,使用byName时,可以自动注入address的bean,需要将手动注入的property删除,若不删除,则自动注入不会生效,以手动注入为先。
在这里插入图片描述
2.测试,address仍然被注入成功
在这里插入图片描述
注意:若地址的bean为address2,而user2中的属性为address,此时只会寻找bean的name为address的bean,address2就不会被注入了。测试如下:
在这里插入图片描述
在这里插入图片描述

6.2按类型自动装配(byType)

注意:按照类型注入,容器内的bean必须是单例
1.在bean.xml中增加autowire="byType“
在这里插入图片描述
2.测试结果
在这里插入图片描述
注意:如果xml中配置类型有两个,会发生报错,idea会直接报错,如下:
在这里插入图片描述
原因:按照类型注入,容器内的bean必须是单例

7.基于注解开发

7.1自动装配

步骤:
1.在bean.xml配置文件需要加头文件
在这里插入图片描述
2.在javaBean类中的对应属性上增加@Autowired注解
在这里插入图片描述
3.测试结果
在这里插入图片描述
注意:@autowired注解默认按类型装配,所以当出现多个bean时,xml会不知道选择哪个bean,此时可以在@autowired注解上配合@Qualifier注解,指定使用哪个bean注入。例如:

在这里插入图片描述在这里插入图片描述
注意:@Qualifier不能单独使用,它和@Autowired配合可以根据名称进行自动装配

@Resource

  • @Resource如有指定的name属性,先按该属性进行byName方式查找装配,写了啥名字就找哪个;
  • 其次再进行默认的byName方式进行装配;
  • 如果以上都不成功,则按byType的方式自动装配。
  • 都不成功,则报异常。
    在这里插入图片描述

7.2分层开发

@Controller,在controller中标注注解
@Service,在service层使用
@Repository,在Dao层使用
1.service层:

  @Service
    public class UserServiceImpl implements IUserService {
    
     
        //自动注入该类型的dao的实现 
         @Autowired private IUserDao userDao; 
         public void register(User user) {
    
    
         System.out.println(user.getName()+"注册成功!");
         userDao.saveUser(user); 
         } 
    }

2.Dao层

  @Repository
    public class UserOracleDao implements IUserDao {
    
    
        public int saveUser (User user) {
    
    
            System.out.println ("我是将数据保存至oracle");
            return 1;
        }
    }

7.3组件开发

1.xml配置文件只留下扫包,其他全部注释
在这里插入图片描述
2.address.java的bean加入@Component和@Value注解
在这里插入图片描述
3.User.java的bean上添加@Component和@Value注解,其中address为@Resource注解
在这里插入图片描述
4.结果,注入成功”贾汪区“和”wshy“
在这里插入图片描述

7.4配置文件

@Bean
@Configuration

xml类配置同组件开发时的配置,只留扫包,其他删除或注释掉
1.新建Cat类
在这里插入图片描述
2.新建mouse类
在这里插入图片描述
3.新建cat_config类,由于@Bean中mouse已经存在,在cat的@Bean注解时,会自动获取容器中已经存在的bean
在这里插入图片描述
4.新建测试类
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_40550118/article/details/107325980