CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-micronaut--micronaut-inject

Core dependency injection interfaces and components for the Micronaut Framework

Pending
Overview
Eval results
Files

bean-providers.mddocs/

Bean Location and Providers

Bean providers and locators offer flexible, programmatic access to beans in the Micronaut context. They enable lazy instantiation, optional dependencies, and type-safe collection access to beans.

Core Interfaces

BeanProvider

Enhanced provider interface that extends Jakarta Provider with additional capabilities for bean introspection and collection access.

/**
 * Enhanced provider interface for accessing beans with additional capabilities
 * @param <T> The bean type
 */
public interface BeanProvider<T> extends jakarta.inject.Provider<T> {
    /**
     * Check if at least one bean of this type is available
     * @return true if a bean is present
     */
    boolean isPresent();
    
    /**
     * Check if exactly one bean of this type is available
     * @return true if only one bean matches
     */
    boolean isUnique();
    
    /**
     * Get an iterator over all available beans of this type
     * @return Iterator of bean instances
     */
    Iterator<T> iterator();
    
    /**
     * Get a stream of all available beans of this type
     * @return Stream of bean instances
     */
    Stream<T> stream();
    
    /**
     * Get the first available bean instance
     * @return Bean instance
     * @throws NoSuchBeanException if no bean is available
     */
    @Override
    T get();
}

Usage Examples:

import io.micronaut.context.BeanProvider;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;

@Singleton
public class NotificationService {
    
    // Lazy provider - bean resolved on first access
    private final BeanProvider<EmailService> emailProvider;
    
    @Inject
    public NotificationService(BeanProvider<EmailService> emailProvider) {
        this.emailProvider = emailProvider;
    }
    
    public void sendNotification(String message) {
        // Check if email service is available before using it
        if (emailProvider.isPresent()) {
            EmailService emailService = emailProvider.get();
            emailService.send(message);
        }
        
        // Process all notification handlers
        emailProvider.stream().forEach(handler -> handler.send(message));
    }
}

// Multiple implementations scenario
@Singleton
public class AggregatorService {
    
    private final BeanProvider<DataProcessor> processors;
    
    @Inject
    public AggregatorService(BeanProvider<DataProcessor> processors) {
        this.processors = processors;
    }
    
    public void processData(Data data) {
        // Use all available processors
        processors.iterator().forEachRemaining(processor -> 
            processor.process(data)
        );
    }
}

BeanLocator

Core interface for locating beans in the context with various resolution strategies.

/**
 * Core interface for bean location and resolution
 */
public interface BeanLocator {
    /**
     * Get a required bean of the given type
     * @param beanType The bean type
     * @return Bean instance
     * @throws NoSuchBeanException if bean not found
     */
    <T> T getBean(Class<T> beanType);
    
    /**
     * Get a required bean with qualifier
     * @param beanType The bean type
     * @param qualifier The qualifier
     * @return Bean instance
     * @throws NoSuchBeanException if bean not found
     */
    <T> T getBean(Class<T> beanType, Qualifier<T> qualifier);
    
    /**
     * Find an optional bean of the given type
     * @param beanType The bean type
     * @return Optional bean instance
     */
    <T> Optional<T> findBean(Class<T> beanType);
    
    /**
     * Find an optional bean with qualifier
     * @param beanType The bean type
     * @param qualifier The qualifier
     * @return Optional bean instance
     */
    <T> Optional<T> findBean(Class<T> beanType, Qualifier<T> qualifier);
    
    /**
     * Get all beans of the given type
     * @param beanType The bean type
     * @return Collection of bean instances
     */
    <T> Collection<T> getBeansOfType(Class<T> beanType);
    
    /**
     * Get all beans of the given type with qualifier
     * @param beanType The bean type
     * @param qualifier The qualifier
     * @return Collection of bean instances
     */
    <T> Collection<T> getBeansOfType(Class<T> beanType, Qualifier<T> qualifier);
    
    /**
     * Get bean provider for the given type
     * @param beanType The bean type
     * @return BeanProvider instance
     */
    <T> BeanProvider<T> getBeanProvider(Class<T> beanType);
    
    /**
     * Get bean provider for the given type with qualifier
     * @param beanType The bean type
     * @param qualifier The qualifier
     * @return BeanProvider instance
     */
    <T> BeanProvider<T> getBeanProvider(Class<T> beanType, Qualifier<T> qualifier);
}

BeanDefinitionRegistry

Registry interface providing metadata and introspection capabilities for bean definitions.

/**
 * Registry for bean definition metadata and introspection
 */
