Spring中定义Bean的6种方式(声明式+编程式)




Spring中原生的定义Bean的方式可以分为两类六种,我们经常使用的仅是它其中一类中的三种。

这个有点像Spring中的事务,我们熟悉的也仅仅是它的声明式写法——@Transaction,并不熟悉编程式的写法,或许你会说,可以,但没必要。此处我不做评价。



Spring中定义Bean的方式可以分为两类,分别是声明式和编程式。顾名思义,声明式可以理解为用一个的标记去标识相关的信息,代码底层再对这些标识符进行一个解析处理;编程式则更多侧重于使用代码的形式去处理相关逻辑。前者使用更友好,后者更底层。





一、声明式

1、<bean>标签

如果我们以xml配置文件的方式启动Spring容器,那么我们就可以在xml配置文件中使用bean标签完成对一个Bean的定义

1)实体类:

public class MoBian3XML {
    
    
}



2)spring-test.xml:

扫描二维码关注公众号,回复: 13306473 查看本文章
<?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方法返回的对象。



上例的测试结果:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4IPtV4eh-1626606615309)(Spring中定义bean的六种原生方式.assets/image-20210718182927004.png)]




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的定义。

猜你喜欢

转载自blog.csdn.net/qq_44377709/article/details/118881453