Spring-几种组件注册方式

Spring-几种组件注册方式

happybean

happybean

一只不正经的程序猿。。。

IOC(Inversion of Control)控制反转,spring中的核心,有了ioc容器,在程序开发过程中可以将bean对象托管给Spring容器进行管理(管理对象的生命周期,对象之间的依赖关系等),从而更好的专注于业务开发,减少代码工作量。

下面介绍几种组件注册到容器中的方式

!注意以下Spring版本不同,实现方式可能会到受影响

1.配置文件注册方式

引入spring-context maven依赖

<dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-context</artifactId>
 <version>4.3.17.RELEASE</version>
</dependency>

bean测试类

public class Person {

 private String name;

 private int age;

 public Person() {
 }

 public Person(String name, int age) {
 this.name = name;
 this.age = age;
 }

 public String getName() {
 return name;
 }

 public void setName(String name) {
 this.name = name;
 }

 public int getAge() {
 return age;
 }

 public void setAge(int age) {
 this.age = age;
 }

 @Override
 public String toString() {
 return "Person{" +
 "name='" + name + '\'' +
 ", age=" + age +
 '}';
 }
}

创建spring-bean.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">

 <!--基于配置方式 id,name 要保证唯一性-->
 <bean class="org.happybean.bean.Person" name="person1" id="person1-id" >
 <property name="name" value="spring1"/>
 <property name="age" value="20"/>
 </bean>

 <bean class="org.happybean.bean.Person" name="person2" id="person2-id" >
 <property name="name" value="spring2"/>
 <property name="age" value="21"/>
 </bean>
</beans>

测试使用

public static void main(String[] args) {
 //加载配置文件
 ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring-bean.xml");

 //根据 bean name 获取,需要类型强制转换
 Person person1 = (Person) applicationContext.getBean("person1");
 System.out.println("person1:"+person1);

 //根据bean id 获取,需要类型强制转换
 Person person2 = (Person) applicationContext.getBean("person2-id");
 System.out.println("person2:"+person2);

 //根据bean类型获取,无需要类型强制转换,
 //使用此种方式时要保证改类型bean只配置一个,否则会抛出异常 org.springframework.beans.factory.NoUniqueBeanDefinitionException
 Person person3 = applicationContext.getBean(Person.class);
 System.out.println("person3:"+person3);

 //根据bean name和类型获取,无需要类型强制转换
 //多个相同类型bean时,可以使用该方法获取
 Person person4 = applicationContext.getBean("person1", Person.class);
 System.out.println("person4:"+person4);
}

2.配置类注册方式

配置类

@Configuration
public class SpringConfig {

 //@Configuration 告诉spring这是一个配置类

 @Bean
 public Person person1(){
 //@Bean 将对象注册到容器 name默认为方法名
 return new Person("spring1",20);
 }

 @Bean(name = "person2-name")
 public Person person2(){
 //@Bean 将对象注册到容器 id默认为方法名
 return new Person("spring2",21);
 }
}

测试使用

public static void main(String[] args) {
 //加载配置类 此时的配置类等同于xml配置文件
 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);

 //根据bean 默认name(方法名) 获取,需要类型强制转换
 Person person1 = (Person) applicationContext.getBean("person1");
 System.out.println("person1:" + person1);

 //根据 bean name 获取,需要类型强制转换
 Person person2 = (Person) applicationContext.getBean("person2-name");
 System.out.println("person2:" + person2);

 //根据bean name和类型获取,无需要类型强制转换
 //多个相同类型bean时,可以使用该方法获取
 Person person4 = applicationContext.getBean("person1", Person.class);
 System.out.println("person4:" + person4);

 //获取bean 在容器中的 name
 String[] beanNames = applicationContext.getBeanDefinitionNames();
 for (String name : beanNames) {
 System.out.println(name);
 }
}

3.Xml配置文件包扫描方式

配置文件 spring-scan.xml

<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 http://www.springframework.org/schema/context/spring-context.xsd">
 <!--配置文件方式扫描,@Controller @Service @Repository等注解的类会以bean方式注册到容器中-->
 <context:component-scan base-package="org.happybean.controller,org.happybean.service,org.happybean.repository"/>
</beans>

注册bean时默认使用单例模式注入,或者可以在bean标签中定义 scope="prototype"定义为多实例模式

4.配置类注解包扫描方式

配置类

@Configuration
@ComponentScan(value = {"org.happybean.controller", "org.happybean.service", "org.happybean.repository"})
public class SpringConfig {
}

包扫描方式会默认以类首字母小写作为 bean name,或者也可以用@Controller("SpringController")方式自定义name

