Spring学习记录(上)

1、Spring介绍

1.1、简介

  • 2002年首次推出了Spring框架的雏形:interface21框架

  • Spring框架以interface21框架为基础,经过重新设计,并不断丰富其内涵,在2004年3月24日发布了1.0正式版。

  • 创始人:Rod Johnson,是著名的作家。他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。

  • Spring理念:解决企业开发的复杂性。

    官网:https://spring.io/projects

    Github:https://github.com/spring-projects/spring-framework

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.10</version>
</dependency>

<!--整合Mybatis时需要-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.10</version>
</dependency>

1.2、优点

  • Spring是一个开源的免费框架
  • Spring是一个轻量级的、非入侵式的框架
  • 控制反转(IoC),面向切面编程(AOP)
  • 支持事务的处理,对框架整合的支持

1.3、组成

Spring的七个模块

2、Spring使用

2.1、Maven

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-webmvc</artifactId>
    <version>5.3.10</version>
</dependency>

<!--整合Mybatis时需要-->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.10</version>
</dependency>

2.2、ApplicationContext.xml文件:

Spring通过读取这个文件来创建对象,文件名可以自定,但这边不建议

<?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.zhanc.pojo.User">
        <!--通过Spring创建也是走构造方法-->
        <!--
			ref:指定Spring容器中创建好的对象
			value:具体的值(基本数据类型)
		-->
        <!--<property name="name" value="zhanc"/>-->
        <!--多参构造可使用以下方法放置参数-->
        <!--1、通过指定索引的方式(tips:索引下标从0开始)-->
        <!--<constructor-arg index="0" value="zhanc"/>-->
        <constructor-arg name="name" value="zhanc"/>
    </bean>

</beans>

3、创建对象

普通创建对象:类 变量名=new 类();

通过Spring创建:ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");先获取先获取ApplicationContext,之后需要的对象从context中取即可,新的类也只需要在配置文件中注册即可。

//先获取ApplicationContext,之后需要什么对象就只需要在context中取
//修改需求只需要他自己在xml配置文件中修改(或另创建程序修改xml)即可
ApplicationContext context=new ClassPathXmlApplicationContext("beans.xml");
User user = (User) context.getBean("user");
System.out.println(user.getName());

3、ApplicationContext.xml配置

3.1、alias 别名

<!--对象的别名,不常用,bean下的name选项是更好的解决方案-->
<alias name="user" alias="user2"/>

3.2、bean 对象

<!--
	id:bean的唯一标识符,也就是实例化中的变量名
	class:bean对象对应的全限定名
	name:别名,相较于alias可以同时取多个别名
-->
<bean id="user" class="com.zhanc.pojo.User" name="user3,user4">
    <constructor-arg name="name" value="zhanc"/>
</bean>

3.3、import

import一般用于团队开发,可导入其他成员的ApplicationContext配置文件

<import resource="beans1.xml"/>
<import resource="beans2.xml"/>

4、依赖注入

依赖注入本质上是Set注入

4.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="user" class="com.zhanc.pojo.User">
        <!--多参构造可使用以下方法放置参数-->
        <!--1、通过指定索引的方式(tips:索引下标从0开始)-->
        <!--<constructor-arg index="0" value="zhanc"/>-->
        <constructor-arg name="name" value="zhanc"/>
    </bean>

</beans>

4.2、Set方法注入(重点)

【环境搭建】

4.2.1、引用类型

public class Address {
    private String address;

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

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

4.2.2、测试对象

public class Student {
    private int id;
    private String name;
    private Address addr;
    private String[] books;
    private List<String> hobbys;
    private Map<String,Integer> cards;
    private Set<String> games;
    private String wife;
    private Properties info;
	
    //getter and setter方法略过
    
    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", addr=" + addr.toString() +
                ", books=" + Arrays.toString(books) +
                ", hobbys=" + hobbys +
                ", cards=" + cards +
                ", games=" + games +
                ", wife='" + wife + '\'' +
                ", info=" + info +
                '}';
    }
}

