Spring学习(一)——Sping-XML

一、Spring的概述

(一)什么是Spring?

**Spring是针对bean对象的生命周期进行管理的轻量级容器。**提供了功能强大IOC、AOP及Web MVC等功能。Spring框架主要由七部分组成:分别是 Spring Core、 Spring AOP、 Spring ORM、 Spring DAO、Spring Context、 Spring Web和 Spring Web MVC。

官网:https://spring.io/

(二)Spring核心功能

Spring框架可以和任意框架进行整合。

  • IOC------控制反转

  • DI------依赖注入

  • AOP------面向切面

(三)Spring的好处

  • 高内聚低耦合

    • 高内聚:让方法责任更加单一,更加纯粹,最大程度的保证内聚以及责任单一

    • 低耦合:减少代码之间的关联,即一个类对另外一个类的依赖程度,极可能让类与类之间的关联降到最低

    • 原则:

      • 责任单一原则:需要用整个编程生涯来贯彻

      • 最少知道原则:禁止跨级调用;让一个类认识/调用最少的类

  • 简化事务:仅仅使用一个注解,就能让事务生效

  • 集成了Junit,方便测试

  • 简化了开发

  • 方便集成各种框架:使用Spring去管理所有的框架

二、IOC(控制反转)

(一)IOC的概念

控制权从应用程序代码转移到外部容器,由容器负责管理对象的创建和依赖关系。

(二)创建Spring项目

添加依赖

XML 复制代码
<dependencies>
  <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.1.9.RELEASE</version>
  </dependency>

  <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.30</version>
    <scope>provided</scope>
  </dependency>
 </dependencies>

创建spring配置文件:spring1.xml

编辑spring.xml来管理bean

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

    <!--当前的Student类交给了Spring容器去创建-->
    <bean id="stu" class="com.javatest.demo.Student"/>
</beans>

创建Student类

java 复制代码
@Getter
@Setter
public class Student {
    private Integer id;
    private String name;
    private Integer age;
}

测试类

java 复制代码
private static void test1() {
    // 从类加载路径中,加载配置文件spring1.xml
    // 读取配置文件中的内容
    // 解析xml标签
    // 创建一个bean的集合,new一个对象,存入bean的集合等待调用
    // applicationContext 实际上就是Spring容器对象
    // 不论是否调用bean对象,在Spring容器初始化的时候,都会创建bean对象
    ClassPathXmlApplicationContext applicationContext =
        new ClassPathXmlApplicationContext("spring1.xml");
    // 从Spring容器中,寻找id=stu的bean对象
    Student stu= (Student) applicationContext.getBean("stu");
    // 赋值
    stu.setId(100);
    stu.setName("张三");
    stu.setAge(11);
    System.out.println(stu);
}

运行结果:

java 复制代码
----------Student创建了-------------
Student(id=100, name=张三, age=11)

(三)Spring的启动原理

程序启动 → 读取xml文件 → 解析xml配置文件 → 读取了bean标签的内容 → 通过反射,初始化bean对象(new对象) → bean对象 存入Spring容器,等待调用。

代码实现:

java 复制代码
public static void main(String[] args) throws Exception {
    test4();
}
private static void test4() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    Student student = (Student) test3("stu");
    student.setId(10);
    student.setName("张三");
    student.setAge(30);
    System.out.println(student);
    // Student(id=10, name=张三, age=30)
}
private static Object test3(String id) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    Map<String, Object> map = test2();
    Object o = map.get(id);
    return o;
}
private static Map<String, Object> test2() throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
    String id = "stu";
    String className = "com.javatest.demo.Student";
    Class<?> aClass = Class.forName(className);
    Object o = aClass.getConstructor().newInstance();
    Map<String, Object> springApplication = new ConcurrentHashMap<>();
    springApplication.put(id, o);
    return springApplication;
}

运行结果:

java 复制代码
---------------Student对象被创建了---------------
Student(id=10, name=张三, age=30)

(四)Spring中获取bean的三种方式

Studen类:

java 复制代码
@Getter
@Setter
//@ToString
public class Student {
    private Integer id;
    private String name;
    private Integer age;
    public Student(){
        System.out.println("---------------Student对象被创建了---------------");
    }
}

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

    <!--当前的Student类交给了Spring容器去创建-->
    <bean id="stu" class="com.javasm.demo.Student"/>
</beans>

