Java学习笔记

个人技术成长之路

Spring核心

Spring框架是Java平台的一个开源应用框架,提供了一个简易的开发方式,通过依赖注入和面向切面编程,用简单的Java对象(POJO)实现了企业级应用的功能。

IoC容器

控制反转(Inversion of Control,IoC)是Spring框架的核心。IoC容器负责创建对象,管理对象(通过依赖注入),装配对象,配置对象,并管理这些对象的整个生命周期。

// 定义一个简单的服务接口
public interface MessageService {
    String getMessage();
}

// 实现服务接口
public class MessageServiceImpl implements MessageService {
    @Override
    public String getMessage() {
        return "Hello, Spring!";
    }
}

// 使用XML配置
<beans>
    <bean id="messageService" class="com.example.MessageServiceImpl"/>
</beans>

// 使用Java配置
@Configuration
public class AppConfig {
    @Bean
    public MessageService messageService() {
        return new MessageServiceImpl();
    }
}

依赖注入

依赖注入(Dependency Injection,DI)是IoC的一种实现方式,它允许对象在被创建时,动态地注入它所依赖的对象。

// 定义一个依赖于MessageService的类
public class MessagePrinter {
    private final MessageService service;
    
    // 构造函数注入
    @Autowired
    public MessagePrinter(MessageService service) {
        this.service = service;
    }
    
    public void printMessage() {
        System.out.println(service.getMessage());
    }
}

// 使用XML配置
<beans>
    <bean id="messageService" class="com.example.MessageServiceImpl"/>
    <bean id="messagePrinter" class="com.example.MessagePrinter">
        <constructor-arg ref="messageService"/>
    </bean>
</beans>

// 使用Java配置
@Configuration
public class AppConfig {
    @Bean
    public MessageService messageService() {
        return new MessageServiceImpl();
    }
    
    @Bean
    public MessagePrinter messagePrinter() {
        return new MessagePrinter(messageService());
    }
}

面向切面编程

面向切面编程(Aspect-Oriented Programming,AOP)允许将横切关注点(如日志记录、事务管理)与业务逻辑分离。

// 定义一个切面
@Aspect
@Component
public class LoggingAspect {
    
    // 定义一个切点
    @Pointcut("execution(* com.example.service.*.*(..))") 
    public void serviceMethods() {}
    
    // 前置通知
    @Before("serviceMethods()")
    public void logBefore(JoinPoint joinPoint) {
        System.out.println("Before method: " + joinPoint.getSignature().getName());
    }
    
    // 后置通知
    @After("serviceMethods()")
    public void logAfter(JoinPoint joinPoint) {
        System.out.println("After method: " + joinPoint.getSignature().getName());
    }
}

注意:要使用Spring AOP,需要添加spring-aop依赖,并在配置类上添加@EnableAspectJAutoProxy注解。

Spring MVC

Spring MVC是Spring框架的一个模块,提供了构建Web应用程序的模型-视图-控制器(MVC)架构。

MVC架构

MVC架构将应用程序分为三个主要部分:

  • 模型(Model):表示应用程序的数据和业务逻辑
  • 视图(View):负责数据的可视化展示
  • 控制器(Controller):处理用户请求并调用模型和视图

控制器示例

@Controller
public class HelloController {
    
    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("message", "Hello, Spring MVC!");
        return "hello"; // 视图名称
    }
    
    @GetMapping("/greeting")
    @ResponseBody
    public String greeting(@RequestParam(name="name", required=false, defaultValue="World") String name) {
        return "Hello, " + name + "!";
    }
}

RESTful API

Spring MVC提供了构建RESTful Web服务的强大支持。

@RestController
@RequestMapping("/api/users")
public class UserController {
    
    private final UserService userService;
    
    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }
    
    @GetMapping
    public List getAllUsers() {
        return userService.findAll();
    }
    
    @GetMapping("/{id}")
    public User getUser(@PathVariable Long id) {
        return userService.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found with id: " + id));
    }
    
    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public User createUser(@RequestBody User user) {
        return userService.save(user);
    }
    
    @PutMapping("/{id}")
    public User updateUser(@PathVariable Long id, @RequestBody User user) {
        user.setId(id);
        return userService.update(user);
    }
    
    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void deleteUser(@PathVariable Long id) {
        userService.deleteById(id);
    }
}

Spring Boot

Spring Boot是Spring框架的扩展,简化了Spring应用的初始搭建和开发过程。它采用了"约定优于配置"的原则,大大减少了开发人员的配置工作。

特点

  • 自动配置:Spring Boot自动配置Spring应用程序,减少了手动配置的需要
  • 独立运行:Spring Boot应用可以独立运行,不需要外部的Web服务器
  • 内嵌服务器:内置Tomcat、Jetty或Undertow,无需部署WAR文件
  • Starter依赖:简化构建配置,提供针对不同场景的starter依赖