4.2.3、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"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="addr" class="com.zhanc.pojo.Address">
        <property name="address" value="xxxxx小区"/>
    </bean>

    <bean id="student" class="com.zhanc.pojo.Student">
        <!--int-->
        <property name="id" value="123"/>

        <!--String-->
        <property name="name" value="zhanc"/>

        <!--ref引用类型-->
        <property name="addr" ref="addr"/>

        <!--array数组-->
        <property name="books">
            <array>
                <value>三国演义</value>
                <value>红楼梦</value>
                <value>西游记</value>
            </array>
        </property>

        <!--list列表-->
        <property name="hobbys">
            <list>
                <value></value>
                <value></value>
                <value>rap</value>
            </list>
        </property>

        <!--map映射-->
        <property name="cards">
            <map>
                <entry key="学号" value="123123123"/>
                <entry key="专业编码" value="123123123"/>
            </map>
        </property>

        <!--set集合-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>COC</value>
                <value>BOB</value>
            </set>
        </property>

        <!--null-->
        <property name="wife">
            <null/>
        </property>

        <!--properties-->
        <property name="info">
            <props>
                <prop key="性别"></prop>
                <prop key="年龄">15</prop>
                <prop key="班级">软件工程</prop>
            </props>
        </property>
    </bean>

</beans>

4.2.4、测试类

@Test
public void SpringTest(){
    ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
    Student student = (Student) context.getBean("student");
    System.out.println(student);

    //输出:
    //Student{
    // id=123,
    // name='zhanc',
    // addr=Address{address='xxxxx小区'},
    // books=[三国演义, 红楼梦, 西游记],
    // hobbys=[唱, 跳, rap],
    // cards={学号=123123123, 专业编码=123123123},
    // games=[LOL, COC, BOB],
    // wife='null',
    // info={性别=男, 班级=软件工程, 年龄=15}
    // }
}

4.3、拓展方式注入

4.3.1、p命名空间注入

<beans ...
    xmlns:p="http://www.springframework.org/schema/p"
    ...>
    
    <!--p(property)命名空间-->
    <bean id="user" class="com.zhanc.pojo.User" p:id="1" p:name="zhanc" p:pwd="123"/>

</beans>

4.3.2、c命名空间注入

<beans ...
    xmlns:c="http://www.springframework.org/schema/c"
    ...>
    
    <!--c(constructor-arg)命名空间-->
    <!--1.通过索引注入-->
    <bean id="user" class="com.zhanc.pojo.User" c:_0="1" c:_1="zhanc" c:_2="123123"/>
    <!--2.通过属性名注入-->
    <bean id="user" class="com.zhanc.pojo.User" c:id="1" c:name="zhanc" c:pwd="123123"/>

</beans>

5、Bean作用域

  • 单例模式(默认模式)

    每次从容器中getBean的时候,返回的都是同一个对象

  • 原型模式

    每次从容器中getBean的时候,返回一个新的对象

  • request、session、application、websocket只有在web开发中使用

6、使用注解开发

使用注解环境要求jdk1.5及以上、Spring2.5及以上

在Spring4以后,要使用注解开发,必须要保证aop包的导入

需要aop包

使用注解需要导入context约束,添加注解的支持

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">
	
	<!--指定要扫描的包,这个包下的注解就会生效-->
    <context:component-scan base-package="com.zhanc"/>
    <!--开启注解支持-->
    <context:annotation-config/>

</beans>

6.1、注册装配Bean

//等价于<bean id="user" class="com.zhanc.pojo.User"/>
@Component
public class User {
    //等价于<property name="name" value="zhanc"/>
    @Value("zhanc")
    public String name;
}

@Component的几个衍生注解,按照mvc三层架构分层

  • dao 【@Repository】

  • service 【@Service】

  • controller 【@Controller】

    这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean

6.2、自动装配Bean属性

在Spring中有三种装配属性的方式:

  1. 在xml中显式地配置

    在此前所学的配置方式都为xml显式配置,即为bean详细的指定中每个属性(property),较为繁琐

  2. 在java中显式地配置

    我们后文再讲

  3. 隐式地自动装配

    本节重点讲解

测试环境搭建:一个人拥有两只宠物,分别为猫和狗

三个实体类:

public class People {
    private String name;
    private Dog dog;
    private Cat cat;
    //……节省篇幅,这里getter/setter方法和重写toString方法略
}

public class Cat {
    @Override
    public String toString() {
        return "mmmmm~";
    }
}

public class Dog {
    @Override
    public String toString() {
        return ("wwwww~");
    }
}

6.2.1、byName自动装配

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="dog" class="com.zhanc.pojo.Dog"/>
    <bean id="cat" class="com.zhanc.pojo.Cat"/>

    <!--byName:自动在容器上下文中查找,和自己对象set方法后面的值对应的bean_id-->
    <bean id="people" class="com.zhanc.pojo.People" autowire="byName">
        <property name="name" value="zhanc"/>
    </bean>

