我的Java-Web进阶--Spring

1.Spring框架概述

2.IOC控制反转(非注解版)

 

IOC的基础操作 

Spring的IoC(Inversion of Control,控制反转)是Spring框架的核心特性之一。它允许对象在创建时由一个调节器对象或服务提供它们的依赖,而不是通过硬编码的方式创建这些依赖。这促进了松耦合的设计,使得应用程序更易于测试和维护。

下面我将按照您的要求介绍如何使用XML配置方式来实现Spring的IoC基础操作,并给出实例代码。

1. 创建相关类

首先,我们创建几个简单的Java类,这些类将作为Spring容器中的Bean。

// User.java
package com.example;

public class User {
    private String name;
    private int age;
    private String[] hobbies;

    // Constructors, getters and setters
    public User() {}

    public User(String name, int age, String[] hobbies) {
        this.name = name;
        this.age = age;
        this.hobbies = hobbies;
    }

    @Override
    public String toString() {
        return "User{name='" + name + "', age=" + age + ", hobbies=" + String.join(", ", hobbies) + "}";
    }
}

2. 添加Spring的XML配置文件

接下来,我们需要创建一个Spring的XML配置文件来定义Bean。这个文件通常位于src/main/resources目录下,命名为applicationContext.xml

<!-- applicationContext.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/beans/spring-beans.xsd">

    <!-- Bean definition for User with constructor arguments -->
    <bean id="user" class="com.example.User">
        <constructor-arg value="John Doe" type="String"/>
        <constructor-arg value="30" type="int"/>
        <constructor-arg>
            <array>
                <value>Reading</value>
                <value>Hiking</value>
                <value>Coding</value>
            </array>
        </constructor-arg>
    </bean>

</beans>

在这个配置文件中,我们定义了一个名为user的Bean,它使用了User类的构造函数进行初始化。这里展示了如何为构造函数参数传递Stringint以及String[]类型的值。

3. 注册Bean并使用

最后,我们需要编写一些Java代码来加载Spring上下文并获取Bean实例。

// MainApp.java
package com.example;

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

public class MainApp {
    public static void main(String[] args) {
        // Load Spring configuration file
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");

        // Retrieve bean from Spring container
        User user = (User) context.getBean("user");

        // Print out the retrieved bean
        System.out.println(user);
    }
}

这段代码创建了一个ClassPathXmlApplicationContext实例,它会从类路径下加载applicationContext.xml配置文件。然后,我们使用getBean方法根据ID检索User类型的Bean,并将其打印出来。

XML的Bean对象的参数设置

property

property通过调用类的setter方法进行参数设置

constructor-arg

constructor-arg通过调用构造方法给对象赋值

 

constructor-arg用于集合注入

 Bean对象生命周期

 

 3.IOC控制反转(半注解版)

Spring框架的注解开发是一种基于元数据的配置方式,它允许开发者通过在类、方法或字段上添加注解来替代XML配置。这种方式不仅简化了配置,还使得代码更加清晰和易于维护。以下是几个常用的Spring注解及其用途。

Bean对象池查询

 

Bean对象创建@Component

不写@Component里面的id,默认把类型作为id 

简单的数据类型传参@Value

 对象类型数据传参@Autowired,@Qualified,@Resource

@Autowired

@Autowired 用于自动装配依赖,它可以通过构造函数、setter方法或直接在字段上使用。默认情况下,@Autowired是基于类型进行匹配的。如果容器中有多个相同类型的Bean,而没有指定具体的Bean,则可能会抛出异常。

package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class ServiceA {

    private final Repository repository;

    // 构造器注入
    @Autowired
    public ServiceA(Repository repository) {
        this.repository = repository;
    }

    // 使用服务
    public void useService() {
        System.out.println("Using " + repository);
    }
}

@Qualifier

@Qualifier@Autowired 一起使用,当有多个相同类型的Bean时,可以通过名称明确指定要注入哪个Bean。这解决了类型匹配时可能存在的歧义问题。

package com.example;

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

@Component
public class ServiceB {

    private final Repository specificRepository;

    // 构造器注入,并使用 @Qualifier 指定特定的 Bean
    @Autowired
    public ServiceB(@Qualifier("specificRepository") Repository specificRepository) {
        this.specificRepository = specificRepository;
    }

    // 使用服务
    public void useService() {
        System.out.println("Using " + specificRepository);
    }
}

@Resource

@Resource 是Java EE提供的注解,也支持按名称进行依赖注入。它首先尝试根据名称查找Bean,如果找不到,则回退到按类型查找。因此,它总是优先考虑名字匹配,这与@Autowired的行为有所不同。

package com.example;

import javax.annotation.Resource;
import org.springframework.stereotype.Component;

@Component
public class ServiceC {

    // 字段注入,使用@Resource按名称查找
    @Resource(name="specificRepository")
    private Repository specificRepository;

