文章目录
Spring中原生的定义Bean的方式可以分为两类六种,我们经常使用的仅是它其中一类中的三种。
这个有点像Spring中的事务,我们熟悉的也仅仅是它的声明式写法——@Transaction,并不熟悉编程式的写法,或许你会说,可以,但没必要。此处我不做评价。
Spring中定义Bean的方式可以分为两类,分别是声明式和编程式。顾名思义,声明式可以理解为用一个的标记去标识相关的信息,代码底层再对这些标识符进行一个解析处理;编程式则更多侧重于使用代码的形式去处理相关逻辑。前者使用更友好,后者更底层。
一、声明式
1、<bean>标签
如果我们以xml配置文件的方式启动Spring容器,那么我们就可以在xml配置文件中使用bean标签完成对一个Bean的定义
1)实体类:
public class MoBian3XML {
}
2)spring-test.xml:
![](/qrcode.jpg)
<?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">
<bean id="mobian3" class="pers.mobian.springseventh.MoBian3XML">
</beans>
3)Spring容器启动:
public class MainTestXML1 {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-test.xml");
System.out.println(context.getBean("mobian3"));
}
}
2、@Bean注解
在配置类里面,使用@Bean注解。
类上要使用@Configuration注解,当然你不用也可以,只是我们希望配置类能有一个属于它的专属标识符
1)配置类:
@Configuration
public class Config {
@Bean(name = "mobian666")
public MoBian moBian(){
return new MoBian();
}
}
2)Spring容器启动:
public class MainTest4 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
System.out.println(context.getBean("mobian666"));
}
}
3、@Component注解
与<Bean>标签和@Bean注解的作用范围不同,该方式可批量向Spring中注入Bean,多用于controller、service包下类,前者更多的运用在单个实体类的定制化处理。
1)配置文件配置:
1.如果是xml文件的启动,就在xml文件中配置
<context:component-scan base-package="pers.mobian.firstTest"/>
2.如果是在配置类中配置
@Configuration
@ComponentScan("pers.mobian.firstTest")
public class ContextConfig {
}
2)此时就需要使用@Component及其同类型的注解(@Controller、@Service、@Repository)注释在类上,以便该类能够以Bean的形式注入到Spring的容器中。
@Component
public class Car {
}
3)Spring容器启动:
public class MoBianTestScan {
public static void main(String[] args) {
// 使用配置文件的形式获取
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
System.out.println(context.getBean("car"));
// 使用xml文件的形式获取
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-test.xml");
System.out.println(context.getBean("car"));
}
}
二、编程式
4、BeanDefinition接口
1)Spring容器启动:
public class MainTest1 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 创建一个beanDefinition,并设置对应的beanDefinition对象的bean的类型
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
beanDefinition.setBeanClass(MoBian.class);
// 将beanDefinition注册到Spring容器中,并设置对应的Bean的名字
context.registerBeanDefinition("mobian",beanDefinition);
context.refresh();
System.out.println(context.getBean("mobian"));
}
}
该方式在启动的时候就可以不需要任何的配置文件。当我们在使用声明式方式配置Bean时,其底层都是使用的该方式进行配置
5、FactoryBean接口
1)创建一个需要的类:
public class Car {
}
2)实现FactoryBean接口的类:
实现FactoryBean接口,重写getObject和getObjectType两个方法
public class MoBian2 implements FactoryBean {
@Override
public Object getObject() throws Exception {
return new Car();
}
@Override
public Class<?> getObjectType() {
return Car.class;
}
}
3)Spring容器启动:
public class MainTest3 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
// 此处我们还是采用编程式的方式定义Bean,即第四种方式
// 当然,此处也可以将该Bean使用声明式的方式定义
AbstractBeanDefinition definition = BeanDefinitionBuilder.genericBeanDefinition().getBeanDefinition();
definition.setBeanClass(MoBian2.class);
context.registerBeanDefinition("mobian",definition);
context.refresh();
// 获取getObject方法返回的对象
System.out.println(context.getBean("mobian"));
// 获取注册到Spring容器的beanDefinition的名字
System.out.println(context.getBean("&mobian"));
}
}
使用该方式会生成两个Bean对象,一个是getObject方法中返回对象对应的类生成的Bean,一个是实现了FactoryBean接口的类生成的Bean。我们注册到Spring容器中的Bean是实现了FactoryBean接口的类生成的Bean,但是我们在获取实现了FactoryBean接口的类的Bean时,却需要使用&+注册BeanDefinition时的名字,而用注册BeanDefinition时使用的名字获取到的则是getObject方法返回的对象。
上例的测试结果:
6、Supplier接口
1)Spring容器启动:
public class MainTest2 {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.registerBean(MoBian.class, new Supplier<MoBian>() {
@Override
public MoBian get() {
return new MoBian();
}
});
context.refresh();
System.out.println(context.getBean("moBian"));
}
}
直接将对应类型的Bean注册到Spring容器中,后面的参数为一个函数式接口(即jdk1.8之后才支持该方式),直接重写它的get方法,即可完成Spring容器中Bean的定义。