一、将javaBean装载到容器中的方式(注解版)
一、自定义的javabean装载到容器中
1.1、@ComponentScan+@Component
对于我们自己创建(自定义)的javabean,将它加入到Spring容器中,我们一般使用@ComponentScan+@Component注解的方式将它加到组件中。@ComponentScan的value属性指定包扫描路径,指定包及其子包下标注了@Component注解的Javabean会被加到容器中(注意:@Controller、@Service、@Repository本质上也是@Component,他们的作用本质是一样的)
示例:
1、配置类
/**
*
* @ComponentScan注解包扫描,会将指定包下标注了@Component、@Controller、@Service、@Resposity的组件加载到容器中去。
* 它有以下常用属性:
* 1、basePackages属性:指定要扫描的包
* 2、useDefaultFilters:是否使用默认的过滤器,默认是true。想自己指定过滤规则时要将该属性设置为false
* 3、includeFilters属性:指定满足被扫描的包下的组件要满足哪些条件才能被加到容器中,它是一个@Filter集合
* @Filter过滤注解。它的常用属性如下:
* 1、type属性指定根据什么条件过滤 1)FilterType.ANNOTATION根据注解类型过滤
* 2)FilterType.ASSIGNABLE_TYPE根据组件的类型过滤
* 3)FilterType.ASPECTJ根据ASPECTJ表达式过滤
* 4)FilterType.REGEX根据正则表达式过滤(基本不用、我也不太会)
* 5)FilterType.CUSTOM自定义过滤规则
* 4、excludeFilters属性:指定不将哪些包加入到容器中,用法和includeFilters属性差不多
*/
@ComponentScan(
basePackages={"com.tellhow.review.spring_annotation.componenttocontainer"},
useDefaultFilters=false,
includeFilters = {@ComponentScan.Filter(type = FilterType.CUSTOM, classes = {MyTypeFilter.class})}
)
@Slf4j
@Configuration//标注了@Configuration注解的类,Spring会将它识别为配置类。标注了@Configuration注解的类也会当做组件加到容器中
public class SpringAnnotationAddComponent {
public static void main(String[] args) {
ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MyConfig.class);
for (String beanDefinitionName : applicationContext.getBeanDefinitionNames()) {
log.info(beanDefinitionName);
}
}
}
//自定义类型过滤器,用来过滤不需要加到容器的组件
class MyTypeFilter implements TypeFilter {
/**
* 确定此筛选器是否与给定元数据所描述的类匹配。
* @param metadataReader 目标类(被扫描类扫描的类)的元数据读取器
* @param metadataReaderFactory 为其他类(如超类和接口)获取元数据读取器的工厂
* @throws IOException
* return 返回值为trues时才会被加到容器中
*/
@Override
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) {
ClassMetadata classMetadata = metadataReader.getClassMetadata();
if (classMetadata.getClassName().contains("Service")){//如果被加到容器中的类名包括Service,就不添加到容器中
return false;
}
return true;
}
}
2、组件类(这个类在指定扫描包下并标注了@Controller注解,且这个类没有过滤掉,所以这个类是实例会被加到容器中)
package com.tellhow.review.spring_annotation.componenttocontainer.controller;
import org.springframework.stereotype.Controller;
/**
* @author wujianghao
* @date 2022年10月28日 10:27
*/
@Controller
public class ComponentController {
}
二、将第三方jar的javaBean作为组件加到容器中
从第三方引入的类,由于不是我们编写的。这些类上一般不会标@Component注解。而且我们是通过导入jar包的方式导入这些javabean的,导入的是class文件,无法对这些javabean添加@Component注解(实际上即使可以添加也不会添加,因为不方便管理),所以不适合用上面包扫描的方式,我们可以使用下面这些方式向Spring容器注入这个javabean作为组件。
2.1、@Configuration+@Bean
1)、@Configuration注解标注在类上,说明这个类是一个配置类。@Configuration注解有一个属性proxyBeanMethods,它用来指定是否应该代理@Bean方法以强制执行bean生命周期行为,例如,即使在用户代码中直接调用@Bean方法的情况下,也要返回共享的单例bean实例。
2)、在配置类的方法上标注@Bean,那么这个会以这个方法名作为组件名以方法的返回值作为组件值。
/**
* @Configuration注解用来标识这是一个配置类 他有一个重要的属性proxyBeanMethods属性是用来设置MyConfig配置类是否被代理。
* true的话通过调用MyConfig方法获取对象时(非从容器中取),每次取出来的都是同一个。
* false的话通过调用MyConfig方法获取对象时(非从容器中取),每次取出来的都不是同一个。
* 当配置类的中的bean之间存在依赖关系时,用proxyBeanMethods设置为true,没依赖关系设置为false,默认值是true
*/
@Configuration(proxyBeanMethods = true)
@Slf4j
public class MyConfig {
/**
* 在配置类中@Bean注解标识在方法上,这个的返回值会被当做组件加载到容器中,组件的名字是默认是方法名。也可与通过@Bean注解的value属性指定组件名称
*/
@Bean("spiritsBranch")
public AvenueBranchPojo spiritsBranch() {
log.info("---------鬼神道avenueBranchPojo单例对象开始创建----------");
return new AvenueBranchPojo();
}
/**
* @Scope注解:用来指定组件的作用域,通过value属性指定
* ConfigurableBeanFactory.SCOPE_PROTOTYPE//多例模式(每次从容器中获取的对象都不是相同的),在调用该对象时,才会创建对象
* ConfigurableBeanFactory.SCOPE_SINGLETON //单例模式(每次从容器中获取的对象都是相同的),项目在开始运行的时侯,就会创建对象
* org.springframework.web.context.WebApplicationContext.SCOPE_REQUEST//同一个请求域下(不用该作用域)
* org.springframework.web.context.WebApplicationContext.SCOPE_SESSION//同一个Session下(不用该作用域)
*/
@Scope(ConfigurableBeanFactory.SCOPE_SINGLETON)//多例模式
@Bean("worldPojo")
public WorldPojo worldPojo() {
log.info("--------传武世界WorldPojo(多例)对象开始创建---------");
WorldPojo worldPojo = new WorldPojo();
worldPojo.setName("传武世界");
return worldPojo;
}
@Lazy//懒加载,bean的作用域为单例时,项目开始运行就调用下面的方法并创建出该对象。我们想在用到该对象才创建,只需要加一个@Lazy注解。作用域为多例在调用的时才会创建对象。所以这个注解对于多例模式没有用
@Bean("creationBranch")
@Scope(value = ConfigurableBeanFactory.SCOPE_SINGLETON)//这个bean的作用域
@Conditional(value = {MyCondition.class})//条件装配注解,这个组件满足条件的才会被装载到容器中
public AvenueBranchPojo creationBranch() {
log.info("----------万物道AvenueBranchPojo单例对象开始创建(懒加载)----------");
return new AvenueBranchPojo();
}
/**
*我们向容器添加BeanFactory类型的组件,我们从容器中取,取出来的不是BeanFactory组件本身。而是FactoryBean的getObject()方法的返回值对象
*
*/
@Bean("myFactoryBean")
public MyFactoryBean myFactoryBean() {
log.info("--------传武世界myFactoryBean(多例)对象开始创建---------");
MyFactoryBean myFactoryBean = new MyFactoryBean();
return myFactoryBean;
}
}
//实现FactoryBean 的bean不能作为普通bean使用。FactoryBean是以bean样式定义的,但是为bean引用公开的对象(getObject())始终是它所创建的对象
class MyFactoryBean implements FactoryBean {
@Override
public Object getObject() throws Exception {
WorldPojo worldPojo = new WorldPojo();
worldPojo.setName("斗罗大陆");
worldPojo.setWId("10086");
return worldPojo;
}
@Override
public Class<?> getObjectType() {
return WorldPojo.class;
}
}
/**
* 条件装配类,可以给组件指定满足条件的才会被装配到容器中
*/
class MyCondition implements Condition {
/**
*
* @param context 环境条件
* @param metadata 被检查的类的方法或元数据
* @return 是否满足匹配条件
*/
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
return context.getRegistry().containsBeanDefinition("worldPojo")?true:false;
}
}
2.1、@import注解
@import注解提供等同于Spring XML中的元素的功能。允许导入@Configuration类、ImportSelector和importbeandefinitionregistry实现,以及常规组件类(从4.2开始;类似于AnnotationConfigApplicationContext.register)。
1、使用@import注解组件到容器中
1、将@import注解标在配置类中(不一定非是配置类,只要是组件类都可以)
@Configuration
@Import(value = {UnitedPojo.class,MyImportSector.class,MyImportBeanDefinitionRegistrar.class})
public class MyConfig {
}
2、自定义ImportSector类
public class MyImportSector implements ImportSelector {
//根据导入的@Configuration类的AnnotationMetadata选择并返回应该导入的类的名称。
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
String className = PersonPojo.class.getName();
return new String[]{className};
}
}
3、自定义MyImportBeanDefinitionRegistrar
public class MyImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
//根据导入的@Configuration类的给定注释元数据,根据需要注册bean定义。注意,由于与@Configuration类处理相关的生命周期约束,这里可能没有注册BeanDefinitionRegistryPostProcessor类型。默认实现是空的。Params: importingClassMetadata -导入类注册表的注释元数据-当前bean定义注册表
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
//注册bean的定义信息
registry.registerBeanDefinition("commonController",new RootBeanDefinition(CommonController.class));
}
}
本文介绍了如何使用注解在Spring中将自定义的JavaBean和第三方jar的JavaBean加入到容器中。对于自定义Bean,通过@ComponentScan配合@Component进行包扫描。对于第三方库的Bean,可以利用@Configuration结合@Bean注解,或者使用@import注解导入@Configuration类或组件。
168万+

被折叠的 条评论
为什么被折叠?