    // 使用服务
    public void useService() {
        System.out.println("Using " + specificRepository);
    }
}

理解:Spring把注册的对象都放到一个对象池里面,通过id匹配

@Autowired注解只通过匹配相同对象类型的方式,创建某一大对象的时候,把相同参数的小对象作为参数传递

@Qualified注解通过匹配id的方式,把匹配到的小对象赋值给大对象

@Resource注解先匹配id,如果匹配不到则匹配相同类型的

Bean对象生命周期@Scope

4.IOC控制反转(全注解版)

Bean对象池查询

 5.AOP面向切面编程

面向切面编程(AOP, Aspect-Oriented Programming)是Spring框架中的一个重要特性,它允许你将横切关注点(如日志记录、事务管理、安全性等)从业务逻辑中分离出来。AOP通过在方法执行前后插入额外的行为来实现这一点,而不需要修改原有代码。使用基于注解的AOP配置可以简化配置过程,并使代码更加清晰和易于维护。

AOP 基于注解的使用方法

1. 引入依赖

首先,确保你的项目包含了必要的Spring AOP依赖。如果你使用的是Maven,可以在pom.xml中添加以下依赖:

<dependencies>
    <!-- Spring AOP -->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>5.3.10</version> <!-- 使用与你的项目兼容的版本 -->
    </dependency>

    <!-- 如果需要使用AspectJ编译器 -->
    <dependency>
        <groupId>org.aspectj</groupId>
        <artifactId>aspectjweaver</artifactId>
        <version>1.9.7</version> <!-- 使用与你的项目兼容的版本 -->
    </dependency>
</dependencies>
2. 启用AOP支持

为了让Spring能够识别和处理AOP注解,你需要在配置类上启用AOP支持。这可以通过在配置类上添加@EnableAspectJAutoProxy注解来完成。

package com.example.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

@Configuration
@EnableAspectJAutoProxy
public class AppConfig {
    // 配置类内容
}
3. 创建切面类(重点)

接下来,创建一个切面类,并使用@Aspect注解将其标记为一个切面。在这个类中,你可以定义各种通知(Advice),比如@Before, @After, @Around, @AfterReturning, 和 @AfterThrowing,它们分别对应于方法执行前、后、环绕、成功返回后和抛出异常后。

package com.example.aspect;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // 定义切入点表达式
    @Pointcut("execution(* com.example.service.*.*(..))")
    public void serviceLayer() {}

    // 在服务层方法执行前记录日志
    @Before("serviceLayer()")
    public void logBefore() {
        System.out.println("Logging before method execution.");
    }

    // 在服务层方法执行后记录日志
    @After("serviceLayer()")
    public void logAfter() {
        System.out.println("Logging after method execution.");
    }
}
4. 定义业务逻辑类

现在,我们可以定义一些业务逻辑类,这些类的方法将会被上面定义的切面所拦截。

package com.example.service;

import org.springframework.stereotype.Service;

@Service
public class MyService {

    public void performTask() {
        System.out.println("Executing task in MyService.");
    }
}
5. 测试AOP功能

最后,我们编写一个简单的测试类来验证AOP是否按预期工作。

package com.example;

import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

import com.example.service.MyService;

public class AopTestApp {

    public static void main(String[] args) {
        ApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
        MyService myService = context.getBean(MyService.class);

        // 调用服务方法,触发AOP通知
        myService.performTask();
    }
}
6. 运行结果

当你运行AopTestApp时,你应该会看到如下输出:

Logging before method execution.
Executing task in MyService.
Logging after method execution.

这表明AOP切面已经成功地在MyService#performTask方法执行前后插入了日志记录的通知。

AOP 注解详解

  • @Aspect:用于定义一个类作为切面。
  • @Pointcut:用于定义切入点表达式,标识哪些连接点(通常是方法调用)会被拦截。可以重复使用。
  • @Before:用于定义前置通知,在方法执行之前执行。
  • @After:用于定义后置通知,在方法执行之后执行,无论方法是否抛出了异常。
  • @Around:用于定义环绕通知,可以完全控制方法的执行流程,包括选择是否继续执行方法。
  • @AfterReturning:用于定义返回后通知,在方法正常返回后执行。
  • @AfterThrowing:用于定义异常通知,在方法抛出异常后执行。

切入点表达式

切入点表达式是用来指定哪些方法应该被拦截的规则。AspectJ提供了丰富的语法来定义切入点表达式。例如:

  • execution(* com.example.service.*.*(..)) 匹配com.example.service包下所有类的所有方法。
  • within(com.example.service..*) 匹配com.example.service包及其子包下的所有类的所有方法。
  • @annotation(org.springframework.transaction.annotation.Transactional) 匹配所有带有@Transactional注解的方法。

通过合理使用这些注解和表达式,你可以轻松地为应用程序添加横切关注点,同时保持业务逻辑的清晰和简洁。

通知执行顺序

 

基于XML的配置方式(非重点)

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值