Spring注解版-组件注册

给容器中注册组件的方法:

  1. @Bean注解方法返回实体注册, 一般在注册外部jar包中的类使用, 例如配置数据源DataSource…
  2. 包扫描(@ComponentScan)+组件标注注解(@Controller/@Sevice/@Respository/@Component)
  3. @Import或者实现ImportSeletor接口或者实现ImportBeanDefinitionRegistrar接口
  4. 实现FactoryBean接口, 再搭配使用@Bean注解注册实现类;
@Configuration & @Bean&@Scope&@Lazy

1. @Configuration
@Configuration注解标注的类, 则为一个配置类, 相当于xml配置文件
@configuration中有两个属性:
1).value: @configuration继承@component, spring会扫描所有被@component注解的类, 认为这些类是bean, 需要注入容器中; 所以value是用来指定这些类在容器中的id值;
2).proxyBeanMethods: 用来指定@Bean注解标注的方法是否使用代理,默认是true使用代理,直接从IOC容器之中取得对象;如果设置为false,也就是不使用注解,每次调用@Bean标注的方法获取到的对象和IOC容器中的都不一样,是一个新的对象,所以我们可以将此属性设置为false来提高性能;
2. @Bean
@Bean标注的方法, 方法返回的实体类会注入IOC容器中;
属性:
1).value: 指定bean在容器中的id值, 如果value不指定值, 则默认以方法名为beanid值;
2).initMethod: 指定bean的初始化方法;
3).destroyMethod:指定bean的销毁方法;
3. @Scope
指定bean的作用域, 存在四种值,分别为 singleton 单例, prototype 多例, request 同一次请求内, session 同一个session内;默认为singleton 单例模式;
若指定为 singleton且不是懒加载(查看@Lazy)的情况下, 则在容器启动时调用被@bean标注的方法将bean实例化, 之后获取bean都是从容器中获取,且每次获取都是同一个实体;
若指定为prototype, 则在获取bean时调用被@bean标注的方法获取bean, 每次获取时都重新调用被@bean标注的方法, 所以每次获取的bean都是不同的;
4. @Lazy
指定作用域在单例模式下时是否启用懒加载, 默认是false; 如果设置value=true, 则在容器启动时, 不会实例化bean; spring会在第一次获取bean的时候实例化bean, 之后每次获取bean都是从容器中获取,不在创建新的bean;

// 告诉Spring这个类是一个配置类
@Configuration
public class SpringConfig {
	// 将user注册至容器中 相当于xml配置文件中配置<bean id="user" class="xx.xx.xx.model.User"></bean>
	@Bean
	public User user() {
		return new User();
	}
	
	@Bean
	@Scope(value = "singleton") // 单例模式
	@Lazy(value = true) // 启用懒加载
	public Human human(){
		return new Human();
	}

	/**
	 * @see ConfigurableBeanFactory#SCOPE_PROTOTYPE prototype 多例
	 * @see ConfigurableBeanFactory#SCOPE_SINGLETON singleton 单例
	 * @see org.springframework.web.context.WebApplicationContext#SCOPE_REQUEST request 同一次请求内
	 * @see org.springframework.web.context.WebApplicationContext#SCOPE_SESSION session 同一个session内
	 */
	@Scope(value = "prototype") // 多例模式
	@Bean(value="man", initMethod="personInit", destoryMethod="personDestory")
	public Person person(){
		return new Person();
	}
}
@ComponentScan&@Filter&enum FilterType

1. @ComponentScan
在配置类上标注此注解, 配置spring需要扫描的包路径, 将符合包路径条件且标注了@Controller/@Service/@Repository/@Component等注解的类注册至容器中;
1).value: 指定包扫描的路径;
2).includeFilters:指定包含过滤条件, Filter数组类型, 配合@Filter注解使用;
3).excludeFilters:指定排除过滤条件, Filter数组类型, 配合@Filter注解使用;
2. @Filter
用于@CmponentScan注解中配置过滤条件
1).type:指定过滤条件类型; 包含:①FilterType.ANNOTATION 注解类型;②FilterType.ASSIGNABLE_TYPE 指定明确类型; ③FilterType.ASPECTJ 使用ASPECTJ表达式, 不常用;
FilterType.REGEX 正则表达式,不常用;⑤FilterType.CUSTOM 自定义过滤条件类型, 需要创建一个实现了org.springframework.core.type.filter.TypeFilter的类, 重写method方法, 在方法中进行自定义匹配规则;
2)valueclasses:根据指定过滤条件类型, 配置具体过滤的类, class<?>[]数组类型;

@Configuration(value="config")
@ComponentScan(value = "study.bryan.spring", 
excludeFilters = { // 排除
		// 排除掉被@Controller注解标注的类 
		@Filter(type = FilterType.ANNOTATION, classes = {Controller.class}), 
		// 排除 PersonBookServiceImpl,BookServiceImpl这两个类
		@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {PersonBookServiceImpl.class, BookServiceImpl.class})		 
},
includeFilters = { // 包含
		@Filter(type = FilterType.ASSIGNABLE_TYPE, classes = {BookController.class}),
		// 自定义规则  MyTypeFilter 实现TypeFilter接口, 根据match方法匹配
		@Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})
}
)
public class SpringConfig {
	@Bean
	public User user() {
		return new User();
	}
}

