Spring入门介绍了Spring框架的基本概念、核心思想以及环境搭建方法,涵盖了控制反转(IoC)和依赖注入(DI)等核心特性。文章详细讲解了如何配置项目环境并创建第一个Spring项目,为初学者提供了全面的指导。
Spring框架简介Spring框架是一个开源的Java平台下的轻量级框架,由Rod Johnson在2003年创建,旨在简化企业应用开发。Spring框架通过其核心容器提供了一套全面的、通用的企业服务,支持面向切面编程(AOP)、数据库事务管理、持久化层集成等功能。Spring框架的设计目标是降低Java EE开发的复杂性,通过使用基本的JavaBean代替EJB,并提供了更多的企业特征。
Spring框架主要通过依赖注入(Dependency Injection,DI)和控制反转(Inversion of Control,IoC)来管理对象依赖关系,使开发人员能够专注于应用逻辑,而不必担心底层框架的复杂性。
控制反转(IoC):IoC意味着对象不是自己创建依赖对象,而是依赖对象由外部容器创建,然后注入到对象中。这是Spring框架的核心特性之一。
依赖注入(DI):DI是指对象的依赖关系通过配置文件或者注解来注入,而不是通过硬编码的方式。Spring框架提供了多种依赖注入的方式,如通过构造器注入、setter方法注入等。
面向切面编程(AOP):Spring框架支持AOP,允许开发者定义一些通用的行为,如日志记录、事务管理等,这些行为可以横切地应用到多个类中,而无需修改这些类的源代码。
Spring框架的最新版本可以在Spring官网下载。截至2023年,Spring框架的最新稳定版本是5.3.18。Spring框架提供了多种下载方式,包括从Maven仓库下载依赖、从Spring官网下载压缩包等。
Spring框架的依赖可以通过Maven或Gradle等构建工具进行管理。以下是如何将Spring框架及其相关依赖添加到Maven项目的pom.xml文件中的示例:
<dependencies> <!-- Spring Core Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.3.18</version> </dependency> <!-- Spring Context Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.3.18</version> </dependency> <!-- Spring AOP Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-aop</artifactId> <version>5.3.18</version> </dependency> <!-- Spring JDBC Dependency --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.3.18</version> </dependency> </dependencies>Spring环境搭建
为了搭建Spring环境,你需要安装以下软件:
创建一个简单的Spring项目可以分为以下几个步骤:
以下是如何创建一个简单的Spring项目的步骤:
创建一个Maven项目:
pom.xml
文件中添加Spring框架的依赖,如上所述。创建一个简单的Java类:
package com.example.demo; public class HelloWorld { private String message; public void setMessage(String message){ this.message = message; } public void getMessage(){ System.out.println("Your Message : " + message); } }
创建Spring配置文件:
src/main/resources
目录下创建一个applicationContext.xml
文件。HelloWorld
类的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/bsn/spring-beans.xsd"> <bean id="helloWorld" class="com.example.demo.HelloWorld"> <property name="message" value="Hello World"/> </bean> </beans>
编写测试代码:
package com.example.demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); obj.getMessage(); } }
MainApp
类中的main
方法,输出结果应为Your Message : Hello World
。在项目中配置Spring环境通常涉及以下几个步骤:
applicationContext.xml
,用于定义Bean及其属性。ApplicationContext
来加载配置文件。ApplicationContext
中获取Bean实例并使用它们。import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); obj.getMessage(); } }Spring核心概念
IoC是Spring框架的核心概念之一,它指的是对象的创建和依赖关系的管理由外部容器来完成,而不是由对象自身来完成。依赖注入是实现IoC的一种方式,通过配置文件或注解将依赖对象注入到需要使用这些依赖的类中。
IoC容器:Spring容器负责创建、配置和管理这些对象的生命周期。容器会负责管理这些对象的创建和销毁,以及它们之间的依赖关系。
以下是如何通过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/bsn/spring-beans.xsd"> <bean id="helloWorld" class="com.example.demo.HelloWorld"> <property name="message" value="Hello World"/> </bean> </beans>
以下是如何通过注解来实现依赖注入的示例:
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class HelloWorld { private String message; @Autowired public HelloWorld() { this.message = "Hello World"; } public void getMessage() { System.out.println("Your Message : " + message); } }
在Spring配置文件中,可以使用<bean>
标签来定义一个Bean。每个<bean>
标签都定义了一个Spring容器可以管理的对象。<bean>
标签的常用属性包括id
、class
、scope
等。
id
:Bean的唯一标识符。class
:Bean对应的Java类。scope
:Bean的作用域,常用的scope有singleton、prototype、request、session等。<bean id="helloWorld" class="com.example.demo.HelloWorld" scope="singleton"> <property name="message" value="Hello World"/> </bean>
Bean的生命周期包括以下几个主要阶段:
init-method
属性定义的方法。destroy-method
属性定义的方法。<bean id="helloWorld" class="com.example.demo.HelloWorld" init-method="init" destroy-method="destroy" scope="singleton"> <property name="message" value="Hello World"/> </bean>
package com.example.demo; import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.DisposableBean; public class HelloWorld implements InitializingBean, DisposableBean { private String message; public HelloWorld() { this.message = "Hello World"; } public void init() throws Exception { System.out.println("Initializing..."); } public void destroy() throws Exception { System.out.println("Destroying..."); } public void getMessage() { System.out.println("Your Message : " + message); } }
AOP允许开发者定义一些通用的行为,如日志记录、事务管理等,这些行为可以横切地应用到多个类中,而无需修改这些类的源代码。
<aop:config> <aop:pointcut id="loggingPointcut" expression="execution(* com.example.demo.*.*(..))"/> <aop:aspect ref="loggingAspect"> <aop:before pointcut-ref="loggingPointcut" method="logBefore"/> <aop:after pointcut-ref="loggingPointcut" method="logAfter"/> </aop:aspect> </aop:config> <bean id="loggingAspect" class="com.example.demo.LoggingAspect"/>
package com.example.demo; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.After; @Aspect public class LoggingAspect { @Before("execution(* com.example.demo.*.*(..))") public void logBefore(JoinPoint joinPoint) { System.out.println("Log before: " + joinPoint.getSignature().getName()); } @After("execution(* com.example.demo.*.*(..))") public void logAfter(JoinPoint joinPoint) { System.out.println("Log after: " + joinPoint.getSignature().getName()); } }
Spring提供了多种注解来简化配置和开发,常用的注解包括@Component
、@Service
、@Repository
、@Controller
、@Autowired
等。
@Component
:用于标记任何Spring组件。@Service
:用于标记业务逻辑组件。@Repository
:用于标记数据访问组件。@Controller
:用于标记控制器组件。@Autowired
:用于自动装配依赖。package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service; import org.springframework.stereotype.Repository; import org.springframework.stereotype.Controller; @Component public class HelloWorld { private String message; @Autowired public HelloWorld() { this.message = "Hello World"; } public void getMessage() { System.out.println("Your Message : " + message); } } @Service public class BusinessService { private HelloWorld helloWorld; @Autowired public BusinessService(HelloWorld helloWorld) { this.helloWorld = helloWorld; } public void performBusinessLogic() { helloWorld.getMessage(); } } @Repository public class DataService { public void fetchData() { System.out.println("Fetching data..."); } } @Controller public class WebController { private BusinessService businessService; @Autowired public WebController(BusinessService businessService) { this.businessService = businessService; } public void handleRequest() { businessService.performBusinessLogic(); } }
Spring支持通过XML配置文件和注解来配置Bean及其依赖关系。
<bean id="helloWorld" class="com.example.demo.HelloWorld" scope="singleton"> <property name="message" value="Hello World"/> </bean>
package com.example.demo; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class HelloWorld { @Value("Hello World") private String message; public void getMessage() { System.out.println("Your Message : " + message); } }Spring与数据库操作
为了使用Spring框架进行数据库操作,需要对数据库配置进行设置。
pom.xml
文件中添加数据库驱动的依赖。<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.26</version> </dependency>
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mydb"/> <property name="username" value="root"/> <property name="password" value="password"/> </bean>
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSource"/> </bean>
package com.example.demo; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.RowMapper; import java.util.List; public class UserDao { private JdbcTemplate jdbcTemplate; public UserDao(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } public List<User> getAllUsers() { String sql = "SELECT * FROM users"; return jdbcTemplate.query(sql, new RowMapper<User>() { @Override public User mapRow(ResultSet rs, int rowNum) throws SQLException { User user = new User(); user.setId(rs.getInt("id")); user.setName(rs.getString("name")); user.setEmail(rs.getString("email")); return user; } }); } public void addUser(User user) { String sql = "INSERT INTO users (name, email) VALUES (?, ?)"; jdbcTemplate.update(sql, user.getName(), user.getEmail()); } public void updateUser(User user) { String sql = "UPDATE users SET name = ?, email = ? WHERE id = ?"; jdbcTemplate.update(sql, user.getName(), user.getEmail(), user.getId()); } public void deleteUser(int id) { String sql = "DELETE FROM users WHERE id = ?"; jdbcTemplate.update(sql, id); } }
package com.example.demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import java.util.List; public class UserDaoTest { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); UserDao userDao = context.getBean(UserDao.class); userDao.addUser(new User(1, "John Doe", "john.doe@example.com")); userDao.addUser(new User(2, "Jane Doe", "jane.doe@example.com")); List<User> users = userDao.getAllUsers(); for (User user : users) { System.out.println(user); } userDao.updateUser(new User(1, "John Smith", "john.smith@example.com")); userDao.deleteUser(2); } }
Spring框架提供了多种事务管理方式,包括编程式事务和声明式事务。
编程式事务管理是通过编码方式来显式地控制事务的边界。这种方式需要在代码中显式地编写事务开始、提交和回滚的逻辑。
package com.example.demo; import org.springframework.jdbc.datasource.DataSourceTransactionManager; import org.springframework.jdbc.support.JdbcTransactionManager; import org.springframework.transaction.TransactionStatus; import org.springframework.transaction.support.DefaultTransactionStatus; public class TransactionManagerExample { private DataSourceTransactionManager transactionManager; public void performTransaction() { TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionStatus(true)); try { // 执行数据库操作 transactionManager.commit(status); } catch (Exception e) { transactionManager.rollback(status); throw e; } } }
声明式事务管理是通过配置文件或注解的方式来声明事务属性,而无需在代码中显式地编写事务处理逻辑。
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <tx:annotation-driven transaction-manager="transactionManager"/>
@Transactional
注解来声明事务属性。package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.transaction.annotation.Transactional; public class UserService { private JdbcTemplate jdbcTemplate; @Autowired public UserService(JdbcTemplate jdbcTemplate) { this.jdbcTemplate = jdbcTemplate; } @Transactional public void addUser(User user) { String sql = "INSERT INTO users (name, email) VALUES (?, ?)"; jdbcTemplate.update(sql, user.getName(), user.getEmail()); } }实战案例
<?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/bsn/spring-beans.xsd"> <bean id="helloWorld" class="com.example.demo.HelloWorld"> <property name="message" value="Hello World"/> </bean> </beans>
package com.example.demo; public class HelloWorld { private String message; public void setMessage(String message) { this.message = message; } public void getMessage() { System.out.println("Your Message : " + message); } }
package com.example.demo; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); obj.getMessage(); } }
package com.example.demo; import org.junit.jupiter.api.Test; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import static org.junit.jupiter.api.Assertions.assertEquals; public class HelloWorldTest { @Test public void testHelloWorld() { ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml"); HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); obj.getMessage(); assertEquals("Hello World", obj.message); } }
<bean id="helloWorld" class="com.example.demo.HelloWorld"> <property name="message" value="Hello World"/> </bean> <bean id="businessService" class="com.example.demo.BusinessService"> <property name="helloWorld" ref="helloWorld"/> </bean>
package com.example.demo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class BusinessService { private HelloWorld helloWorld; @Autowired public BusinessService(HelloWorld helloWorld) { this.helloWorld = helloWorld; } public void performBusinessLogic() { helloWorld.getMessage(); } }