Spring java config create bean

Using the @Bean Annotation

@Bean is a method-level annotation and a direct analog of the XML element. The annotation supports some of the attributes offered by , such as:

You can use the @Bean annotation in a @Configuration -annotated or in a @Component -annotated class.

Declaring a Bean

To declare a bean, you can annotate a method with the @Bean annotation. You use this method to register a bean definition within an ApplicationContext of the type specified as the method’s return value. By default, the bean name is the same as the method name. The following example shows a @Bean method declaration:

@Configuration public class AppConfig < @Bean public TransferServiceImpl transferService() < return new TransferServiceImpl(); >>
@Configuration class AppConfig

The preceding configuration is exactly equivalent to the following Spring XML:

Both declarations make a bean named transferService available in the ApplicationContext , bound to an object instance of type TransferServiceImpl , as the following text image shows:

transferService -> com.acme.TransferServiceImpl

You can also use default methods to define beans. This allows composition of bean configurations by implementing interfaces with bean definitions on default methods.

public interface BaseConfig < @Bean default TransferServiceImpl transferService() < return new TransferServiceImpl(); >> @Configuration public class AppConfig implements BaseConfig

You can also declare your @Bean method with an interface (or base class) return type, as the following example shows:

@Configuration public class AppConfig < @Bean public TransferService transferService() < return new TransferServiceImpl(); >>
@Configuration class AppConfig < @Bean fun transferService(): TransferService < return TransferServiceImpl() >>

However, this limits the visibility for advance type prediction to the specified interface type ( TransferService ). Then, with the full type ( TransferServiceImpl ) known to the container only once the affected singleton bean has been instantiated. Non-lazy singleton beans get instantiated according to their declaration order, so you may see different type matching results depending on when another component tries to match by a non-declared type (such as @Autowired TransferServiceImpl , which resolves only once the transferService bean has been instantiated).

If you consistently refer to your types by a declared service interface, your @Bean return types may safely join that design decision. However, for components that implement several interfaces or for components potentially referred to by their implementation type, it is safer to declare the most specific return type possible (at least as specific as required by the injection points that refer to your bean).

Bean Dependencies

A @Bean -annotated method can have an arbitrary number of parameters that describe the dependencies required to build that bean. For instance, if our TransferService requires an AccountRepository , we can materialize that dependency with a method parameter, as the following example shows:

@Configuration public class AppConfig < @Bean public TransferService transferService(AccountRepository accountRepository) < return new TransferServiceImpl(accountRepository); >>
@Configuration class AppConfig < @Bean fun transferService(accountRepository: AccountRepository): TransferService < return TransferServiceImpl(accountRepository) >>

The resolution mechanism is pretty much identical to constructor-based dependency injection. See the relevant section for more details.

Читайте также:  A simple HTML document

Receiving Lifecycle Callbacks

Any classes defined with the @Bean annotation support the regular lifecycle callbacks and can use the @PostConstruct and @PreDestroy annotations from JSR-250. See JSR-250 annotations for further details.

The regular Spring lifecycle callbacks are fully supported as well. If a bean implements InitializingBean , DisposableBean , or Lifecycle , their respective methods are called by the container.

The standard set of *Aware interfaces (such as BeanFactoryAware, BeanNameAware, MessageSourceAware, ApplicationContextAware, and so on) are also fully supported.

The @Bean annotation supports specifying arbitrary initialization and destruction callback methods, much like Spring XML’s init-method and destroy-method attributes on the bean element, as the following example shows:

public class BeanOne < public void init() < // initialization logic >> public class BeanTwo < public void cleanup() < // destruction logic >> @Configuration public class AppConfig < @Bean(initMethod = "init") public BeanOne beanOne() < return new BeanOne(); >@Bean(destroyMethod = "cleanup") public BeanTwo beanTwo() < return new BeanTwo(); >>
class BeanOne < fun init() < // initialization logic >> class BeanTwo < fun cleanup() < // destruction logic >> @Configuration class AppConfig

