1.Spring基础知识介绍
Spring是一个轻量级的Java EE开源框架,旨在简化企业级应用程序的开发。它提供了全面的基础设施支持,通过控制反转(IoC)和面向切面编程(AOP)等核心技术,帮助开发者实现松耦合、高内聚的应用程序架构。
-
Spring的核心模块:
- IoC(控制反转):IoC是Spring框架的核心思想之一,它通过将对象的创建和依赖关系的维护交给Spring容器来管理,实现了对象之间的松耦合。开发者只需要通过配置文件或注解来声明对象及其依赖关系,Spring容器会自动创建对象并注入依赖。
- AOP(面向切面编程):AOP是Spring框架的另一个重要特性,它允许开发者在不修改源代码的情况下,为程序添加额外的行为(如日志记录、事务管理等)。AOP通过将横切关注点(如日志、事务等)封装成切面,并将其应用到目标对象上,从而实现了代码的解耦和复用。
-
Spring的优点:
- 轻量级:Spring框架的jar包较小,运行占用资源少,效率高。
- 松耦合:通过IoC和AOP等技术,Spring实现了对象之间的松耦合,提高了系统的可维护性和可扩展性。
- 面向切面编程支持:Spring提供了强大的AOP支持,方便开发者进行面向切面的编程。
- 支持多种优秀框架:Spring能够与其他优秀的开源框架(如Struts、Hibernate、MyBatis等)无缝集成,降低了开发难度。
- 声明式事务管理:Spring提供了声明式事务管理,通过配置即可实现对事务的管理,无需手动编程。
-
Spring的体系结构:
- Core Container(核心容器):包括Beans模块、Core模块、Context模块等,提供了Spring框架的基本功能。
- Data Access/Integration(数据访问/集成):包括JDBC、ORM、OXM等模块,提供了对数据库和其他数据源的访问支持。
- Web:包括WebSocket、Servlet、Web和Portlet模块,提供了创建Web应用程序的支持。
- 其他模块:如AOP、Aspects、Instrumentation、Messaging、Test等,提供了面向切面编程、类工具支持、消息传递、测试等功能。
关键常用技术总结
-
IoC容器的使用:
- BeanFactory:是Spring IoC容器的最基础接口,提供了基本的容器功能。
- ApplicationContext:是BeanFactory的子接口,提供了更丰富的功能,如事件传播、国际化支持等。
- Bean的创建和配置:可以通过XML配置文件或注解来声明Bean及其依赖关系。Spring容器会自动读取配置文件或注解,并创建Bean对象,注入依赖。
-
AOP的应用:
- 切面(Aspect):定义了横切关注点的行为。
- 连接点(Joinpoint):是程序执行过程中能够插入切面的点。
- 通知(Advice):是切面在特定连接点执行的动作。
- 切入点(Pointcut):定义了哪些连接点会被切面拦截。
- Spring AOP的实现方式:可以通过XML配置文件或注解来定义切面、连接点、通知和切入点。
-
事务管理:
- 声明式事务管理:通过配置即可实现对事务的管理,无需手动编程。Spring提供了对编程式事务和声明式事务的支持。
- 事务的传播行为:定义了事务在不同方法调用之间的传播方式,如REQUIRED、REQUIRES_NEW等。
- 事务的隔离级别:定义了事务之间的隔离程度,如ISOLATION_DEFAULT、ISOLATION_READ_COMMITTED等。
-
Spring MVC:
- Spring MVC是Spring提供的用于构建Web应用程序的MVC框架。它通过将应用程序分为模型(Model)、视图(View)和控制器(Controller)三个部分,实现了职责的分离和代码的解耦。
- Spring MVC的核心组件:包括DispatcherServlet(前端控制器)、HandlerMapping(处理器映射器)、HandlerAdapter(处理器适配器)、ViewResolver(视图解析器)等。
2. IoC容器示例
XML配置方式
配置文件(applicationContext.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">
<bean id="myService" class="com.example.MyService"/>
<bean id="myController" class="com.example.MyController">
<property name="service" ref="myService"/>
</bean>
</beans>
Java类:
public class MyService {
public void doSomething() {
System.out.println("Service is doing something");
}
}
public class MyController {
private MyService service;
public void setService(MyService service) {
this.service = service;
}
public void execute() {
service.doSomething();
}
}
// 主程序
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
MyController controller = (MyController) context.getBean("myController");
controller.execute();
}
}
注解配置方式
Java类(使用注解):
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Controller;
@Component
public class MyService {
public void doSomething() {
System.out.println("Service is doing something");
}
}
@Controller
public class MyController {
@Autowired
private MyService service;
public void execute() {
service.doSomething();
}
}
// 配置类
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.example")
public class AppConfig {
}
// 主程序(使用注解配置)
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MyController controller = context.getBean(MyController.class);
controller.execute();
}
}
AOP示例
切面类:
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class LoggingAspect {
@Before("execution(* com.example..*(..))")
public void logBefore() {
System.out.println("Executing method...");
}
}
配置类(添加AOP启用):
import org.springframework.context.annotation.EnableAspectJAutoProxy;
@Configuration
@EnableAspectJAutoProxy
@ComponentScan(basePackages = "com.example")
public class AppConfigWithAop {
}
事务管理示例
服务类:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
public class MyTransactionalService {
@Autowired
private MyRepository repository;
@Transactional
public void performTransaction() {
// 执行数据库操作
repository.save(...);
// 如果抛出异常,则事务回滚
}
}
配置类(添加事务管理器):
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import javax.persistence.EntityManagerFactory;
import javax.sql.DataSource;
@Configuration
@EnableTransactionManagement
public class AppConfigWithTransaction {
@Bean
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");
dataSource.setUsername("user");
dataSource.setPassword("password");
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(dataSource());
em.setPackagesToScan(new String[] { "com.example.domain" });
em.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
return em;
}
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(entityManagerFactory);
return transactionManager;
}
}
Spring MVC控制器示例
控制器类:
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class MyController {
@GetMapping("/hello")
public String hello(Model model) {
model.addAttribute("message", "Hello, World!");
return "hello"; // 返回视图名
}
}
配置类(Spring Boot风格,如果使用Spring Boot则无需此配置,因为它默认启用了Spring MVC):
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@EnableWebMvc
public class WebConfig {
@Bean
public InternalResourceViewResolver viewResolver() {
InternalResourceViewResolver resolver = new InternalResourceViewResolver();
resolver.setPrefix("/WEB-INF/views/");
resolver.setSuffix(".jsp");
return resolver;
}
}
3.Spring缺点
Spring框架作为Java开发中广泛使用的企业级应用框架,尽管具有众多优点,但也存在一些缺点。以下是对Spring框架缺点的详细归纳:
一、学习曲线陡峭
- 复杂性高:Spring框架本身非常庞大且复杂,包含了多个模块和功能,如核心容器、数据访问、Web、AOP等。初学者需要花费较多的时间和精力来理解和掌握这些模块和功能。
- 概念繁多:Spring框架引入了许多新的概念和术语,如IoC(控制反转)、AOP(面向切面编程)等,这些概念对于没有经验的开发者来说可能较为抽象和难以理解。
二、配置复杂繁琐
- XML配置:Spring框架的传统配置方式是基于XML文件的,这种方式需要编写大量的XML代码来定义Bean、AOP、事务等。随着应用程序规模的扩大,XML配置文件可能会变得冗长而复杂,增加了维护的难度。
- 注解配置:虽然Spring也支持基于注解的配置方式,但注解的使用也需要一定的学习和理解成本,且在某些情况下可能仍然需要结合XML配置。
三、运行时性能开销
- 依赖注入开销:Spring通过IoC容器管理对象之间的依赖关系,提供了灵活的对象创建和管理机制。然而,在运行时进行大量的对象创建和依赖注入操作可能会增加一定的性能开销,尤其是在应用启动时。
- AOP开销:Spring的AOP功能也需要在运行时进行额外的处理,如代理对象的创建和切面的织入等,这些操作同样会带来一定的性能损失。
四、过度依赖问题
- 框架耦合度高:由于Spring框架的强大功能和广泛应用,许多开发者可能会过度依赖于它,导致应用代码与Spring框架的耦合度较高。这可能会使得在需要替换其他框架或进行版本升级时面临较大的改动和重构成本。
- 第三方依赖多:Spring框架依赖于大量的第三方库和组件,这可能会导致版本冲突和依赖管理问题。在使用Spring时,开发者需要仔细管理这些依赖项,以避免出现不必要的问题。
五、文档和社区支持问题
- 文档质量参差不齐:尽管Spring框架有大量的文档和教程可供学习和参考,但其中部分文档可能存在质量参差不齐的问题。一些文档可能已过时或者不完整,这给学习和使用者带来了一定的困扰。
- 社区支持差异:虽然Spring框架有一个广泛的开发社区,但社区中的支持和帮助质量可能因个人经验和专业知识的不同而有所差异。在某些情况下,开发者可能难以找到特定问题的答案或得到最新的技术支持。