简单获取Bean的两种方法
- 简单获取Bean的两种方法
- 那么对于调用`Bean`对象时需要注意什么?
- 五大类注解自定义名称
- 三种bean注入
简单获取Bean的两种方法
在之前使用spring时我们都是使用xml
语句进行对象注入,而如果对于一个大型项目采用这种方法,需要编写大量的xml
对象注入语句,使用起来可以说是非常不方便了。那么使用什么方法才可以使得我们并不需要编写大量的代码就可以写出优秀的程序呢?
五大类注解由此而生,对于一个类对象只需要添加一个注解,然后就可以获取到添加该注解的bean
对象。
在添加注解之前我们需要在配置文件中修改文件中的字段:
<?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 http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<content:component-scan base-package="com.controller">
</content:component-scan>
<!-- 注意:base-package="这里填写的是类创建的路径" -->
</beans>
将配置文件修改之后,我们需要读懂配置文件中添加的字段。
<content:component-scan>
这个标签如果在xml
文件中进行配置,就会在base-package
这个目录下自动扫描以下五大类注解,然后将这些类加注册为bean
。
- @Controller:控制层
归属于业务逻辑层,用来控制用户行为和检查仓库数据的有效性。
@Repository:数据仓库层
归属于持久层,直接调用数据库的数据,通常每个数据表只存在一个需要@repository注解类。
@Service:服务层
使用数据仓库持久化的特性将数据传递给控制层(不直接与数据库中数据交互,相对于数据控制中心)。
@Component:组件层
归属于公共方法类,提供一些五大类注解都会使用的方法。
@Configuration:配置层
一般用于当前项目的配置,一般每个项目的配置文件都会存在不同。
使用示例:
//一个添加@controller的对象被注入时
@Controller
public class Employ {
public void addOne(){
System.out.println("录用一个新人");
}
}
App.class
获取bean
对象:
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
Employ employ = context.getBean("employ", Employ.class);
employ.addOne();
}
}
可以看到使用了@Controller
的类的确被注册。
那么对于调用Bean
对象时需要注意什么?
在使用bean标签注入对象时,语法如下:
<bean class="User" id="user">
表示类名为:User
,引用时使用id
也就是user
,意味着user就是bean
注册时使用的名称。而当我们使用五大类注解时如果直接使用默认名称,与类名有什么关联!在上面我们举例时默认使用了小写的类名,然后可以获取到bean
对象,而如果本来就是小写的类我们又如何去获取,如果是一个全部字母为大写的类又是如何注册Bean
对象的?
打开源码:
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;
}
//如果前两个字符串不是大写,就创建一个新字符数组保存原来的字符串,然后将第一个字符改为小写
char chars[] = name.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
return new String(chars);
}
根据以上源码可以得出Bean
对象命名的三种规则:
- 当首字母为大写时,将首字母改为小写,其他不变
- 当首字母为小写时,使用原类名进行调用
- 当前两个字母为大写时,使用原类名进行调用
所有我们在编写一个类对象时,不能随意命名,要看懂spring中对于bean
对象有不同要求然后获取bean
对象时进行修改。
五大类注解自定义名称
在五大类使用时需要注意名称的大小写来注册一个Bean
对象,那么有没有更加方便的定义方法呢?
添加Bean
自定义名称
@Controller(value="Bean1")
在之后的使用中就可以使用自定义名称来作为Bean
名称来调用对象。要注意一旦使用了自定义的名称作为Bean
对象,原来的类名就不能使用了。
三种bean注入
除了使用五大类注解来注册一个对象,我们还可以使用@Bean
去针对性的注入一个方法或者对象,需要注意的是@Bean
对象需要配合五大类注解一起使用,单独使用是无法起效的。
在注册一个类时,在类中使用了Bean
注解的方法或者对象都会被一同注入。
例如在刚刚的员工方法,我们掉用了addOne
时在控制台打印信息。而在addOne
上添加@Bean
注解后,直接获取Employ
对象时在控制台就会打印信息。相对于另外新注册了一个Bean
对象,可以直接使用context.getBean("bean的名称");
//App------------间接调用Bean
public class App {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("spring-config.xml");
Employ employ = context.getBean("employ", Employ.class);
}
}
//App------------直接调用Bean
public class App {
public static void main(String[] args) {
ApplicationContext context = new context.getBean("addOne");
}
}
//Employ
@Controller
public class Employ {
@Bean
public void addOne(){
System.out.println("录用一个新人");
}
}
输出相同:
上面中的五大类注解可以进行自定义名称,同样的@Bean
也可以自定义名称来作为Bean
对象。
//语法1-----可加{}命名为多个名称
@Bean("add")
public void add() {
System.out.println("Do UserRepository add method");
}
//语法2-----可加{}命名为多个名称
@Bean(name = "add")
public void add() {
System.out.println("Do UserRepository add method");
}
//语法3-----可加{}命名为多个名称
@Bean(values = "add")
public void add() {
System.out.println("Do UserRepository add method");
}
命名多个名称是为了让程序更加易读。
public @interface Bean {
@AliasFor("name")
String[] value() default {};
@AliasFor("value")
String[] name() default {};
/** @deprecated */
@Deprecated
Autowire autowire() default Autowire.NO;
boolean autowireCandidate() default true;
String initMethod() default "";
String destroyMethod() default "(inferred)";
}
这个是关于bean命名的源码:
name
和value
:可以看到name默认调用bean是使用方法名,name
和value
可以作为多个命名存在。- Autowire:装配默认不开启自动装配功能
- initMethod:初始化代码,不常用
- destroyMethod:销毁操作,如果程序使用了close或者shutdown,会自动销毁