Spring(三)注解配置
要使用注解方式配置bean,还需要导入spring-aop这个jar包:
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.3.3</version>
</dependency>
依旧需要创建一个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"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!-- 开启注解,指定要扫描的包(Spring将会扫描该包下以及其子包下的所有类上是否有注解)-->
<context:component-scan base-package="com.dh.pojos"/>
</beans>
然后只需要在要放入容器中的类上加上注解:共有四个
@Component,@Controller,@Service,@Repository
四个的作用都是一样的,只是为了方便程序员区分类,@Controller放在servlet类中,@Service放在service类中,@Repository放在dao类中。
在类的最上方加上注解:
package com.dh.pojos;
import org.springframework.stereotype.Component;
@Component
//在注解时也可以指定一个名字
//@Component("person")
public class Person {
private String name;
private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
}
测试:测试同xml配置
import com.dh.pojos.Person;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class MyTest01 {
@Test
public void test01(){
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext.xml");
//如果没有指定名字可以使用类名小写开头的类名
//指定了名字可以使用名字
Person person = (Person) applicationContext.getBean("person");
System.out.println(person);
//还可以使用类名.class
Person person1 = applicationContext.getBean(Person.class);
System.out.println(person1);
}
}
那么如何进行依赖注入呢?
对属性进行依赖注入也有相应的注解:
@Value:用于对普通属性赋值;
@Autowired:用于对复杂属性赋值;
@Qualifier:弥补@Autowired的缺陷,可以指定JavaBean的id;
@Resource:java扩展的注解。
在Person类中添加其它复杂的属性:
private String name;
private int age;
private Dog dog;
private String driver;
然后为其注入值:
//普通值
@Value("Tom")
private String name;
//SpEL表达式
@Value("#{18+2}")
private int age;
//其它bean
@Autowired
private Dog dog;
//properties文件中的值
@Value("${jdbc.driver}")
private String driver;
注意,需要在applicationContext中加载配置文件:
<context:property-placeholder location="classpath:jdbc.properties"/>
结果:
Person{name='Tom', age=20, dog=Dog{type='null', color='null'}, driver=com.mysql.cj.jdbc.Driver}
@Autowired是利用类型来注入的,当有多个的时候就会报错:
比如:
一个接口:
package com.dh.service;
public interface UserService {
}
两个实现类,并使用注解放入容器:
package com.dh.service;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl1 implements UserService {
}
package com.dh.service;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl2 implements UserService {
}
此时有一个User类:
package com.dh.service;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class User {
@Autowired
private UserService userService;
public UserService getUserService() {
return userService;
}
public void setUserService(UserService userService) {
this.userService = userService;
}
@Override
public String toString() {
return "User{" +
"userService=" + userService +
'}';
}
}
测试:
User user = applicationContext.getBean(User.class);
System.out.println(user);
结果会发生异常,截取主要的详细:
No qualifying bean of type 'com.dh.service.UserService' available: expected single matching bean but found 2: userServiceImpl1,userServiceImpl2
因为使用@Autowired找UserService找到了两个,所以Spring不知道是哪个。
此时就需要@Qualifier出场了,指定所需要的JavaBean的id:
@Autowired
@Qualifier("userServiceImpl1")
private UserService userService;
或者可以直接使用@Resource注解
要使用此注解,需要导入jar包:
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
//同时指定name和type
@Resource(name = "userServiceImpl1",type = UserServiceImpl1.class)
private UserService userService;
注解设置作用域
在类中使用@Scope注解就可以配置类的作用域了。
@Component
@Scope("prototype")
public class User {
}
注解和xml联合使用
虽然注解很强大,但是对于一些别人写好的类,我们就没有办法去加注解了,此时就只能使用xml配置了。
而Spring是支持注解和xml联合使用的:
如:
使用xml配置bean,使用注解实现依赖注入
<bean id="person2" class="com.dh.pojos.Person"/>
<bean id="dog2" class="com.dh.pojos.Dog"/>
<!-- 开启扫描注解-->
<context:annotation-config/>
public class Person {
@Autowired
private Dog dog;
}
多文件配置
当配置文件中的内容太多时,就可以分开在几个不同的文件中书写,那么如何同时加载呢?
方法一:
new ClassPathXmlApplicationContext("file1","file2",...);
方法二:
在一个配置文件中引入其它配置文件:
<import resource="file_name"/>
然后只需要加载主文件即可。