Spring获取bean的三种方式:

java 复制代码
public class Test2 {
    static ClassPathXmlApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("spring1.xml");

    public static void main(String[] args) throws Exception {
        test1();
    }

    /**
     * 获取bean的方式
     */
    private static void test1() {
        // 根据id获取
        Student student = (Student) applicationContext.getBean("stu");
        System.out.println(student);

        // 根据类型获取
        Student student1 = applicationContext.getBean(Student.class);
        System.out.println(student1);

        // 根据id+类型获取
        Student student2 = applicationContext.getBean("stu", Student.class);
        System.out.println(student2);
    }
}

运行结果:

java 复制代码
----------Student创建了-------------
com.javatest.demo.Student@6989da5e
com.javatest.demo.Student@6989da5e
com.javatest.demo.Student@6989da5e

(五)bean别名

XML 复制代码
<!--别名,不常用-->
<alias name="stu" alias="s"/>
java 复制代码
Student s = context.getBean("s", Student.class);

(六)Spring创建bean的几种方式

1.无参构造(最常用)

XML 复制代码
<bean id="stu" class="com.javatest.demo.Student"/>

2.静态工厂创建bean对象

XML 复制代码
<bean id="xiaoming" class="com.javatest.demo.StudentStaticFactory" factory-method="getStudent"/>
java 复制代码
public class StudentStaticFactory {
    public static Student getStudent() {
        Student student = new Student();
        student.setName("小明");
        return student;
    }
}
java 复制代码
private static void test3() {
    Object xiaoming = applicationContext.getBean("xiaoming");
    System.out.println(xiaoming);
    // Student(id=null, name=小明, age=null)
}

3.实例工厂创建bean对象

XML 复制代码
<bean id="stuFactory" class="com.javatest.demo.StudentFactory"/>
<bean id="xiaohong" factory-bean="stuFactory" factory-method="getStudent"/>
java 复制代码
public class StudentFactory {
    public Student getStudent() {
        Student student = new Student();
        student.setName("小红");
        return student;
    }
}
java 复制代码
private static void test4() {
    Object xiaohong = applicationContext.getBean("xiaohong");
    System.out.println(xiaohong);
    // Student(id=null, name=小红, age=null)
}

4.Spring工厂创建bean对象

XML 复制代码
<bean id="huowang" class="com.javatest.demo.StudentSpringFactory"/>
java 复制代码
public class StudentSpringFactory implements FactoryBean<Student> {
    @Override
    public Student getObject() throws Exception {
        //返回的对象是什么,Spring容器中存什么
        Student student = new Student();
        student.setName("李火旺");
        return student;
    }

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

    @Override
    public boolean isSingleton() {
        //是否是单例
        //true:单例
        //false:多例
        //默认是true
        return true;
    }
}
java 复制代码
private static void test5() {
    Object huowang = applicationContext.getBean("huowang");
    System.out.println(huowang);
    Object huowang1 = applicationContext.getBean("huowang");
    System.out.println(huowang1);
    // com.javatest.demo.Student@489115ef
    // com.javatest.demo.Student@489115ef
}

(七)单例

Spring的bean对象,在默认情况下,都是单例的

XML 复制代码
<bean id="teacher" class="com.javasm.demo.Teacher" scope="prototype"/>

单例:Spring启动 → 加载解析XML文件 → 创建Bean对象 →bean保存到容器 →随着容器关闭销毁

多例:Spring启动→加载解析XML文件→先把解析的内容记录下来→调用的时候创建bean

(八)懒加载

不使用不创建对象

仅仅对单例生效:

XML 复制代码
<bean id="teacher1" class="com.javasm.demo.Teacher" lazy-init="true"/>

全局配置:

XML 复制代码
<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"
       default-lazy-init="true"
>

(九)初始化&销毁

java 复制代码
@Getter
@Setter
public class Teacher {
    private Integer id;
    private String name;

    public Teacher(Integer id, String name) {
        this.id = id;
        this.name = name;
    }

    public Teacher() {
        System.out.println("------------Teacher---------");
    }

    public void test1() {
        System.out.println("我是Test1-----------初始化");
    }

    public void test2() {
        System.out.println("我是Test2=============销毁");
    }
}
XML 复制代码
<bean id="teacher2" class="com.javatest.demo.Teacher" init-method="test1" destroy-method="test2"/>
java 复制代码
private static void test7() {
    Object teacher2 = applicationContext.getBean("teacher2");
    System.out.println(teacher2);
    applicationContext.close();
}

执行顺序:

  • 构造方法
  • 初始化方法
  • 正常调用方法
  • ---销毁
  • 关闭容器

三、DI(依赖注入)

(一)DI的概念

通过外部容器将依赖的对象传递给类,而不是让类自己创建或查找依赖,从而实现松耦合。

(二)代码实现

1.实体类

java 复制代码
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Game {
    private Integer id;
    private String name;
    private Double price;
    //公司
    private Company company;
    //英雄列表
    private String[] heros;
    //关卡
    private List<String> levels;
    //背包
    private Map<Integer, String> items;
    //成就
    private Set<String> achievements;
    //游戏配置
    private Properties gameConfig;

    //玩家列表
    private List<Player> playerList;
}
java 复制代码
@Data
public class Company {
    private String name;
    private String address;
}
java 复制代码
@Data
public class Player {
    private Integer id;
    private String nickname;
}

2.spring2.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="game" class="com.javatest.demo2.Game">
        <property name="id" value="1000"/>
        <property name="name" value="黑神话·悟空"/>
        <property name="price" value="648.88"/>
        <!--公司-->
        <property name="company" ref="company"/>

        <!--英雄列表-->
        <property name="heros">
            <array>
                <value>孙悟空</value>
                <value>杨戬</value>
                <value>哪吒</value>
            </array>
        </property>

        <!--关卡列表-->
        <property name="levels">
            <list>
                <value>黑风寨</value>
                <value>黄风岭</value>
                <value>小西天</value>
            </list>
        </property>

        <!--背包列表-->
        <property name="items">
            <map>
                <entry key="1001" value="金箍棒"/>
                <entry key="1002" value="三尖两刃刀"/>
                <entry key="1003" value="定风珠"/>
            </map>
        </property>

        <!--成就列表-->
        <property name="achievements">
            <set>
                <value>借刀杀人</value>
                <value>顺手牵羊</value>
                <value>万箭齐发</value>
            </set>
        </property>

        <!--游戏配置列表-->
        <property name="gameConfig">
            <props>
                <prop key="maxPlayer">100</prop>
                <prop key="maxLevel">120</prop>
            </props>
        </property>

        <!--玩家列表-->
        <property name="playerList">
            <list>
                <bean class="com.javatest.demo2.Player">
                    <property name="id" value="1001"/>
                    <property name="nickname" value="玩家1"/>
                </bean>

                <ref bean="player2"/>
            </list>
        </property>
    </bean>
    <bean id="company" class="com.javatest.demo2.Company">
        <property name="name" value="游戏科学"/>
        <property name="address" value="杭州"/>
    </bean>

    <bean id="player2" class="com.javatest.demo2.Player">
        <property name="id" value="1002"/>
        <property name="nickname" value="玩家2"/>
    </bean>
</beans>

3.测试类

java 复制代码
public class Test {
    static ClassPathXmlApplicationContext applicationContext =
            new ClassPathXmlApplicationContext("spring2.xml");

    public static void main(String[] args) {
        test1();
    }

    private static void test1() {
        Game game = applicationContext.getBean("game", Game.class);
        System.out.println(game);
    }
}

4.运行结果

java 复制代码
Game(id=1000, name=黑神话·悟空, price=648.88, 
company=Company(name=游戏科学, address=杭州), 
heros=[孙悟空, 杨戬, 哪吒], 
levels=[黑风寨, 黄风岭, 小西天], 
items={1001=金箍棒, 1002=三尖两刃刀, 1003=定风珠}, 
achievements=[借刀杀人, 顺手牵羊, 万箭齐发], 
gameConfig={maxLevel=120, maxPlayer=100}, 
playerList=[Player(id=1001, nickname=玩家1), Player(id=1002, nickname=玩家2)])

(三)自动装配

XML 复制代码
<!--autowire 自动装配:byType 根据属性的类型,去Spring容器中寻找对应的bean对象,如果找到了,自动赋值给对应的属性-->
<bean id="g2" class="com.javatest.demo2.Game" autowire="byType"/>
<!--autowire 自动装配:byName 根据属性的名字,去寻找id和属性名一样的bean-->
<bean id="g3" class="com.javatest.demo2.Game" autowire="byName"/>

全局配置:

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"
    default-autowire="byName"
