【spring】注解版

发布于:2025-03-08 ⋅ 阅读:(98) ⋅ 点赞:(0)

1.管理bean

之前我们要想管理bean都是在xml文件中将想要添加的bean手动添加进ioc容器中,这样太过麻烦了,在 Java 开发里,针对一些较为繁琐的操作,通常会有相应的简化方式,这个也不例外,就是spring提供的注解。

@Component

只需要把它写在想要放入ioc容器的bean所属的类上即可,在后面可以加上(value="")这个value的值就是相当于之前xml文件中bean标签里的id,可以直接把value去掉直接写上对应的值,毕竟就这一个值也不需要区分。当然你也可以选择什么都不加,那么此时默认的值就是改类名但是首部第一个字母一定要是小写。

还有一个很重要的细节别忘了,就是一定要在xml文件中配置扫描,旨在告诉spring要扫描的包因为ClassPathXmlApplicationContext初始化容器时会把xml文件中声明的标签下的类都创建到容器中。但 是因为bean.xml并不知道哪一个类加上注解了,所以无法创建对象。

<context:component-scan base-package="com.xq"></context:component-scan>

base-package的值就是告诉com.xq一下的包都要扫描。 

该注解衍生出三个注解

@Controller:一般用在表现层。

@Service:一般用在业务。

@Repository:一般用在持久层。

其实它们跟@Component是一个用法,之所以这样分开是因为java写项目时是需要进行分层开发的

为了区分各个层,就用了这三个注解。

2.依赖注解

@Autowired

有一点要说明,它只能注入引用类型的bean

分三个场景来讲

构造函数注入

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

// 定义一个服务接口
interface MessageService {
    void sendMessage(String message);
}

// 实现服务接口
@Component
class EmailService implements MessageService {
    @Override
    public void sendMessage(String message) {
        System.out.println("Sending email: " + message);
    }
}

// 使用 @Autowired 进行构造函数注入
@Component
class UserService {
    private final MessageService messageService;

    @Autowired
    public UserService(MessageService messageService) {
        this.messageService = messageService;
    }

    public void notifyUser(String message) {
        messageService.sendMessage(message);
    }
}

在该代码中,类UserService依赖于MessageService,通过构造函数注入的方式,spring会自动将EmailService的实例注入到UserService中。

setter方法注入

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

// 定义一个服务接口
interface PaymentService {
    void processPayment(double amount);
}

// 实现服务接口
@Component
class CreditCardPaymentService implements PaymentService {
    @Override
    public void processPayment(double amount) {
        System.out.println("Processing credit card payment: " + amount);
    }
}

// 使用 @Autowired 进行 Setter 方法注入
@Component
class OrderService {
    private PaymentService paymentService;

    @Autowired
    public void setPaymentService(PaymentService paymentService) {
        this.paymentService = paymentService;
    }

    public void placeOrder(double amount) {
        paymentService.processPayment(amount);
    }
}

这里的OrderService通过setter方法注入了PaymentService实例。

字段注入 

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

// 定义一个服务接口
interface LoggingService {
    void log(String message);
}

// 实现服务接口
@Component
class ConsoleLoggingService implements LoggingService {
    @Override
    public void log(String message) {
        System.out.println("Logging to console: " + message);
    }
}

// 使用 @Autowired 进行字段注入
@Component
class ProductService {
    @Autowired
    private LoggingService loggingService;

    public void addProduct(String productName) {
        loggingService.log("Adding product: " + productName);
    }
}

 ProductService类中的loggingService被注入ConsoleLoggingService的实例,但是这里有一点要注意,万一接口有多个实现类呢,那这样就会报错,在识别时ioc容器会先先按照类型进行筛选,如果有多个相同类型的,然后用变量名作为bean的id继续筛选。

3.其他注入数据的注解

使用注入数据注解的效果跟在xml配置文件中的bean标签中写一个标签的作用是一样的.

@Qualifier:它可以在按照类中注入的基础之上再按照名称注入,但是它给类成员注入时不能单独使用,但是在给方法参数注入式可以。

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

// 定义一个接口
interface Animal {
    void sound();
}

// 实现接口
@Component("dog")
class Dog implements Animal {
    @Override
    public void sound() {
        System.out.println("Woof!");
    }
}

@Component("cat")
class Cat implements Animal {
    @Override
    public void sound() {
        System.out.println("Meow!");
    }
}

// 使用 @Autowired 和 @Qualifier 注入指定的 Bean
@Component
class AnimalService {
    private final Animal animal;

    @Autowired
    @Qualifier("dog")
    public AnimalService(Animal animal) {
        this.animal = animal;
    }

    public void makeSound() {
        animal.sound();
    }
}

将@Autowired和@Qualifier组合在一起,spring会根据类型和@Qualifier指定的名称从ioc容器中查找对应的bean并注入到AnimalService中。

@resource

它与@Autowired的注入策略相反,它是先看bean的id来筛选,因为它后面可以加(name=“”),再来看类型。

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

// 定义一个接口
interface Printer {
    void print();
}

// 实现接口,并使用 @Component 指定 Bean 的名称为 "colorPrinter"
@Component("colorPrinter")
class ColorPrinter implements Printer {
    @Override
    public void print() {
        System.out.println("Printing in color...");
    }
}

// 使用 @Resource 按名称注入
@Component
class PrintingService {
    @Resource(name = "colorPrinter")
    private Printer printer;

    public void doPrinting() {
        printer.print();
    }
}

这里的@Resource直接指明了bean的id为colorPrinter,spring直接在ioc容器中寻找对应的bean,再将其注入到printer字段中。

@Value

用于注入基本数据类型和String类型,因为前面提到的那些只能注入引用数据类型。可以用在字段、构造函数参数或者方法参数上,用于注入值。

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

@Component
public class MyComponent {
    @Value("Hello, Spring!")
    private String message;

    @Value("123")
    private int number;

    public String getMessage() {
        return message;
    }

    public int getNumber() {
        return number;
    }
}

通过该注解,可以很方便的将各种外部值注入到spring管理的bean中。

4.改变作用域范围的注解

@Scope

类似于xml文件中的scope属性,它是用来注解一个类的

分别是

@Scope(value="singleton")单例bean

@Scope(value="prototype")多例bean

@Service("accountService")
@Scope(value = "prototype")
public class AccountServiceImpl implements AccountService {
    @Resource(name = "accountDao1")
    AccountDao accountDao1;

    public void addAccount() {
        accountDao1.addAccount();
    }
}

public class TestAccount {
    public static void main(String[] args) {
        ApplicationContext context = new ClassPathXmlApplicationContext("bean.xml");
        AccountService accountService1 = (AccountService) context.getBean("accountService");
        AccountService accountService2 = (AccountService) context.getBean("accountService");
        System.out.println(accountService1==accountService2);
    }
}

根据注解显示创建的是多例bean,所以输出为false。、

5.生命周期相关的注解

使用与生命周期相关的注解的作用跟在bean标签中使用init-method和destroy-method的作用是一样 的。

@PreDestroy 作用:用于指定销毁方法。

@PostConstruct 作用:用于指定初始化方法。

代码就不写了,没啥写的,无非就是在相应的方法上加上相应的注解。


网站公告

今日签到

点亮在社区的每一天
去签到