写在前面
在spring4之后,要使用注解开发,必须要保证aop的包导入了

1. 环境搭建
1.1 applicationContext.xml
这里需要配置两个上下文属性:
- component-scan 指定要扫描的包
- annotation-config 开启注解
<?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">
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="cc.leeleo.entity"/>
<!--开启注解-->
<context:annotation-config/>
</beans>
1.2 新建一个要扫描的包
这里创建cc.leeleo.entity 包作为要扫描的包,并创建User类,并添加@Component注解,此处的注解的作用相当于是在xml中配置<**bean id="user" class="cc.leeleo.entity.User"**/> ,说明当前类交由Spring管理了。
User.java
@Component
@Data
public class User {
private String id;
public User() {
this.id = UUID.randomUUID().toString();
}
}
1.3 测试

以上我们就完成了注解的最基本的使用,简直不要太简单~
2. 注解实现属性注入
Spring使用了@Value注解来实现属性的注入,从而替代了使用配置文件来繁琐的配置属性注入,下面我们来看下具体实现
很简单,这里我们给User类添加一个属性name,并使用@Value注解为其赋值
User.java
@Component
@Data
public class User {
private String id;
@Value("张三")
private String name;
public User() {
this.id = UUID.randomUUID().toString();
}
}
测试:

2.1 衍生注解
在日常的开发中经常会使用到MVC三层架构,针对这些分层,@Compnent提供了几个衍生注解
- dao 【@Repository】
- service 【@Service】
- controller 【@Controller】
这四个注解功能都是一样的,都是将标识的类注册到Spring容器中进行装配
上代码:
-
修改要扫描的包名:
<context:component-scan base-package="cc.leeleo"/> -
新建四个包,同时新建四个MVC层的类
-
cc.leeleo.entity
@Component @Data public class User { private String id; @Value("张三") private String name; public User() { this.id = UUID.randomUUID().toString(); } } -
cc.leeleo.controller
@Controller public class UserController { @Autowired private UserService userService; public User getUser(){ return userService.getUser(); } } -
cc.leeleo.service
@Service public class UserService { @Autowired private UserDao userDao; public User getUser() { return userDao.getUser(); } } -
cc.leeleo.dao
@Repository public class UserDao { @Autowired private User user; public User getUser() { return user; } }
-
测试:
@Test
public void test(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
UserController userController = context.getBean("userController", UserController.class);
User user = userController.getUser();
System.out.println(user.toString());
}
输出:
"D:\Program Files\Java\jdk1.8.0_261\bin\java.exe" -ea -Didea.test.cyclic.buffer.size=1048576 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\lib\idea_rt.jar=62334:C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\lib\idea_rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\plugins\junit\lib\junit5-rt.jar;C:\Program Files\JetBrains\IntelliJ IDEA 2020.3\plugins\junit\lib\junit-rt.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\charsets.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\deploy.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\access-bridge-64.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\cldrdata.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\dnsns.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jaccess.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jfxrt.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\localedata.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\nashorn.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunec.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunjce_provider.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunmscapi.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunpkcs11.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\zipfs.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\javaws.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\jce.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\jfr.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\jfxswt.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\jsse.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\management-agent.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\plugin.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\resources.jar;D:\Program Files\Java\jdk1.8.0_261\jre\lib\rt.jar;D:\项目\study\spring-01\spring-annotation\target\test-classes;D:\项目\study\spring-01\spring-annotation\target\classes;C:\Users\java-boy\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\java-boy\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-webmvc\5.3.9\spring-webmvc-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-aop\5.3.9\spring-aop-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-beans\5.3.9\spring-beans-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-context\5.3.9\spring-context-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-core\5.3.9\spring-core-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-jcl\5.3.9\spring-jcl-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-expression\5.3.9\spring-expression-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\springframework\spring-web\5.3.9\spring-web-5.3.9.jar;C:\Users\java-boy\.m2\repository\org\projectlombok\lombok\1.18.22\lombok-1.18.22.jar" com.intellij.rt.junit.JUnitStarter -ideVersion5 -junit4 TestAnnotation,test
User(id=882471a5-d84f-4ead-95e0-301359c591d2, name=张三)
进程已结束,退出代码为 0
2.2 作用域
我们在之前讲到依赖注入的时候,提到过作用域的概念,之前学到的prototype和singleton这俩作用域都是以配置文件给
这里我们直接给需要更改作用域的bean增加@Scope注解就可以了
上代码:
这里我们修改User类增加@Scope注解,使其为多例模式
@Component
@Data
@Scope("prototype")
public class User {
private String id;
@Value("张三")
private String name;
public User() {
this.id = UUID.randomUUID().toString();
}
}
测试:

我们发现新get的bean和现有的bean内存地址不一样,已经变成多例模式了
3、使用java实现xml配置
完全不使用Spring的xml配置,全部使用java代码实现,
先来初始化一个Spring容器,并获取一个bean
-
使用xml实现
以前初始化一个Spring的ApplicationContext,我们需要指定一个配置文件,并且需要在配置文件中通过标签来配置一个bean -
使用java实现
-
新建User类
@Data public class User { private String id; @Value("张三") private String name; public User() { this.id = UUID.randomUUID().toString(); } } -
新建配置类,增加@Configuration注解,并新增一个get方法使用@Bean注解,配置一个bean
@Configuration public class SpringConfig { @Bean public User getUser(){ return new User(); } }需要注意:
- 如果有多个返回值相同的方法,那么会报如下错误:
org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'cc.leeleo.entity.User' available: expected single matching bean but found 2: getUser,getUser2 - @Bean注解只能作用于方法上面
- 如果有多个返回值相同的方法,那么会报如下错误:
测试:这里需要注意,以前使用
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");现在需要改为使用配置类来替代原先的xml路径了
ApplicationContext context = new AnnotationConfigApplicationContext(SpringConfig.class); -

知识点:
方法的名称就相当于的id属性
方法的返回值就相当于的class属性
所以我们想通过bean的id获取它的话,应该是像下面这样:
User user = context.getBean(**"getUser"**,User.**class**);
至此,我们就实现一个0xml配置的Spring容器了,使用@Configuration注解,其实就等同于使用xml中的
3.1 @ComponentScan
该注解的作用相当于配置文件的如下配置:
<!--指定要扫描的包,这个包下的注解就会生效-->
<context:component-scan base-package="cc.leeleo"/>
我们只需要在添加了@Configuration注解的类上追加@ComponentScan即可
@Configuration
@ComponentScan("cc.leeleo")
public class SpringConfig {
@Bean
public User getUser(){
return new User();
}
}
于此同时,只需要在指定的包下,新建的类中添加@Component、@Controller、@Repository、@Service、任一注解,均可将当前类交由Spring容器进行管理。
3.2 @Import导入配置类
我们在之前使用配置文件的时候讲过,可以通过
<import resource="beans2.xml"/>
以下使用java的方式,此处导入的就不是xml的配置文件了,而是加了@Configuration注解的配置类了
-
新建个实体类Company
public class Company { @Value("leeleo") public String name; } -
新建配置类SpringConfig2
@Configuration public class SpringConfig2 { @Bean public Company company(){ return new Company(); } } -
导入配置类
@Configuration @Import(SpringConfig2.class) public class SpringConfig { @Bean public User getUser(){ return new User(); } }
测试:
