Spring之通过一个入门小工程来了解Spring

项目结构

image-20241122072335900

创建Empty Project

image-20241122071507639

修改工程JDK

创建完spring6的空工程之后,将这里改为JDK17。否则创建的module默认不是JDK17,就会报各种错误。

image-20241122071558858

image-20241122071638137

在空工程里面创建一个Module

image-20241122071929943

详细代码

User类

package com.xu.entity;

public class User {
}

beans.xml配置文件

注意:

  1. bean的id不能重复, 这个id就相当于是bean的身份证号。
<?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.xu.entity.User"/>
</beans>

FirstTest测试类

package com.xu.test;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class FirstTest {
    @Test
    public void testFirst() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
        Object user = applicationContext.getBean("user");
        System.out.println(user); //运行结果:com.xu.entity.User@7f0eb4b4
                                  //说明Spring容器帮我们成功创建出来了User对象
    }
}

代码细节剖析

1. 底层是如何创建的User对象?是通过反射机制调用的无参构造函数吗?

答:是

如何通过反射机制获取对象?

package com.xu.entity;

public class User {
    public User() {
        System.out.println("User类的无参构造方法执行了~");
    }
}
@Test
public void testReflect() {
    try {
        Class<?> aClass = Class.forName("com.xu.entity.User");
        System.out.println(aClass.newInstance());
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

运行结果:

image-20241122191248720

  1. Spring beans.xml里面的class可以配置抽象类吗?

答:不可以

  • 如何理解下面这句代码中的abstract="true"
<bean id="abstractClass" class="com.xu.entity.AbstractClass" abstract="true"/>
  • 在Spring的beans.xml配置文件中,标签的abstract属性用于定义一个抽象的bean。将abstract属性设置为true表示该bean是抽象的,不能直接实例化。具体含义如下:
    抽象的bean无法被直接实例化,它只作为其他非抽象bean的父类或模板,它可以提供一些通用的配置或方法,供子类或其他具体的bean继承和使用,抽象bean可以包含一些通用的属性或方法,但它们没有具体的实现,需要子类或具体的bean来提供实现。
    抽象bean可以被其他非抽象的bean继承,继承后的子类bean可以继承父类bean的属性和方法,并可以覆盖或补充父类的实现。通过定义抽象bean,可以实现代码的重用和封转通用逻辑的目的。它提供了一种模板化的方式,允许其他具体的bean来继承和扩展。
    在配置文件中,抽象bean的定义通常用于作为其他具体bean的基类或模板,而不能直接实例化为一个独立的bean。因此,抽象bean的abstract属性被设置为true,以标识它是一个抽象的概念, 而不是一个具体的可实例化的bean。
  1. 代码3.1中,getBean()方法返同的类型是Object。这个时候,如果我想要访问子类的特有属性和方法时,还需要向下转型,有其它办法可以优化这个问题吗?

代码3.1:

@Test
public void testFirst() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
    Object user = applicationContext.getBean("user");
    System.out.println(user);
}

答:有,可以调用getBean的另外一种实现方式。请看代码3.2

代码3.2:

UserDaoImplForMySQL类中有一个特有的方法getUserList

public class UserDaoImplForMySQL {
    public void getUserList(){
        System.out.println("获取用户列表方法执行了~");
    }
}

通过下面这种方式可以直接获取到UserDaoImplForMySQL类型的对象userDao

通过userDao可以直接访问UserDaoImplForMySQL类的特有方法getUserList

@Test
public void test2() {
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
    UserDaoImplForMySQL userDao = applicationContext.getBean("userDaoBean", UserDaoImplForMySQL.class);
    userDao.getUserList();
}
  1. 可以一次性读取多个bean的xml文件吗?

答:可以

在beans.xml中声明一个id为user的bean,在spring.xml中声明一个id为vip的bean。通过如下代码同时读取两个配置文件。

@Test
public void test3(){
    ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml", "spring.xml");
    User user = applicationContext.getBean("user", User.class);

    Vip vip = applicationContext.getBean("vip", Vip.class);
}

image-20241122193905219

  1. ClassPathXmlApplicationContext是从类路径中加载配置文件,如果配置文件不在类路径当中,又应该如何加载配置文件呢?
@Test
public void test4(){
    ApplicationContext applicationContext = new FileSystemXmlApplicationContext("D:\\3_study\\1.coding\\external.xml");
    Object userDaoBean = applicationContext.getBean("userDaoBean", UserDaoImplForMySQL.class);
}

image-20241122194619908

  1. ApplicationContext的超级父接口BeanFactory。

    可以直接用BeanFactory来定义对象

@Test
public void test5() {
    BeanFactory beanFactory = new ClassPathXmlApplicationContext("beans.xml");
    Object user = beanFactory.getBean("user");
    System.out.println(user); //com.xu.entity.User@5c33f1a9
}

启用Log4j2日志框架

引入Log4j2依赖

<!--log4j2的依赖-->
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.19.0</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j2-impl</artifactId>
    <version>2.19.0</version>
</dependency>

新建log4j2.xml文件(文件必须放到根路径下,名字固定为log4j2.xml)

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
    <loggers>
        <!--
            level指定日志级别,从低到高的优先级:
                ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFF
        -->
        <root level="DEBUG">
            <appender-ref ref="spring6log"/>
        </root>
    </loggers>

    <appenders>
        <!--输出日志信息到控制台-->
        <console name="spring6log" target="SYSTEM_OUT">
            <!--控制日志输出的格式-->
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss SSS} [%t] %-3level %logger{1024} - %msg%n"/>
        </console>
    </appenders>
</configuration>

使用日志框架

public class UserDaoImplForMySQL {
    Logger logger = LoggerFactory.getLogger(UserDaoImplForMySQL.class);

    public UserDaoImplForMySQL() {
        logger.info("UserDaoImplForMySQL类的无参构造方法执行了~~~");
    }
}

image-20241122200628741

posted @ 2024-11-22 07:32  growingbambi  阅读(19)  评论(0)    收藏  举报