Spring之通过一个入门小工程来了解Spring
项目结构
创建Empty Project
修改工程JDK
创建完spring6的空工程之后,将这里改为JDK17。否则创建的module默认不是JDK17,就会报各种错误。
在空工程里面创建一个Module
详细代码
User类
package com.xu.entity;
public class User {
}
beans.xml配置文件
注意:
- 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);
}
}
运行结果:
- 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。
- 代码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();
}
- 可以一次性读取多个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);
}
- ClassPathXmlApplicationContext是从类路径中加载配置文件,如果配置文件不在类路径当中,又应该如何加载配置文件呢?
@Test
public void test4(){
ApplicationContext applicationContext = new FileSystemXmlApplicationContext("D:\\3_study\\1.coding\\external.xml");
Object userDaoBean = applicationContext.getBean("userDaoBean", UserDaoImplForMySQL.class);
}
-
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类的无参构造方法执行了~~~");
}
}