当然你也可以使用 @ComponentScan中的excludeFilters排除不需要注册到容器中的类

或用以下配置类方式实现多实例模式

@Bean
@Scope("prototype")
public Person person1() {
 return new Person("spring1", 20);
}

通过测试我们可以得知,在使用默认的单例模式注册时,spring会使用饿汉模式进行注册,如果想改为懒加载模式(懒汉模式),可以在xml配置文件bean标签中加入lazy-init="true”,或者以如下方式实现

@Lazy
@Bean(name = "person2-name")
public Person person2() {
 //@Bean 将对象注册到容器 id默认为方法名
 //使用@Lazy将单例模式下的bean改为懒加载模式(懒汉模式)
 return new Person("spring2", 21);
}

5.条件注册方式

如果你想满足某种条件下才注册bean,可以使用如下方式

创建一个注册条件类 必须实现 org.springframework.context.annotation.Condition

public class OsCondition implements Condition {

 /**
 * 满足操作系统是mac时才会创建 name为乔布斯的bean
 *
 * @param conditionContext 上下文(环境)
 * @param annotatedTypeMetadata 注解信息
 */
 @Override
 public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) {
 //获取环境信息
 Environment environment = conditionContext.getEnvironment();
 //获取操作系统信息
 String osName = environment.getProperty("os.name");
 if (osName.equals("Mac OS X")) {
 return true;
 }
 return false;
 }
}

bean配置

@Bean
@Conditional(OsCondition.class)
public Person steveJobs() {
 //@Conditional 满足某种条件下才会注册bean
 return new Person("steveJobs", 56);
}

测试使用

public static void main(String[] args) {
 //加载配置类 此时的配置类等同于xml配置文件
 ApplicationContext applicationContext = new AnnotationConfigApplicationContext(SpringConfig.class);
 //获取bean 在容器中的 name
 String[] beanNames = applicationContext.getBeanDefinitionNames();
 for (String name : beanNames) {
 System.out.println(name);
 }
}

这种方式在springboot中也大量的使用

6.手动注册方式

也许你还想自己手动注册一个bean,可以尝试如下写法

public static void main(String[] args) {
 //加载配置类 此时的配置类等同于xml配置文件
 ApplicationContext applicationContext = new AnnotationConfigApplicationContext();

 //获取bean工厂
 ConfigurableApplicationContext configurableContext = (ConfigurableApplicationContext) applicationContext;
 BeanDefinitionRegistry registry = (DefaultListableBeanFactory) configurableContext.getBeanFactory();
 //bean builder
 BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Person.class);
 BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
 //手动注册bean
 registry.registerBeanDefinition("manual", beanDefinition);

 //获取bean 在容器中的 name
 String[] beanNames = applicationContext.getBeanDefinitionNames();
 for (String name : beanNames) {
 System.out.println(name);
 }
}

 

7.快速注册方式

如果你想快速将一个类注册到容器中,可以使用@Import

bean 默认name是类全名 例如:org.happybean.bean.Person

@Configuration
@Import({Person.class})
public class SpringConfig {
}

@Import中可以写多个class

8.批量注册方式

可以在@Import注解中添加一个ImportSelector类以实现批量注册的功能

自定义注册选择器

public class SpringImportSelector implements ImportSelector {
 /**
 * 注册的所有类
 *
 * @param annotationMetadata 当前类注解的信息 例如:@Import
 * @return 所有需要注册到容器的全类名
 */
 @Override
 public String[] selectImports(AnnotationMetadata annotationMetadata) {
 String[] className = {"org.happybean.bean.Animal"};
 return className;
 }
}

配置类

@Configuration
@Import(SpringImportSelector.class)
public class SpringConfig {
}

9.@Import注解 手动注册方式

此时你需要编写一个org.springframework.context.annotation.ImportBeanDefinitionRegistrar

实现类

public class SpringImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {

 /**
 * @param annotationMetadata  当前类注解信息
 * @param beanDefinitionRegistry beanDefinition 注册类
 */
 @Override
 public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
 //判断是否存在 name为animal 的bean
 if (!beanDefinitionRegistry.containsBeanDefinition("animal")) {
 BeanDefinitionBuilder beanDefinitionBuilder = BeanDefinitionBuilder.genericBeanDefinition(Animal.class);
 BeanDefinition beanDefinition = beanDefinitionBuilder.getBeanDefinition();
 beanDefinitionRegistry.registerBeanDefinition("animal", beanDefinition);
 }
 }
}

使用方式同上

@Configuration
@Import(SpringImportBeanDefinitionRegistrar.class)
public class SpringConfig {
}

转载于:https://my.oschina.net/u/3439484/blog/3023014

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值