使用方式:
1、借助 @Import 注解类,创建ImportBeanDefinitionRegistrar的子类,手动构造BeanDefinition对象并注册到容器
2、借助BeanFactoryPostProcessor接口类,通过ClassPathBeanDefinitionScanner类扫描并注册类到容器
3、借助 @Import 注解类,创建ImportBeanDefinitionRegistrar的子类,通过ClassPathBeanDefinitionScanner类扫描并注册类到容器
一、通过创建 ImportBeanDefinitionRegistrar 的子类实现
public class User { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } } /** * 通过创建 ImportBeanDefinitionRegistrar 的子类实现手动将bean注入到Spring容器中。 * 在方法registerBeanDefinitions中构造BeanDefinition对象,并调用BeanDefinitionRegistry的registerBeanDefinition方法注册 * 然后通过@Import注解导入到Spring容器中。 */ public class MapperImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar, ResourceLoaderAware{ private ResourceLoader resourceLoader; @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { registerUserBean(registry); } private void registerUserBean(BeanDefinitionRegistry registry){ if(!registry.containsBeanDefinition(User.class.getSimpleName())){ BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(User.class); GenericBeanDefinition beanDefinition = (GenericBeanDefinition)builder.getRawBeanDefinition(); beanDefinition.setBeanClass(User.class); beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE); //设置目标Bean的属性值 beanDefinition.getPropertyValues().add("username", "abc"); beanDefinition.getPropertyValues().add("password", "123"); registry.registerBeanDefinition(User.class.getSimpleName(), beanDefinition); } } @Override public void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } } /** * CommandLineRunner: * 用于在应用程序启动前执行某些动作。 * 在所有Spring Beans都初始化之后,SpringApplication.run()之前执行。 * 如果存在多个CommandLineRunner的实现类,可以使用@Order注解来排序。 */ @SpringBootApplication() @Import({MapperImportBeanDefinitionRegistrar.class}) public class Main implements CommandLineRunner { @Autowired private User user; public static void main(String[] args){ SpringApplication.run(Main.class, args); } @Override public void run(String... args) throws Exception { System.out.println(user.getUsername() + ", " + user.getPassword()); } }
二、通过创建 BeanFactoryPostProcessor 的子类,并结合ClassPathBeanDefinitionScanner类实现
BeanFactoryPostProcessor: 在Bean初始化之前Spring容器会回调该类的postProcessBeanFactory方法。
ClassPathBeanDefinitionScanner:将指定包下的类通过一定规则过滤后将Class信息包装成 BeanDefinition 的形式注册到IOC容器中。
/** * 自定义注解类 */ @Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface Mapper { String value() default ""; } /** * 接口类 */ public interface CountryMapper { void show(); } /** * 接口的实现类,该类用自定义注解@Mapper进行标注 */ @Mapper public class CountryMapperImpl implements CountryMapper { @Override public void show(){ System.out.println("invoke show..."); } } /** * BeanFactoryPostProcessor的子类 * 在Bean初始化之前Spring容器会回调该类的 postProcessBeanFactory 方法 */ @Component public class MapperBeanFactoryPostProcessor implements BeanFactoryPostProcessor, ApplicationContextAware { private ApplicationContext applicationContext; @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { //扫描满足特定规则的类,并注册到容器中 MapperClassPathBeanDefinitionScanner scanner = new MapperClassPathBeanDefinitionScanner((BeanDefinitionRegistry)beanFactory); scanner.setResourceLoader(this.applicationContext); scanner.registerDefaultFilters(); scanner.scan(MapperClassPathBeanDefinitionScanner.BASE_PACKAGES); } } public class MapperClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner{ public static final String BASE_PACKAGES = "com.seasy.springboottest"; public MapperClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) { super(registry); } public void registerDefaultFilters() { //默认:根据指定注解类@Mapper过滤出满足条件的类 TypeFilter typeFilter = new AnnotationTypeFilter(Mapper.class); //根据指定的类(包括子类和接口类)过滤出满足条件的类 // TypeFilter typeFilter = new AssignableTypeFilter(CountryMapperImpl.class); // TypeFilter typeFilter = new AssignableTypeFilter(CountryMapper.class); this.addIncludeFilter(typeFilter); } @Override protected Set<BeanDefinitionHolder> doScan(String... basePackages) { return super.doScan(basePackages); } @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { return super.isCandidateComponent(beanDefinition) && beanDefinition.getMetadata().hasAnnotation(Mapper.class.getName()); } } @SpringBootApplication() public class Main implements CommandLineRunner { @Autowired private CountryMapper countryMapper; public static void main(String[] args){ SpringApplication.run(Main.class, args); } @Override public void run(String... args) throws Exception { countryMapper.show(); } }
三、通过FactoryBean和Spring代理创建
/** * 自定义注解类 */ @Documented @Inherited @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.TYPE}) public @interface Mapper { String value() default ""; } //创建接口类,并用自定义注解类标注 @Mapper public interface RoleMapper{ public void printRole(); } @Mapper public interface UserMapper{ public void print(); } /** * 自定义拦截器 */ public class CustomMethodInterceptor implements MethodInterceptor{ @Override public Object invoke(MethodInvocation invocation) throws Throwable { StopWatch stopWatch = new StopWatch(); stopWatch.start(); Object object = null; //接口没有对应的实现类,不能直接调用 invocation.proceed() 方法 //object = invocation.proceed(); //在此处编写业务逻辑 //...... System.out.println(invocation.getMethod().getDeclaringClass().getName() + ": " + invocation.getMethod().getName()); stopWatch.stop(); System.out.println("执行时间:" + stopWatch.getTotalTimeMillis() + "ms"); return object; } } /** * 工厂Bean:通过Spring代理工厂创建代理类 */ public class ScannerFactoryBean implements FactoryBean<Object>{ private ProxyFactory factory; private String interfaceClassName; public void setInterfaceClassName(String interfaceClassName) { this.interfaceClassName = interfaceClassName; try { factory.setInterfaces(Class.forName(interfaceClassName)); } catch (ClassNotFoundException e) { e.printStackTrace(); } } public ScannerFactoryBean(){ factory = new ProxyFactory(); //Spring代理工厂 factory.addAdvice(new CustomMethodInterceptor()); } @Override public Object getObject() throws Exception { return factory.getProxy(); } @Override public Class<?> getObjectType() { try { if(StringUtils.hasText(interfaceClassName)){ return Class.forName(interfaceClassName); } } catch (ClassNotFoundException e) { e.printStackTrace(); } return null; } @Override public boolean isSingleton() { return true; } } /** * 自定义BeanDefinition扫描器 */ public class ScannerClassPathBeanDefinitionScanner extends ClassPathBeanDefinitionScanner{ private ScannerFactoryBean scannerFactoryBean = new ScannerFactoryBean(); public ScannerClassPathBeanDefinitionScanner(BeanDefinitionRegistry registry) { super(registry); } @Override protected Set<BeanDefinitionHolder> doScan(String... basePackages) { Set<BeanDefinitionHolder> beanDefinitions = super.doScan(basePackages); ScannedGenericBeanDefinition beanDefinition; for(BeanDefinitionHolder holder : beanDefinitions){ beanDefinition = (ScannedGenericBeanDefinition) holder.getBeanDefinition(); if(beanDefinition.getMetadata().isInterface()){ //是接口类 //添加BeanClass的属性值 beanDefinition.getPropertyValues().add("interfaceClassName", beanDefinition.getBeanClassName()); beanDefinition.setBeanClass(scannerFactoryBean.getClass()); //通过工厂Bean获取Bean对象 } } return beanDefinitions; } /** * 是候选组件 */ @Override protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) { AnnotationMetadata metadata = beanDefinition.getMetadata(); //isIndependent独立的、isConcrete具体的、isInterface接口 return metadata.isIndependent() && (metadata.isConcrete() || metadata.isInterface()); } } public class ScannerImportBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar{ @Override public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) { //BeanDefinition扫描器 ClassPathBeanDefinitionScanner scanner = new ScannerClassPathBeanDefinitionScanner(registry); scanner.addIncludeFilter(new AnnotationTypeFilter(Mapper.class)); //基于注解类进行扫描过滤 scanner.scan("com.seasy.springboottest"); } } /** * 配置类 */ @Configuration //通过导入的方式把实例加入SpringIOC容器中 @Import(value = {ScannerImportBeanDefinitionRegistrar.class}) public class ScannerConfig { } @RunWith(SpringJUnit4ClassRunner.class) @SpringBootTest(classes = Main.class) public class ScannerTest { @Test public void test3()throws Exception{ //基于配置类加载Spring的应用上下文 AnnotationConfigApplicationContext applicationContext = new AnnotationConfigApplicationContext(ScannerConfig.class); UserMapper userMapper = (UserMapper)applicationContext.getBean("userMapper"); userMapper.print(); RoleMapper roleMapper = (RoleMapper)applicationContext.getBean("roleMapper"); roleMapper.printRole(); } }
RuntimeBeanReference:
一个bean可能需要依赖其他的bean,而在Spring的解析阶段,其实容器中是没有依赖的Bean的实例的。为了表示这个被依赖的bean,在解析到依赖的Bean的时侯,解析器会依据依赖bean的name创建一个RuntimeBeanReference对像,将这个对像放入BeanDefinition的MutablePropertyValues中。
reference = new RuntimeBeanReference("otherBeanName");
beanDefinition.getPropertyValues().addPropertyValue("referBeanName", reference);
在创建Bean时,需要将依赖解析成真正的在Spring容器中存在的Bean。这是在getBean时由AbstractAutowireCapableBeanFactory在applyPropertyValues方法中通过BeanDefinitionValueResolver来实现的。BeanDefinitionValueResolver将真正的依赖bean和referBeanName关联起来。
相关推荐
在本篇博文中,我们将深入探讨如何在Spring Boot应用中使用Java代码来创建Bean并将其注册到Spring容器中。这是Spring Boot的核心特性之一,它使得我们能够以编程方式管理对象,而无需XML配置。让我们逐步解析这个...
在Spring框架中,自动扫描和管理Bean是一种便捷的方式,它允许开发者无需显式地在配置文件中声明每个Bean,而是让Spring容器自动发现并管理应用中的组件。这一特性极大地简化了Spring应用的配置,提高了开发效率。...
- 使用`PlatformTransactionManager`接口的实现,如`DataSourceTransactionManager`,并将其注册到Spring容器中。 5. **扫描Mapper接口** - 通过`MapperScannerConfigurer`或`@MapperScan`注解,扫描包含MyBatis ...
这样,我们就创建了一个简单的注解处理器,它可以扫描指定包下所有带有`MyComponent`注解的类,并将它们注册为Spring的bean,bean的名称由注解的`value`属性决定。 最后,为了让Spring知道并执行我们的`...
IoC容器是通过扫描应用程序上下文来发现所有需要管理的bean,并根据bean定义来创建和初始化这些bean。在Spring中,bean可以通过XML配置、Java配置或者注解进行定义。在模拟实现时,我们可以创建一个`BeanDefinition`...
- 避免过度使用`getBean()`:频繁使用`getBean()`可能导致代码过于紧密地耦合于Spring容器,降低代码的可读性和可测试性。 总结,Spring框架通过BeanFactory和ApplicationContext提供了灵活的方式来管理和获取Bean...
它会遍历指定包及其子包下的所有类,寻找带有特定注解(如@Service、@Component、@Repository、@Controller等)的类,并将这些类实例化为Spring容器中的bean。通过这种方式,我们可以避免手动编写大量的XML配置,...
当Spring容器加载这个配置类时,它会调用这些@Bean注解的方法,生成Bean实例并将其注册到IoC容器中。 在SIA实战项目中,我们可能会看到类似这样的代码片段: ```java @Configuration public class AppConfig { @...
扫描机制允许开发者声明类为Spring管理的bean,无需在XML配置文件中手动注册。Spring通过`@Component`、`@Service`、`@Repository`和`@Controller`等注解标记类,然后使用`@ComponentScan`注解来指定哪些包应该被...
其核心思想是反转控制(IoC),即控制权由应用代码转移到了Spring容器。 10、什么是依赖注入? 依赖注入(DI)是一种设计模式,它允许一个对象通过构造器、工厂方法的参数或属性来定义它们对其他对象的依赖关系,...
当Spring容器遇到`@Bean`注解的方法时,它会执行该方法,将返回的对象添加到bean定义中,并根据需要进行依赖注入。你可以通过`@Bean`注解的参数来指定依赖关系,或者使用`@Autowired`注解来自动装配。 例如: ```...
在传统的编程模式中,开发者需要手动创建和管理对象,而在Spring IOC中,这个过程被反转,由Spring容器负责对象的创建、初始化、装配以及管理,开发者只需声明对象间的依赖,无需关心具体的实例化过程。 1. **Bean...
3. **MapperScannerConfigurer**:这个类用于扫描指定包下的 Mapper 接口,并自动将其注册到 Spring 容器中,这样就可以通过依赖注入的方式直接使用这些接口。 4. **MapperFactoryBean**:它是 Spring 的 ...
`@Bean`方法返回的对象将被注册为Spring容器中的一个Bean。 7. **属性注入** `@Value`注解可以用来注入基本类型或者从属性文件中读取的值。例如,`@Value("${property.name}")`可以从`application.properties`文件...
Spring通过容器管理对象及其依赖,使得开发者无需手动创建和配置对象,而是由Spring来负责。 **控制反转(Inversion of Control,IOC)** 是DI的另一种表述方式,核心思想是将对象的创建和管理权交给框架或容器,而...
AnnotationAwareAspectJAutoProxyCreator实现了这个接口,从而使得Spring容器在创建bean之后可以进行AOP相关的处理。它主要负责分析容器中的bean,寻找合适的切面,并将这些切面织入到目标bean中去。 后置处理器的...
在上述代码中,我们扫描了指定包路径下所有标记了`@MyComponent`注解的类,并将它们作为Bean定义注册到Spring容器中。 现在,我们来看看压缩包内的文件: 1. `pom.xml`:这是Maven项目的核心配置文件,它包含了...
Spring容器会根据这些定义创建Bean的实例,并负责其生命周期。 1. **Bean的声明**:有两种主要方式声明Bean,一种是使用XML配置,另一种是使用注解。在Spring Boot中,更倾向于使用注解,如@Component、@Service、@...
在实际开发中,自动扫描功能可以帮助我们避免手动注册每个Mapper接口,只需指定正确的包名,Spring就会自动查找并管理这些接口,大大提高了开发效率。同时,合理地整合和配置这三个框架,可以构建出一个灵活、可扩展...
DI允许我们声明bean间的依赖关系,而无需在代码中手动创建或查找依赖对象。Spring容器会根据配置自动装配bean。这可以通过构造函数注入、setter方法注入或者字段注入来实现。 4. **Scope**: Spring提供了多种bean的...