Bean加载方式
本文适合已经有了Spring基础的读者来阅读,如果你对Spring有一定了解但又没那么了解,或者你想要去了解SpringBoot的自动配置原理,读完这篇文章之后一定能对你有所帮助
1 环境准备
按照以下步骤搭建一个Demo,方便后续演示使用:
1)新建一个maven项目,在pom文件中导入spring的依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.9</version>
</dependency>
2)新建一个com.itheima.bean包,这个包用来存放一些后续演示中会使用的Bean。在包中创建以下类:
public class Cat {
}
public class Dog {
}
public class Mouse {
}
3)在com.itheima.bean中新建一个service包,包中创建以下接口:
public interface BookSerivce {
void check();
}
4)在service包中创建一个impl包,在包中创建以下类
public class BookServiceImpl1 implements BookSerivce {
@Override
public void check() {
System.out.println("book service 1..");
}
}
public class BookServiceImpl2 implements BookSerivce {
@Override
public void check() {
System.out.println("book service 2....");
}
}
public class BookServiceImpl3 implements BookSerivce {
@Override
public void check() {
System.out.println("book service 3......");
}
}
public class BookServiceImpl4 implements BookSerivce {
@Override
public void check() {
System.out.println("book service 4........");
}
}
这样基础环境就搭建好了,整体结构如下:
2 Bean加载方式之XML方式
2.1 配置自定义Bean
在resources目录下新建一个名为applicationContext1.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
如果希望在spring容器中加载某个类的Bean,那么只需要在标签中添加一个标签,并按照以下格式配置类的信息即可:
<!--定义一个id为cat的Bean,Bean的类型为Cat-->
<bean id="cat" class="com.itheima.bean.Cat"/>
如果我们希望使用这个Bean,只需要从容器获取即可,具体如下:
在com.itheima包下创建一个app包,这个包专门用来演示获取Bean,在app包下新建一个类,内容如下:
public class App1 {
public static void main(String[] args) {
//获取容器对象
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext1.xml");
//获取Bean
Object cat = ctx.getBean("cat");
System.out.println(cat);
}
}
我们在xml中声明Bean时,也可以不指定类型,例如:
<!--定义一个id为cat的Bean,Bean的类型为Cat-->
<bean id="cat" class="com.itheima.bean.Cat"/>
<!--创建一个Dog的Bean,不指定id-->
<bean class="com.itheima.bean.Dog"/>
那么我们在获取Bean的时候就只能根据类型去获取
public class App1 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationCOntext1.xml");
Object cat = ctx.getBean("cat");
System.out.println(cat);
//获取Dog类型的Bean
Dog dog = ctx.getBean(Dog.class);
System.out.println(dog);
}
}
如果spring容器中存在两个以上Dog类型的Bean,我们按类型获取就会出现异常,这时就只能给不同的DogBean定义id然后根据id获取了
我们还可以通过以下方法获取容器中我们手动添加的所有Bean的定义信息
public class App1 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationCOntext1.xml");
// Object cat = ctx.getBean("cat");
// System.out.println(cat);
// Dog dog = ctx.getBean(Dog.class);
// System.out.println(dog);
//获取所有Bean的DefinitionName,即定义名
String[] names = ctx.getBeanDefinitionNames();
//循环打印
for (String name : names) {
System.out.println(name);
}
}
}
打印信息如下:
当我们在定义Bean的时候,如果指定了id,那么Bean的DefinitionName就是我们指定的id,如果我们没有指定id,那么DefinitionName默认就是类的全路径名#数字编号
,如果该类型的Bean是容器中第一个,那个数字编号就为0,第二个则为1,以此类推。
我们通过id获取Bean的方式实际上是通过DefinitionName来获取Bean,也就是说,如果我们希望获取Dog的Bean,也可以这样写:
public class App1 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationCOntext1.xml");
//通过Bean的默认定义名来获取Bean
Object cat = ctx.getBean("com.itheima.bean.Dog#0");
System.out.println(cat);
}
}
虽然我并不认为有人会这样去获取
2.2 配置第三方Bean
除了配置我们自己定义的Bean之外,也可以在xml中配置一些第三方的Bean,例如数据库连接池等等,演示如下:
1)在pom文件中引入druid的依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
2)在xml文件中配置druid的Bean(这里只是演示一下,数据源啥的就不配了)
<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource"/>
3)从容器中进行获取:
public class App1 {
public static void main(String[] args) {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationCOntext1.xml");
// Object cat = ctx.getBean("cat");
// System.out.println(cat);
// Dog dog = ctx.getBean(Dog.class);
// System.out.println(dog);
String[] names = ctx.getBeanDefinitionNames();
for (String name : names) {
System.out.println(name);
}
}
}
打印结果如下:
如果我们没有指定id,也会按照类的全路径名#数字编号
的格式为第三方Bean配置一个默认的DefinitionName
3 Bean加载方式之注解方式
3.1 配置自定义Bean
注解方式是为了简化xml方式的,如果我们需要将一个类加载到spring容器中,只需要在类上打上一个注解即可:
//将Cat类的一个Bean加载到容器中,Bean的名称为tom
@Component("tom")
public class Cat {
}
@Component
有三个衍生注解,分别是@Controller
、@Service
、@Repository
,分别对应着Controller层,Service层和Dao层的Bean,这三个注解作用和@Component
基本一致,更多的是起一个区分和标志作用
除此之外,我们还需要在xml中配置spring的包扫描,用来扫描对应包下的注解,并将包中打上注解的类加载到spring容器中
新建一个配置文件,名为applicationContext2.xml,内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context.xsd
">
<!--配置包扫描-->
<context:component-scan base-package="com.itheima.bean"/>
</beans>
如果要获取容器中的Bean,只需要采用相同的方式即可,这里为了不干扰,我们在app包下新建一个类来演示
public class App2 {
public static void main(String[] args) {
ApplicationContext ctx = new