>

(四)构造方法的注入

Music类:

java 复制代码
@Data
public class Music {
    private Integer id;
    private String name;
    private String time;
    private Company company;

    public Music(Integer id, String name, String time, Company company) {
        this.id = id;
        this.name = name;
        this.time = time;
        this.company = company;
    }
}

spring3.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="company" class="com.javatest.demo2.Company">
        <property name="name" value="酷狗音乐"/>
        <property name="address" value="北京"/>
    </bean>
    <!--
        index:构造方法第几个参数
        name: 构造方法的参数名称
        推荐使用index配置参数
    -->
    <bean id="music" class="com.javatest.demo3.Music">
        <constructor-arg name="id" value="100" type="java.lang.Integer"/>
        <constructor-arg index="1" value="云顶天宫"/>
        <constructor-arg index="2" value="10mins"/>
        <constructor-arg index="3" ref="company"/>
    </bean>
</beans>

四、Spring中常见异常

1.bean的id写错了,没有找到名字是stu1的bean对象

2.根据类型,从Spring容器中获取bean对象,但是容器中有两个bean对象,是相同类型的,所以报错

因为要找1个bean,但是发现了2个

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

    <!--当前的Student类交给了Spring容器去创建-->
    <bean id="stu" class="com.javatest.demo.Student"/>
    <bean id="stu1" class="com.javatest.demo.Student"/>
</beans>
java 复制代码
---------------Student对象被创建了---------------
---------------Student对象被创建了---------------
com.javatest.demo.Student@6989da5e
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: 
No qualifying bean of type 'com.javatest.demo.Student' available: 
expected single matching bean but found 2: stu,stu1
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveNamedBean(DefaultListableBeanFactory.java:1144)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveBean(DefaultListableBeanFactory.java:411)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:344)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:337)
	at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:1123)
	at com.javatest.demo.Test2.test1(Test2.java:29)
	at com.javatest.demo.Test2.main(Test2.java:18)

3.类中没有无参构造,报错
要养成一个习惯,只要写有参构造,不论是否需要无参构造,都要写一个

java 复制代码
12月 20, 2024 9:50:48 下午 org.springframework.context.support.AbstractApplicationContext refresh
警告: Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'teacher' defined in class path resource [spring1.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.javatest.demo.Teacher]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.javatest.demo.Teacher.<init>()
Exception in thread "main" java.lang.ExceptionInInitializerError
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'teacher' defined in class path resource [spring1.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.javatest.demo.Teacher]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.javatest.demo.Teacher.<init>()
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1303)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1197)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
	at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
	at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222)
	at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
	at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:845)
	at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:877)
	at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:549)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:144)
	at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:85)
	at com.javatest.demo.Test2.<clinit>(Test2.java:14)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.javatest.demo.Teacher]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.javatest.demo.Teacher.<init>()
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:83)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1295)
	... 13 more
Caused by: java.lang.NoSuchMethodException: com.javatest.demo.Teacher.<init>()
	at java.base/java.lang.Class.getConstructor0(Class.java:3349)
	at java.base/java.lang.Class.getDeclaredConstructor(Class.java:2553)
	at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:78)
	... 14 more

Process finished with exit code 1
相关推荐
夜半被帅醒6 分钟前
MySQL 数据库优化详解【Java数据库调优】
java·数据库·mysql
万亿少女的梦16812 分钟前
基于Spring Boot的网络购物商城的设计与实现
java·spring boot·后端
汤姆和佩琦30 分钟前
2024-12-25-sklearn学习(20)无监督学习-双聚类 料峭春风吹酒醒,微冷,山头斜照却相迎。
学习·聚类·sklearn
醒了就刷牙39 分钟前
黑马Java面试教程_P9_MySQL
java·mysql·面试
好学近乎知o42 分钟前
正则表达式(学习Django过程中可能涉及的)
学习·正则表达式·django
雨中奔跑的小孩1 小时前
爬虫学习案例8
爬虫·学习
m0_748233641 小时前
SQL数组常用函数记录(Map篇)
java·数据库·sql
jieshenai1 小时前
使用 VSCode 学习与实践 LaTeX:从插件安装到排版技巧
ide·vscode·学习
编程爱好者熊浪2 小时前
JAVA HTTP压缩数据
java
吴冰_hogan2 小时前
JVM(Java虚拟机)的组成部分详解
java·开发语言·jvm