Spring框架学习笔记

本文全面介绍了Spring框架,包括其优点、组成与扩展,如Spring Boot和Spring Cloud。详细阐述了IOC理论推导、创建对象方式、配置方法、依赖注入、Bean自动装配等内容。还讲解了使用注解和Java方式配置Spring,以及代理模式,包括静态和动态代理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、Spring框架

1.1 优点

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

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

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

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

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

1.2 组成

在这里插入图片描述

1.3 扩展

  • Spring Boot
    • 一个快速开发的脚手架。
    • 基于SpringBoot可以快速开发单个微服务
    • 约定大于配置!
  • Spring Cloud
    • Spring Cloud是基于SpringBoot实现的

弊端:发展了太久,违背了原来的理念!配置十分繁琐,人称“配置地狱”

2、IOC理论推导

在我们之前的业务中,用户的需求可能影响我们原来的代码,我们需呀哦根据用户的需求去修改源代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!

我们使用一个Set接口


private UserDao userDao;
//利用set进行动态实现值的注入!
public void setUserDao(UserDao userDao){
    this.userDao=userDao;
}

这种思想,从本质上解决了问题,我们程序员不用再去管理对象的创建了。系统的耦合性大大降低,可以更加专注在业务的实现上。这是IOC的原型!

使用xml之后,我们彻底不用再去程序中改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的Ioc,一句话搞定:对象由Spring来创建,管理,装配!

3、IOC创建对象的方式

  1. 下标赋值

    <bean id="user" class="com.muyu.pojo.User">
        <constructor-arg index="0" value="fanxu"/>
    </bean>
    
  2. 类型

    <bean id="user" class="com.muyu.pojo.User">
        <constructor-arg type="java.lang.String" value="fanxu"/>
    </bean>
    
  3. 参数名

    <bean id="user" class="com.muyu.pojo.User">
        <constructor-arg name="name" value="fanxu"/>
    </bean>
    

总结:在配置文件的时候, 容器中管理的对象就已经初始化了。

4、Spring配置

5.1 别名

<!--别名 如果添加了别名 我们也可以使用别名获取到这个对象-->
<alias name="user" alias="userNew"/>

5.2 Bean的配置

<!--
        id:bean的唯一标识符,也就是相当于我们学的对象名
        class:bean 对象所对应的全限定名:包名+类型
        name:也是别名,而且name可以一次性取很多别名
    -->
    <bean id="user" class="com.muyu.pojo.User" name="u,u2">
        <constructor-arg name="name" value="fanxu"/>
    </bean>

5.3 import

import,一般用于团队开发使用,它可以将多个配置文件,导入合并为一个

假设现在项目中有多个人开发,这三个人复制不同的类开发,不同的类要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!

  • 张三
  • 李四
  • 王五
  • applicationContext.xml

使用的时候,直接使用总的配置就可以了

5、依赖注入

6.1构造器注入

6.2 Set方式注入(重点)

  • 依赖注入:Set注入!
    • 依赖:bean对象的创建依赖于容器
    • 注入:bean对象中的所有属性,由容器来注入!

【环境搭建】

  1. 复杂类型
  2. 真实测试对象

applicationContext配置文件

<?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="address" class="com.muyu.pojo.Address">
        <property name="address" value="西安"/>
    </bean>
    <bean id="student" class="com.muyu.pojo.Student">
        <!--第一种,普通注入,使用value-->
        <property name="name" value="范栩"/>
        <!--第二种,bean注入,ref-->
        <property name="address" ref="address"/>
        <!--第三种,注入数组ref-->
        <property name="books">
            <array>
                <value>人类简史</value>
                <value>忏悔录</value>
                <value>圣经</value>
            </array>
        </property>
        <!--注入list-->
        <property name="hobbys">
            <list>
                <value>听歌</value>
                <value>篮球</value>
                <value>打代码</value>
                <value>看电影</value>
            </list>
        </property>
        <!--map-->
        <property name="card">
            <map>
                <entry key="身份证" value="152106"/>
                <entry key="银行卡" value="602030"/>
            </map>
        </property>
        <!--set-->
        <property name="games">
            <set>
                <value>LOL</value>
                <value>DNF</value>
                <value>CF</value>
            </set>
        </property>
        <!--null-->
        <property name="wife">
            <null/>
        </property>
        <!--Properties-->
        <property name="info">
            <props>
                <prop key="学号">1742201003</prop>
                <prop key="性别"></prop>
                <prop key="姓名">小明</prop>
            </props>
        </property>
    </bean>
</beans>

Student实体类

package com.muyu.pojo;

import java.util.*;

public class Student {
	private String name;
	private Address address;
	private String[] books;
	private List<String> hobbys;
	private Map<String,String> card;
	private Set<String> games;
	private Properties info;
	private String wife;

	public String getName() {
		return name;
	}

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

	public Address getAddress() {
		return address;
	}

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

	public String[] getBooks() {
		return books;
	}

	public void setBooks(String[] books) {
		this.books = books;
	}

	public List<String> getHobbys() {
		return hobbys;
	}

	public void setHobbys(List<String> hobbys) {
		this.hobbys = hobbys;
	}

	public Map<String, String> getCard() {
		return card;
	}

	public void setCard(Map<String, String> card) {
		this.card = card;
	}

	public Set<String> getGames() {
		return games;
	}

	public void setGames(Set<String> games) {
		this.games = games;
	}

	public Properties getInfo() {
		return info;
	}

	public void setInfo(Properties info) {
		this.info = info;
	}

	public String getWife() {
		return wife;
	}

	public void setWife(String wife) {
		this.wife = wife;
	}

	@Override
	public String toString() {
		return "Student{" +
				"name='" + name + '\'' +
				", address=" + address +
				", books=" + Arrays.toString(books) +
				", hobbys=" + hobbys +
				", card=" + card +
				", games=" + games +
				", info=" + info +
				", wife='" + wife + '\'' +
				'}';
	}
}

Address实体类

package com.muyu.pojo;

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 + '\'' +
				'}';
	}
}

测试类

package com.muyu.test;

import com.muyu.pojo.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class MyTest {
	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		Student student = (Student) context.getBean("student");
		System.out.println(student);
	}
}

6.3 扩展方式注入

我们可以使用p命令空间和c命令空间进行注入

例:

<?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:p="http://www.springframework.org/schema/p"
       xmlns:c="http://www.springframework.org/schema/c"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd">
    <!--p命名空间注入,可以直接注入属性的值:property-->
    <bean id="user" class="com.muyu.pojo.User" p:name="范栩" p:age="21"/>
    <bean id="user2" class="com.muyu.pojo.User" c:age="21" c:name="小李"/>
</beans>

测试

@Test
public void test01(){
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    User user = context.getBean("user",User.class);
    System.out.println(user);
}

@Test
public void test02(){
    ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    User user2 = context.getBean("user2", User.class);
    System.out.println(user2);
}

注意点:p命名和c命名空间不可以直接使用,需要导入xml约束

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

6.4 bean的作用域

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dQwJg2Ix-1610539059691)(C:\Users\16404\AppData\Roaming\Typora\typora-user-images\image-20210103132818808.png)]

  1. 单例模式(spring默认机制)

    <bean id="user2" class="com.muyu.pojo.User" c:age="21" c:name="小李" scope="singleton"/>
    

    即使创建多个同一个类的对象,在本质上这些类的对象还是一个

  2. 原型模式