/** 自定义TypeFilter 用于FilterType.CUSTOM类型过滤条件*/
import org.springframework.core.type.filter.TypeFilter;
public class MyTypeFilter implements TypeFilter{
	/**
	 * metadataReader: 获取当前类的信息
	 * metadataReaderFactory: 获取其他类的信息
	 */
	public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory)
			throws IOException {
		// 获取当前扫描类的注解信息
		AnnotationMetadata annotationMetadata = metadataReader.getAnnotationMetadata();
		// 获取当前扫描类的资源信息(例如类路径)
		Resource resource = metadataReader.getResource();
		// 获取当前扫描类的类信息
		ClassMetadata classMetadata = metadataReader.getClassMetadata();
		String className = classMetadata.getClassName();
		if (className.contains("Dao")) {
			return true;
		}
		return false;
	}
}
@Conditional

指定条件, 满足条件则将bean注入容器;
创建实现org.springframework.context.annotation.Condition接口的类, 并重写matchs方法, 即可将此类作为@Conditional注解的value条件值;

@Configuration
public class SpringConfig {
	@Conditional({WinCondition.class})
	@Bean(value = "bill")
	public Person person01() {
		return new Person();
	}
	
	@Conditional({LinuxCondition.class})
	@Bean(value = "linus")
	public Person person02() {
		return new Person();
	}
}

import org.springframework.context.annotation.Condition;
public class WinCondition implements Condition {
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {	
		Environment environment = context.getEnvironment();
		String property = environment.getProperty("os.name");
		if (property.contains("Win")) {
			return true;
		}
		return false;
	}
}

public class LinuxCondition implements Condition {
	public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {	
		Environment environment = context.getEnvironment();	
		String property = environment.getProperty("os.name");
		if (property.contains("linux")) {
			return true;
		}	
		return false;
	}
}
@Import&ImportSeletor&ImportBeanDefinitionRegistrar

@Import
可以在配置类上直接指定需要注册至容器中的类, id为全类名, 实现快速注册一个组件;
ImportSeletor
创建一个实现org.springframework.context.annotation.ImportSelector接口的类, 重写selectImports方法, 在方法中返回需要注册的组件的全类名数组, 搭配@Import注解, 可将返回数组中类注册至容器中;
ImportBeanDefinitionRegistrar
创建一个实现org.springframework.context.annotation.ImportBeanDefinitionRegistrar接口的类, 重写registerBeanDefinitions方法, 在方法中使用org.springframework.beans.factory.support.BeanDefinitionRegistry类调用registerBeanDefinition()方法将组件直接注册;最后搭配@Import注解, 将自定义类放在@Import注解的值中;

@Configuration
// Green类被直接以全类名方式注册至容器中
// MyImportSeletor中selectImports方法返回的全类名数组中的类被注册至容器中
// MyImportBeanDefinitionRegistar中registerBeanDefinitions方法手动注册了组件
@Import({Green.class, MyImportSeletor.class, MyImportBeanDefinitionRegistar.class})
public class SpringConfig {
	...
}

/**实现ImportSelector接口, 在selectImports方法中返回组件全类名*/
import org.springframework.context.annotation.ImportSelector;
import org.springframework.core.type.AnnotationMetadata;
public class MyImportSeletor implements ImportSelector {
	/**
	 * AnnotationMetadata 当前被标注@import注解的配置类信息
	 * @return 返回全类名数组, 不能为null
	 */
	public String[] selectImports(AnnotationMetadata importingClassMetadata) {
		String[] arr = new String[] {
				"study.bryan.spring.model.Blue",
				"study.bryan.spring.model.Red"
		};
		return arr;
	}
}

/**实现ImportBeanDefinitionRegistrar 接口,重写registerBeanDefinitions方法*/
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class MyImportBeanDefinitionRegistar implements ImportBeanDefinitionRegistrar {
	/**
	 * AnnotationMetadata 当前被标注@import注解的配置类信息
	 * BeanDefinitionRegistry BeanDefinition的注册类, 通过此类将组件手动注册至容器中
	 * @return 返回全类名数组, 不能为null
	 */
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		// new一个BeanDefinition  这个类即是Spring中存放组件信息的类,
		BeanDefinition beanDefinition = new RootBeanDefinition(Yellow.class);
		registry.registerBeanDefinition("yellow", beanDefinition);
	}
}
FactoryBean

实现org.springframework.beans.factory.FactoryBean<T>接口, 重写接口的getObject和getObjectType方法;在配置类中使用@Bean注解将实现了FactoryBean接口的类注册;

@Configuration
public class SpringConfig {
	// 这里的注册会将ColorFactoryBean 注册至容器中, 也会将ColorFactoryBean 中getObject方法返回的Color注册至容器中
	// 其中Color的Id为colorFactoryBean, ColorFactoryBean 的id为&colorFactoryBean
	@Bean
	public ColorFactoryBean colorFactoryBean() {
		return new ColorFactoryBean();
	}
}

import org.springframework.beans.factory.FactoryBean;
public class ColorFactoryBean implements FactoryBean<Color> {
	public Color getObject() throws Exception {
		// TODO Auto-generated method stub
		return new Color();
	}
	public Class<?> getObjectType() {
		// TODO Auto-generated method stub
		return Color.class;
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值