创建Spring Boot应用

使用Spring Initializr(https://start.spring.io)可以快速创建Spring Boot项目。

// 一个简单的Spring Boot应用
@SpringBootApplication
public class MyApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(MyApplication.class, args);
    }
}

配置

Spring Boot使用application.properties或application.yml文件进行配置。

# application.properties示例
server.port=8080
spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password

# application.yml示例
server:
  port: 8080
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mydb
    username: root
    password: password

Spring Data

Spring Data是Spring的一个子项目,旨在简化数据库访问,支持关系型数据库和非关系型数据库。

Spring Data JPA

Spring Data JPA简化了JPA(Java Persistence API)的使用,只需定义接口,无需编写实现类。

// 实体类
@Entity
public class User {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    private String email;
    
    // 构造函数、getter和setter
}

// 仓库接口
public interface UserRepository extends JpaRepository {
    
    // 自定义查询方法
    List findByName(String name);
    
    User findByEmail(String email);
    
    // 使用@Query注解
    @Query("SELECT u FROM User u WHERE u.email LIKE %:domain%")
    List findByEmailDomain(@Param("domain") String domain);
}

使用示例

@Service
public class UserService {
    
    private final UserRepository userRepository;
    
    @Autowired
    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }
    
    public List getAllUsers() {
        return userRepository.findAll();
    }
    
    public User getUserById(Long id) {
        return userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found"));
    }
    
    public User createUser(User user) {
        return userRepository.save(user);
    }
}

Spring Security

Spring Security是Spring框架的安全模块,提供了认证、授权和防护功能。

基本配置

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/", "/home").permitAll()
                .antMatchers("/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .and()
            .logout()
                .permitAll();
    }
    
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .inMemoryAuthentication()
                .withUser("user").password("{noop}password").roles("USER")
                .and()
                .withUser("admin").password("{noop}admin").roles("USER", "ADMIN");
    }
}

方法级安全

Spring Security支持方法级别的安全控制。

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
    // 配置
}

@Service
public class UserService {
    
    @PreAuthorize("hasRole('ADMIN')")
    public List getAllUsers() {
        // 只有ADMIN角色才能访问
        return userRepository.findAll();
    }
    
    @PreAuthorize("#id == authentication.principal.id or hasRole('ADMIN')")
    public User getUserById(Long id) {
        // 只有当前用户或ADMIN角色才能访问
        return userRepository.findById(id)
                .orElseThrow(() -> new ResourceNotFoundException("User not found"));
    }
}

Spring Boot 3.0新特性

Spring Boot 3.0是一个重要的版本更新,带来了许多新特性和改进。

Java 17支持

Spring Boot 3.0要求Java 17作为最低版本,充分利用了Java 17的新特性。

Jakarta EE 9+支持

Spring Boot 3.0从javax.*命名空间迁移到了jakarta.*命名空间。

// Spring Boot 2.x
import javax.persistence.Entity;
import javax.persistence.Id;

// Spring Boot 3.x
import jakarta.persistence.Entity;
import jakarta.persistence.Id;

原生镜像支持

Spring Boot 3.0提供了对GraalVM原生镜像的一流支持,可以将Spring应用编译成原生可执行文件,大大减少启动时间和内存占用。

// 使用Spring Boot插件构建原生镜像
./mvnw spring-boot:build-image

HTTP接口客户端

Spring Boot 3.0引入了新的声明式HTTP客户端,简化了HTTP API的调用。

// 定义HTTP接口
public interface GitHubClient {
    
    @GetExchange("/repos/{owner}/{repo}")
    RepositoryInfo getRepository(@PathVariable String owner, @PathVariable String repo);
    
    @GetExchange("/users/{username}/repos")
    List listRepositories(@PathVariable String username);
}

// 使用HTTP接口
@Service
public class GitHubService {
    
    private final GitHubClient client;
    
    public GitHubService(WebClient.Builder builder) {
        WebClient webClient = builder.baseUrl("https://api.github.com").build();
        HttpServiceProxyFactory factory = HttpServiceProxyFactory.builder(WebClientAdapter.forClient(webClient)).build();
        this.client = factory.createClient(GitHubClient.class);
    }
    
    public RepositoryInfo getRepository(String owner, String repo) {
        return client.getRepository(owner, repo);
    }
}

可观测性增强

Spring Boot 3.0改进了可观测性支持,包括Micrometer和Micrometer Tracing的集成。

// 添加可观测性依赖
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-prometheus</artifactId>
</dependency>

提示:Spring Boot 3.0的变化较大,从Spring Boot 2.x迁移时需要注意命名空间的变化和最低Java版本要求。