```

每次从容器中get的时候,都会产生一个新的对象。

  1. 其余的request、session、application、这些只能在web开发中使用到!

6、Bean的自动装配

  • 自动装配是Spring满足bean依赖的一种方式
  • Spring会在上下文中自动寻找,并自动给bean装配属性

在Spring中有三种装配的方式

  1. 在xml中显示的配置
  2. 在java中显示配置
  3. 隐式的自动装配bean(重要)

6.1 测试

环境搭建:一个人有两个宠物!

6.2 ByName自动装配


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

6.3 ByType自动装配

<bean id="cat" class="com.muyu.pojo.Cat"></bean>
<bean id="dog11" class="com.muyu.pojo.Dog"></bean>
    <!--
        byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid!
        byType:会在动在容器上下文中查找,和自己对象属性类型相同的bean!
    -->
<bean id="people" class="com.muyu.pojo.People" autowire="byType">
    <property name="name" value="范栩"/>
</bean>

小结:

  • byName的时候,需要保证所有的bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致!
  • byType的时候,需要保证bean的class唯一,并且这个bean需要和渣滓洞注入的属性类型一致!

6.4 使用注解自动装配

jdk1.5支持的注解,Spring2.5就支持注解了

要使用注解须知:

  1. 导入约束

  2. 配置注解的支持:<context:annotation-config/>

    <?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:annotation-config/>
    
    </beans>
    

@Autowired

直接在属性上使用即可!也可以在set方式上使用!

使用Autowired 我们可以不用编写Set方法了,前提是你这个自动装配的属性在IOC(spring)容器中存在,且符合名字(byName)

扩展:

@Nullable	字段标记了这个注解,说明这个字段可以为null

@Resource

可以自动识别名字,如果名字没有识别到,就自动识别类型,如果类型也没有识别到的话,才会报错

小结:

@Resource和@Autowired的区别:

  • 都是用来自动装配的,都可以放在属性字段上

  • @Autowired通过byname的方式实现

  • @Resource默认通过byname的方式实现,如果找不到名字,则通过bytype的方式实现!如果两个都找不到的情况下,就报错!

  • 执行顺序不同:@Autowired通过byname的方式实现。

7、使用注解开发

在Spring4之后,必须要保证,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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       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
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">
    <context:annotation-config/>
</beans>	

注解说明

  • @Autowired:自动装配通过类型,名字

    ​ 如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value=“xxx”)

  • @Nullable:字段标记了这个注解,说明这个字段可以为Null

  • @Resource:自动装配通过名字,类型

  • @Component:组件,放在类上,说明这个类被Spring管理了,就是bean!

  1. bean

  2. 注解如何注入

    package com.muyu.pojo;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Component;
    //@Component等价于<bean id="user" class="com.muyu.pojo.User"/>
    //@Component组件
    @Component
    public class User {
    	//相当于<property name="name" value="fanxu" />
    	public String name;
    	@Value("fanxu2")
    	public void setName(String name) {
    		this.name = name;
    	}
    }
    
    
  3. 衍生的注解

    @Component有几个衍生注解,我们在web开发中,会按照mvc三层架构分层!

    • dao:@Repository

    • service:@Service

    • controller:@Controller

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

  4. 自动装配置

     @Autowired	//自动装配通过类型,名字
      		   	//如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value="xxx")
     @Nullable	//字段标记了这个注解,说明这个字段可以为Null
     @Resource	//自动装配通过名字,类型
    
    
  5. 作用域

    package com.muyu.pojo;
    
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Scope;
    import org.springframework.stereotype.Component;
    //@Component等价于<bean id="user" class="com.muyu.pojo.User"/>
    //@Component组件
    @Component
    @Scope("singleton")
    public class User {
    	//相当于<property name="name" value="fanxu" />
    	public String name;
    	@Value("fanxu2")
    	public void setName(String name) {
    		this.name = name;
    	}
    }
    
  6. 小结

    xml和注解:

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

    最佳实践:

    • xml用来管理bean
    • 注解只负责值的注入
    • 我们在使用的过程中,要需要注意一个问题:必须让注解生效,就需要开启注解的支持

8、使用java的方式配置Spring

我们现在要完全不适用Spring 的xml配置,全权交给java!

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

9、代理模式

为什么学习代理模式?因为这是SpringAOP的底层【SpringAOP和SpringMVC】

代理模式的分类:23种模式之一

  • 静态代理
  • 动态代理

9.1 静态代理

角色分析:

  • 抽象角色:一般会使用接口或者抽象类来解决
  • 真实角色:被代理的角色
  • 代理角色:代理真实的角色,代理真实角色后,我们一般会做一些附属操作
  • 客户:访问代理对象的人!

代码步骤:
1.接口

package com.muyu.demo01;

//租房的接口
public interface Rent {
	public void rent();
}

2.真实角色

package com.muyu.demo01;

//房东
public class Host implements Rent{
	@Override
	public void rent() {
		System.out.println("房东要出租房子");
	}
}

3.代理角色

package com.muyu.demo01;

public class Proxy implements Rent{
	private Host host;

	public Proxy() {
	}

	public Proxy(Host host) {
		this.host = host;
	}

	@Override
	public void rent() {
		seeHouse();
		host.rent();
		hetong();
		fare();
	}

	//看房
	public void seeHouse(){
		System.out.println("中介带你看房");
	}
	//收中介非
	public void fare(){
		System.out.println("收中介费");
	}
	public void hetong(){
		System.out.println("签合同");
	}
}

4.客户端访问代理角色

package com.muyu.demo01;

public class Client {
	public static void main(String[] args) {
		//房东要租房子
		Host host = new Host();
		//代理,中介帮房东租房子,但是呢?代理一般会有一些附属操作
		Proxy proxy = new Proxy(host);
		//你不用面对房东,直接找中介
		proxy.rent();
	}
}

代理模式的好处?

  • 可以使真实角色的操作更加纯粹!不用再去关注一些公共的业务
  • 公共业务交给代理角色!实现了业务的分工!
    公共业务发生扩展的时候,方便集中管理!

缺点

  • 一个真实角色就会产生一个代理角色:代码量会翻倍,开发效率会变低

9.2 动态代理

  • 动态代理和静态代理角色异样
  • 动态代理的代理类是动态生成的,不是我们直接写好的!
  • 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
    • 基于接口–JDK动态代理
    • 基于类:cglib
    • java字节码实现:JAVAssist

需要了解两个类:Proxy 代理,InvocationHandler 调用处理程序

动态代理的好处

  • 可以使真实角色的操作更加纯粹!不用再去关注一些公共的业务
  • 公共业务交给代理角色!实现了业务的分工!
  • 公共业务发生扩展的时候,方便集中管理!
  • 一个动态代理类代理的是一个接口,一般就是对应的一类业务
  • 一个动态代理类可以代理多个类,只要是实现了同一个接口的
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值