【spring】注解版
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 作用:用于指定初始化方法。
代码就不写了,没啥写的,无非就是在相应的方法上加上相应的注解。