By default, beans defined with Java configuration that have a public close or shutdown method are automatically enlisted with a destruction callback. If you have a public close or shutdown method and you do not wish for it to be called when the container shuts down, you can add @Bean(destroyMethod = «») to your bean definition to disable the default (inferred) mode.

You may want to do that by default for a resource that you acquire with JNDI, as its lifecycle is managed outside the application. In particular, make sure to always do it for a DataSource , as it is known to be problematic on Jakarta EE application servers.

The following example shows how to prevent an automatic destruction callback for a DataSource :

@Bean(destroyMethod = "") public DataSource dataSource() throws NamingException
@Bean(destroyMethod = "") fun dataSource(): DataSource

Also, with @Bean methods, you typically use programmatic JNDI lookups, either by using Spring’s JndiTemplate or JndiLocatorDelegate helpers or straight JNDI InitialContext usage but not the JndiObjectFactoryBean variant (which would force you to declare the return type as the FactoryBean type instead of the actual target type, making it harder to use for cross-reference calls in other @Bean methods that intend to refer to the provided resource here).

In the case of BeanOne from the example above the preceding note, it would be equally valid to call the init() method directly during construction, as the following example shows:

@Configuration public class AppConfig < @Bean public BeanOne beanOne() < BeanOne beanOne = new BeanOne(); beanOne.init(); return beanOne; >// . >
@Configuration class AppConfig < @Bean fun beanOne() = BeanOne().apply < init() >// . >
When you work directly in Java, you can do anything you like with your objects and do not always need to rely on the container lifecycle.

Specifying Bean Scope

Spring includes the @Scope annotation so that you can specify the scope of a bean.

Using the @Scope Annotation

You can specify that your beans defined with the @Bean annotation should have a specific scope. You can use any of the standard scopes specified in the Bean Scopes section.

Читайте также:  Java add certificate to trusted store

The default scope is singleton , but you can override this with the @Scope annotation, as the following example shows:

@Configuration public class MyConfiguration < @Bean @Scope("prototype") public Encryptor encryptor() < // . >>
@Configuration class MyConfiguration < @Bean @Scope("prototype") fun encryptor(): Encryptor < // . >>

@Scope and scoped-proxy

Spring offers a convenient way of working with scoped dependencies through scoped proxies. The easiest way to create such a proxy when using the XML configuration is the element. Configuring your beans in Java with a @Scope annotation offers equivalent support with the proxyMode attribute. The default is ScopedProxyMode.DEFAULT , which typically indicates that no scoped proxy should be created unless a different default has been configured at the component-scan instruction level. You can specify ScopedProxyMode.TARGET_CLASS , ScopedProxyMode.INTERFACES or ScopedProxyMode.NO .

If you port the scoped proxy example from the XML reference documentation (see scoped proxies) to our @Bean using Java, it resembles the following:

// an HTTP Session-scoped bean exposed as a proxy @Bean @SessionScope public UserPreferences userPreferences() < return new UserPreferences(); >@Bean public Service userService() < UserService service = new SimpleUserService(); // a reference to the proxied userPreferences bean service.setUserPreferences(userPreferences()); return service; >
// an HTTP Session-scoped bean exposed as a proxy @Bean @SessionScope fun userPreferences() = UserPreferences() @Bean fun userService(): Service < return SimpleUserService().apply < // a reference to the proxied userPreferences bean setUserPreferences(userPreferences()) >>

Customizing Bean Naming

By default, configuration classes use a @Bean method’s name as the name of the resulting bean. This functionality can be overridden, however, with the name attribute, as the following example shows:

@Configuration public class AppConfig < @Bean("myThing") public Thing thing() < return new Thing(); >>
@Configuration class AppConfig

Bean Aliasing

As discussed in Naming Beans, it is sometimes desirable to give a single bean multiple names, otherwise known as bean aliasing. The name attribute of the @Bean annotation accepts a String array for this purpose. The following example shows how to set a number of aliases for a bean:

@Configuration public class AppConfig < @Bean() public DataSource dataSource() < // instantiate, configure and return DataSource bean. >>
@Configuration class AppConfig < @Bean("dataSource", "subsystemA-dataSource", "subsystemB-dataSource") fun dataSource(): DataSource < // instantiate, configure and return DataSource bean. >>

Bean Description

Sometimes, it is helpful to provide a more detailed textual description of a bean. This can be particularly useful when beans are exposed (perhaps through JMX) for monitoring purposes.

To add a description to a @Bean , you can use the @Description annotation, as the following example shows:

@Configuration public class AppConfig < @Bean @Description("Provides a basic example of a bean") public Thing thing() < return new Thing(); >>
@Configuration class AppConfig

Apache®, Apache Tomcat®, Apache Kafka®, Apache Cassandra™, and Apache Geode™ are trademarks or registered trademarks of the Apache Software Foundation in the United States and/or other countries. Java™, Java™ SE, Java™ EE, and OpenJDK™ are trademarks of Oracle and/or its affiliates. Kubernetes® is a registered trademark of the Linux Foundation in the United States and other countries. Linux® is the registered trademark of Linus Torvalds in the United States and other countries. Windows® and Microsoft® Azure are registered trademarks of Microsoft Corporation. “AWS” and “Amazon Web Services” are trademarks or registered trademarks of Amazon.com Inc. or its affiliates. All other trademarks and copyrights are property of their respective owners and are only mentioned for informative purposes. Other names may be trademarks of their respective owners.

Читайте также:  Typescript debugging node js

Источник

Basic Concepts: @Bean and @Configuration

The central artifacts in Spring’s Java configuration support are @Configuration -annotated classes and @Bean -annotated methods.

The @Bean annotation is used to indicate that a method instantiates, configures, and initializes a new object to be managed by the Spring IoC container. For those familiar with Spring’s XML configuration, the @Bean annotation plays the same role as the element. You can use @Bean -annotated methods with any Spring @Component . However, they are most often used with @Configuration beans.

Annotating a class with @Configuration indicates that its primary purpose is as a source of bean definitions. Furthermore, @Configuration classes let inter-bean dependencies be defined by calling other @Bean methods in the same class. The simplest possible @Configuration class reads as follows:

@Configuration public class AppConfig < @Bean public MyServiceImpl myService() < return new MyServiceImpl(); >>
@Configuration class AppConfig < @Bean fun myService(): MyServiceImpl < return MyServiceImpl() >>

The preceding AppConfig class is equivalent to the following Spring XML:

When @Bean methods are declared within classes that are not annotated with @Configuration , they are referred to as being processed in a “lite” mode. Bean methods declared in a @Component or even in a plain old class are considered to be “lite”, with a different primary purpose of the containing class and a @Bean method being a sort of bonus there. For example, service components may expose management views to the container through an additional @Bean method on each applicable component class. In such scenarios, @Bean methods are a general-purpose factory method mechanism.

Unlike full @Configuration , lite @Bean methods cannot declare inter-bean dependencies. Instead, they operate on their containing component’s internal state and, optionally, on arguments that they may declare. Such a @Bean method should therefore not invoke other @Bean methods. Each such method is literally only a factory method for a particular bean reference, without any special runtime semantics. The positive side-effect here is that no CGLIB subclassing has to be applied at runtime, so there are no limitations in terms of class design (that is, the containing class may be final and so forth).

In common scenarios, @Bean methods are to be declared within @Configuration classes, ensuring that “full” mode is always used and that cross-method references therefore get redirected to the container’s lifecycle management. This prevents the same @Bean method from accidentally being invoked through a regular Java call, which helps to reduce subtle bugs that can be hard to track down when operating in “lite” mode.

The @Bean and @Configuration annotations are discussed in depth in the following sections. First, however, we cover the various ways of creating a spring container by using Java-based configuration.

Источник

Оцените статью