public interface BeanDefinitionRegistry {
    /**
     * Check if a bean of the given type exists
     * @param beanType The bean type
     * @return true if bean exists
     */
    <T> boolean containsBean(Class<T> beanType);
    
    /**
     * Check if a bean exists with qualifier
     * @param beanType The bean type
     * @param qualifier The qualifier
     * @return true if bean exists
     */
    <T> boolean containsBean(Class<T> beanType, Qualifier<T> qualifier);
    
    /**
     * Find bean definition for the given type
     * @param beanType The bean type
     * @return Optional bean definition
     */
    <T> Optional<BeanDefinition<T>> findBeanDefinition(Class<T> beanType);
    
    /**
     * Find bean definition with qualifier
     * @param beanType The bean type
     * @param qualifier The qualifier
     * @return Optional bean definition
     */
    <T> Optional<BeanDefinition<T>> findBeanDefinition(Class<T> beanType, Qualifier<T> qualifier);
    
    /**
     * Get all bean definitions for the given type
     * @param beanType The bean type
     * @return Collection of bean definitions
     */
    <T> Collection<BeanDefinition<T>> getBeanDefinitions(Class<T> beanType);
    
    /**
     * Get single bean definition for the given type
     * @param beanType The bean type
     * @return Bean definition
     * @throws NoSuchBeanException if not found
     * @throws NonUniqueBeanException if multiple found
     */
    <T> BeanDefinition<T> getBeanDefinition(Class<T> beanType);
}

Provider Injection Patterns

Optional Dependencies

@Singleton
public class OptionalFeatureService {
    
    private final BeanProvider<CacheService> cacheProvider;
    private final BeanProvider<MetricsService> metricsProvider;
    
    @Inject
    public OptionalFeatureService(
        BeanProvider<CacheService> cacheProvider,
        BeanProvider<MetricsService> metricsProvider
    ) {
        this.cacheProvider = cacheProvider;
        this.metricsProvider = metricsProvider;
    }
    
    public String processRequest(String request) {
        String result = performCoreLogic(request);
        
        // Optional caching
        if (cacheProvider.isPresent()) {
            cacheProvider.get().cache(request, result);
        }
        
        // Optional metrics
        if (metricsProvider.isPresent()) {
            metricsProvider.get().recordRequest();
        }
        
        return result;
    }
}

Collection-based Processing

@Singleton
public class PluginManager {
    
    private final BeanProvider<Plugin> plugins;
    
    @Inject
    public PluginManager(BeanProvider<Plugin> plugins) {
        this.plugins = plugins;
    }
    
    public void initializePlugins() {
        plugins.stream()
            .sorted(Comparator.comparing(Plugin::getPriority))
            .forEach(Plugin::initialize);
    }
    
    public void processWithPlugins(Event event) {
        plugins.iterator().forEachRemaining(plugin -> 
            plugin.process(event)
        );
    }
}

Lazy Initialization

@Singleton
public class ExpensiveResourceManager {
    
    private final BeanProvider<DatabaseConnection> dbProvider;
    private final BeanProvider<FileSystem> fsProvider;
    
    @Inject
    public ExpensiveResourceManager(
        BeanProvider<DatabaseConnection> dbProvider,
        BeanProvider<FileSystem> fsProvider
    ) {
        this.dbProvider = dbProvider;
        this.fsProvider = fsProvider;
    }
    
    public void performDatabaseOperation() {
        // Database connection only created when needed
        DatabaseConnection db = dbProvider.get();
        db.execute("SELECT * FROM users");
    }
    
    public void performFileOperation() {
        // File system only initialized when needed
        FileSystem fs = fsProvider.get();
        fs.readFile("config.properties");
    }
}

Types

Provider-related Types

public interface Qualifier<T> {
    <BT extends BeanType<T>> Stream<BT> reduce(Class<T> beanType, Stream<BT> candidates);
    boolean equals(Object o);
    int hashCode();
}

public interface BeanResolutionContext {
    BeanContext getContext();
    BeanDefinition<?> getRootDefinition();
    Path getPath();
    BeanResolutionContext copy();
}

public interface BeanCreationContext<T> extends BeanResolutionContext {
    BeanDefinition<T> definition();
    CreatedBean<T> create() throws BeanCreationException;
}

Install with Tessl CLI

npx tessl i tessl/maven-io-micronaut--micronaut-inject

docs

annotations.md

application-context.md

bean-definition.md

bean-factory.md

bean-processing.md

bean-providers.md

environment-config.md

events.md

exceptions.md

index.md

scoping.md

tile.json