</beans>

优点:命名统一规范时,较为方便
弊端:需要bean_id同名且唯一,否则找不到

6.2.2、byType自动装配

<?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
        https://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="com.zhanc.pojo.Dog"/>
    <bean class="com.zhanc.pojo.Cat"/>
    
    <!--byType:自动在容器上下文中查找,和自己对象属性类型相同的bean-->
    <bean id="people" class="com.zhanc.pojo.People" autowire="byName">
        <property name="name" value="zhanc"/>
    </bean>

</beans>

优点:连bean id都可省略(但不建议)

弊端:容器中的同类型的bean只有一个,否则报错

6.2.3、使用注解自动装配

  1. @Autowired (Spring)

    在属性上使用,也可以在set方法上使用。(推荐在属性上使用)

    使用@Autowired后我们可以不用编写Set方法,前提是你这个自动装配的属性在IoC(Spring)容器中存在,且符合byName规则

    小知识:

    @Autowired(required = false) @Autowired设置required属性为false说明该属性可以为空,等同于@Nullable,否则不能为空

    个人理解为byName+byType结合,@Autowired默认是先使用byType

    如果@Autowired自动装配的环境较为复杂,可以配合@Qualifier(value = "dog111") 也能指定bean(当然类型需要相同)

    public class People {
        private String name;
        @Autowired
        @Qualifier(value = "dog111")
        private Dog dog;
        private Cat cat;
        //……节省篇幅,这里getter/setter方法和重写toString方法略
    }
    
  2. @Resource (javax.annotation)

    与@Autowired使用方法相似,在属性上使用,但相较于复杂场景下@Autowired需要结合@Qualifier使用,@Resource可以独立完成指定bean

    使用方法:

    public class People {
        private String name;
        @Autowired
        @Qualifier(value = "dog")
        private Dog dog;
    
        @Resource(name = "cat")
        private Cat cat;
        //……节省篇幅,这里getter/setter方法和重写toString方法略
    }
    
  3. 注意点

    @Resource和@Autowired的区别

    • 都是用于自动装配的,都可以放在属性字段上
    • @Autowired默认通过byType的方式实现,如果出现多个相同类型就使用byName寻找,还找不到时结合@Qualifier(value = "xxx")使用
    • @Resource默认通过byName的方式实现,如果找不到名字,就使用byType寻找,如果存在多个类型,则可使用@Resource(name = "xxx") 来指定名字
    • @Resource较为常用

6.3、作用域

在对应的类上@Scope("模式")

@Component
@Scope("singleton")
public class User {
    @Value("zhanc")
    public String name;
}

6.4、小结

使用注解一定要让注解生效:

<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="com.zhanc"/>
<!--开启注解支持-->
<context:annotation-config/>

xml与注解:

  • xml更加自由,适用于任何场合,维护相对方便
  • 注解 不是自己的类使用不了,维护相对复杂

较优方案:

  • xml用来管理bean
  • 由注解来负责属性的注入

7、Java配置Spring

抛弃Spring的xml配置,全权交给Java来操作

JavaConfig是Spring的一个子项目,在Spring4之后,它成为了一个核心功能

实体类:

@Component
public class User {
    @Value("zhanc")
    private String name;

    public String getName() {
        return name;
    }

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

配置类(类名可以自己取):

//这个类也会被Spring容器托管,注册到容器中,因为他本来就是一个@Component
//@Configuration 代表这是一个配置类,就和我们之前看的applicationContext.xml是等价的
@Configuration
//等价于<context:component-scan base-package="com.zhanc"/>
@ComponentScan("com.zhanc")
//等价于xml中引入其他xml配置<import resource="beans1.xml"/>
@Import(SpringConfig2.class)
public class SpringConfig {
    //等价于<bean id="getUser" class="com.zhanc.pojo.User">
    //方法名就是bean的id
    //返回值就是bean的class
    @Bean
    public User getUser(){
        return new User();
    }
}

测试类:

@Test
public void ConfigTest(){
    //如果完全使用了JavaConfig方式去做,我们就只能通过AnnotationConfig上下文来获取容器,通过配置类的class对象加载
    ApplicationContext context=new AnnotationConfigApplicationContext(SpringConfig.class);
    //方法名就是bean_id
    User user = context.getBean("getUser", User.class);
    System.out.println(user.getName());
}

这种纯Java的配置方式,在SpringBoot中随处可见!
上半部分还未涉及AOP,将会在下半部分继续学习

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值