1.配置(重要)
想要将对象成功的存储到Spring容器中,需要配置一下存储对象的扫描包路径,只有被配置的包下的所有类,添加了注解才能被正确的识别并存储到Spring容器中。
在配置文件中添加如下配置(spring-config.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:content="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans htt
p://www.springframework.org/schema/beans/spring-beans.xsd http://www.spring
framework.org/schema/context https://www.springframework.org/schema/contex
t/spring-context.xsd">
<content:component-scan base-package="com.spring.demo"></content:component-scan>
</beans>
<content:component-scan base-package="com.spring.demo"></content:component-scan>
的base-package里填写的路径就是需要扫描的包路径。如果添加的注解不在这个扫描的包路径下,那么也是不能存储到spring中的。也就是说下面使用的五大类注解和方法注解只有在这个路径下才能正确使用
2.添加五大类注解
将对象存储到Spring容器中,共分为两种注解:
1.五大类注解:
@Controller:表示的是业务逻辑层
@Service:服务层
@Repository:持久层
@Component:组件
@Configuration:配置层
2.方法注解:@Bean(需要配合类注解一起使用)。
2.1 @Controller(控制器存储)
@Controller:用来验证用户请求的正确性。
使用@Controller存储Bean的代码如下所示:
@Controller // 将对象存储到Spring容器中
public class UserController {
public void sayHi(){
System.out.println("do UserController");
}
}
此时我们在启动类中获取Bean对象
public class App {
//1.得到Spring容器
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
//2.得到Bean对象
UserController userController = context.getBean("userController",UserController.class);
//3.使用Bean方法
userController.sayHi();
}
}
注意:之前名称写的bean标签里的id,此时使用注解方法将Bean存储到Spring中,那么在getBean时,填写名称分两种形式:
1.如果类名第一个字母是大写,bean名称为类名第一个字母小写,后面照抄;
2.类名第一个字母和第二个字母如果都是大写时,bean名称为原类名。
2.2 @Service(服务存储)
@Service:调度具体执行方法。
@Service
public class UserService {
public void sayHi(){
System.out.println("do UserService");
}
}
获取Bean代码
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserService userService = context.getBean("userService",UserService.class);
userService.sayHi();
}
}
2.3 @repository(仓库存储)
@repository:数据持久层;直接和数据库进行交互的。一张表对应一个@repository。
@Repository
public class UserRepository {
public void sayHi(){
System.out.println("do UserRepository");
}
}
获取Bean代码
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserRepository userRepository = context.getBean("userRepository",UserRepository.class);
userRepository.sayHi();
}
}
2.4 @Component(组件存储)
使⽤ @Component 存储 bean 的代码如下所示:
@Component
public class UserComponent {
public void sayHi(){
System.out.println("do UserComponent");
}
}
获取Bean代码:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserComponent userComponent = context.getBean("userComponent",UserComponent.class);
userComponent.sayHi();
}
}
2.5 @Configuration(配置存储)
@Configuration:放项目中的一些配置
@Configuration
public class UserConfiguration {
public void sayHi(){
System.out.println("do UserConfiguration");
}
}
获取Bean代码:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
UserConfiguration userConfiguration = context.getBean("userConfiguration",UserConfiguration.class);
userConfiguration.sayHi();
}
}
3.为什么需要这么多注解呢?
就是让程序猿在看见这些注解后能直接了解当前类的用途。程序的工程分层和调用流程如下:
JavaEE 标准分层:至少包含三层;
1、 @Controller:控制层,验证前端参数是否合格,如果合格才会执行下面的代码。
2、@Service:服务层,服务的调度,调用接口,比如要调用几个Repository…
3、@Repository:数据持久层/数据交互层。直接操作数据库的,一张表对应一个Repository。
4.Bean命名规则
通过上面示例,可以看出一般Bean使用的都是标准的大驼峰命名,而获取的时候类名首字母小写就可以得到bean。然而如果当我们首字母和第二个字母都是大写时,就不能正常读取bean了:
我们可以查询Spring关于Bean存储时命名的规则:
在Idea中搜索beanname关键字,找到如下
它使用的是JDK Introspector中的decapitalize方法,源码如下:
public static String decapitalize(String name) {
if (name == null || name.length() == 0) {
return name;
}
//如果第一个字母和第二个字母为大写,就是把原类名 作为bean名称
if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
Character.isUpperCase(name.charAt(0))){
return name;
}
//否则就把首字母转为小写,作为bean名称
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
所以对于上述报错代码,我们只要改为一下代码就可以成功运行了:
由于得出结论:
1.如果类名第一个字母是大写,bean名称为类名第一个字母小写,后面照抄;
2.类名第一个字母和第二个字母如果都是大写时,bean名称为原类名。
5.方法注解 @Bean
类注解是添加到某个类上的,而方法注解是放到某个方法上的,@Bean要搭配类注解一起使用,才能将对象存储到Spring容器中, 否则会报错.正确代码如下:
@Controller
public class Users {
//把方法的返回对象存储到Spring中
@Bean
public User user1(){
User user = new User();
user.setId(1);
user.setName("ZhangSan");
return user;
}
}}
}
user1方法必须要有返回值,@Bean是把当前方法的返回值存储到Spring中!
获取bean时使用的名称要与 方法名一致.
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
User user =(User) context.getBean("user1");
System.out.println(user.toString());
}
}
运行结果如下:
5.1 重命名Bean
可以通过@Bean自带的name属性给Bean对象进行重命名操作,如下代码所示:
说明:这个重命名name是一个数组,可以使一个bean设置多个名字。格式:@Bean(name = {"u1", "us1"})
或者省略name:@Bean({"u1", "us1"})
@Controller
public class Users {
//把方法的返回对象存储到Spring中
@Bean(name = "u1")//重命名为 u1
public User user1(){
User user = new User();
user.setId(1);
user.setName("ZhangSan");
return user;
}
}
把原先的user1重命名为u1后,在获取bean时使用的名称就只能是u1了,原名不能再使用了,否则会报错:
此时我们使用u1就可以正常获取到User对象了,如下代码:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
User user =(User) context.getBean("u1");//使用重命名获取
System.out.println(user.toString());
}
}
运行结果: