Clarify @Bean return type recommendation in case of multiple interfaces
Issue: SPR-15973
This commit is contained in:
@@ -170,8 +170,7 @@ as the local file system, from the Java `CLASSPATH`, and so on.
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
ApplicationContext context =
|
||||
new ClassPathXmlApplicationContext(new String[] {"services.xml", "daos.xml"});
|
||||
ApplicationContext context = new ClassPathXmlApplicationContext("services.xml", "daos.xml");
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
@@ -715,7 +714,6 @@ factory method itself with the `factory-method` attribute.
|
||||
public class DefaultServiceLocator {
|
||||
|
||||
private static ClientService clientService = new ClientServiceImpl();
|
||||
private DefaultServiceLocator() {}
|
||||
|
||||
public ClientService createClientServiceInstance() {
|
||||
return clientService;
|
||||
@@ -747,9 +745,8 @@ One factory class can also hold more than one factory method as shown here:
|
||||
public class DefaultServiceLocator {
|
||||
|
||||
private static ClientService clientService = new ClientServiceImpl();
|
||||
private static AccountService accountService = new AccountServiceImpl();
|
||||
|
||||
private DefaultServiceLocator() {}
|
||||
private static AccountService accountService = new AccountServiceImpl();
|
||||
|
||||
public ClientService createClientServiceInstance() {
|
||||
return clientService;
|
||||
@@ -758,7 +755,6 @@ One factory class can also hold more than one factory method as shown here:
|
||||
public AccountService createAccountServiceInstance() {
|
||||
return accountService;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -836,7 +832,6 @@ has no dependencies on container specific interfaces, base classes or annotation
|
||||
}
|
||||
|
||||
// business logic that actually uses the injected MovieFinder is omitted...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -859,7 +854,6 @@ being instantiated. Consider the following class:
|
||||
public Foo(Bar bar, Baz baz) {
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -905,7 +899,6 @@ by type without help. Consider the following class:
|
||||
this.years = years;
|
||||
this.ultimateAnswer = ultimateAnswer;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -978,7 +971,6 @@ then have to look as follows:
|
||||
this.years = years;
|
||||
this.ultimateAnswer = ultimateAnswer;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
--
|
||||
@@ -1009,7 +1001,6 @@ on container specific interfaces, base classes or annotations.
|
||||
}
|
||||
|
||||
// business logic that actually uses the injected MovieFinder is omitted...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -1155,7 +1146,9 @@ part of a Spring XML configuration file specifies some bean definitions:
|
||||
public class ExampleBean {
|
||||
|
||||
private AnotherBean beanOne;
|
||||
|
||||
private YetAnotherBean beanTwo;
|
||||
|
||||
private int i;
|
||||
|
||||
public void setBeanOne(AnotherBean beanOne) {
|
||||
@@ -1169,7 +1162,6 @@ part of a Spring XML configuration file specifies some bean definitions:
|
||||
public void setIntegerProperty(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -1201,7 +1193,9 @@ in the XML file. The following example uses constructor-based DI:
|
||||
public class ExampleBean {
|
||||
|
||||
private AnotherBean beanOne;
|
||||
|
||||
private YetAnotherBean beanTwo;
|
||||
|
||||
private int i;
|
||||
|
||||
public ExampleBean(
|
||||
@@ -1210,7 +1204,6 @@ in the XML file. The following example uses constructor-based DI:
|
||||
this.beanTwo = yetAnotherBean;
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -1253,7 +1246,6 @@ told to call a `static` factory method to return an instance of the object:
|
||||
// some other operations...
|
||||
return eb;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -2322,7 +2314,6 @@ the following class, with a method computeValue, which we want to override:
|
||||
}
|
||||
|
||||
// some other methods...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3127,7 +3118,6 @@ see <<beans-java-lifecycle-callbacks>>. For example, the following:
|
||||
public void init() {
|
||||
// do some initialization work
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3147,7 +3137,6 @@ see <<beans-java-lifecycle-callbacks>>. For example, the following:
|
||||
public void afterPropertiesSet() {
|
||||
// do some initialization work
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3189,7 +3178,6 @@ With Java config, you use the `destroyMethod` attribute of `@Bean`, see
|
||||
public void cleanup() {
|
||||
// do some destruction work (like releasing pooled connections)
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3209,7 +3197,6 @@ is exactly the same as:
|
||||
public void destroy() {
|
||||
// do some destruction work (like releasing pooled connections)
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3266,7 +3253,6 @@ following example.
|
||||
throw new IllegalStateException("The [blogDao] property must be set.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3356,7 +3342,6 @@ lifecycle requirements (e.g. starts and stops some background process):
|
||||
void stop();
|
||||
|
||||
boolean isRunning();
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3373,7 +3358,6 @@ defined within that context. It does this by delegating to a `LifecycleProcessor
|
||||
void onRefresh();
|
||||
|
||||
void onClose();
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3407,7 +3391,6 @@ another option, namely the `getPhase()` method as defined on its super-interface
|
||||
public interface Phased {
|
||||
|
||||
int getPhase();
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3419,7 +3402,6 @@ another option, namely the `getPhase()` method as defined on its super-interface
|
||||
boolean isAutoStartup();
|
||||
|
||||
void stop(Runnable callback);
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3496,9 +3478,7 @@ declared on the `ConfigurableApplicationContext` interface:
|
||||
public final class Boot {
|
||||
|
||||
public static void main(final String[] args) throws Exception {
|
||||
|
||||
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext(
|
||||
new String []{"beans.xml"});
|
||||
ConfigurableApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml");
|
||||
|
||||
// add a shutdown hook for the above context...
|
||||
ctx.registerShutdownHook();
|
||||
@@ -3506,7 +3486,6 @@ declared on the `ConfigurableApplicationContext` interface:
|
||||
// app runs here...
|
||||
|
||||
// main method exits, hook is called prior to the app shutting down...
|
||||
|
||||
}
|
||||
}
|
||||
----
|
||||
@@ -3526,7 +3505,6 @@ with a reference to that `ApplicationContext`.
|
||||
public interface ApplicationContextAware {
|
||||
|
||||
void setApplicationContext(ApplicationContext applicationContext) throws BeansException;
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3562,7 +3540,6 @@ a reference to the name defined in its associated object definition.
|
||||
public interface BeanNameAware {
|
||||
|
||||
void setBeanName(String name) throws BeansException;
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -3876,17 +3853,14 @@ Find below the custom `BeanPostProcessor` implementation class definition:
|
||||
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
// simply return the instantiated bean as-is
|
||||
public Object postProcessBeforeInitialization(Object bean,
|
||||
String beanName) throws BeansException {
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName) {
|
||||
return bean; // we could potentially return any object reference here...
|
||||
}
|
||||
|
||||
public Object postProcessAfterInitialization(Object bean,
|
||||
String beanName) throws BeansException {
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) {
|
||||
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
|
||||
return bean;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4326,7 +4300,6 @@ example:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4364,15 +4337,15 @@ You can apply the `@Autowired` annotation to constructors:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
[NOTE]
|
||||
====
|
||||
As of Spring Framework 4.3, the `@Autowired` constructor is no longer necessary if the
|
||||
target bean only defines one constructor. If several constructors are available, at
|
||||
least one must be annotated to teach the container which one it has to use.
|
||||
As of Spring Framework 4.3, an `@Autowired` annotation on such a constructor is
|
||||
no longer necessary if the target bean only defines one constructor to begin with.
|
||||
However, if several constructors are available, at least one must be annotated to
|
||||
teach the container which one to use.
|
||||
====
|
||||
|
||||
As expected, you can also apply the `@Autowired` annotation to "traditional" setter
|
||||
@@ -4391,7 +4364,6 @@ methods:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4415,7 +4387,6 @@ arguments:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4437,10 +4408,23 @@ You can apply `@Autowired` to fields as well and even mix it with constructors:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
[TIP]
|
||||
====
|
||||
Make sure that your target components (e.g. `MovieCatalog`, `CustomerPreferenceDao`)
|
||||
are consistently declared by the type that you are using for your `@Autowired`-annotated
|
||||
injection points. Otherwise injection may fail due to no type match found at runtime.
|
||||
|
||||
For XML-defined beans or component classes found through a classpath scan, the container
|
||||
usually knows the concrete type upfront. However, for `@Bean` factory methods, you need
|
||||
to make sure that the declared return type is sufficiently expressive. For components
|
||||
implementing several interfaces or for components potentially referred to by their
|
||||
implementation type, consider declaring the most specific return type on your factory
|
||||
method (at least as specific as required by the injection points referring to your bean).
|
||||
====
|
||||
|
||||
It is also possible to provide __all__ beans of a particular type from the
|
||||
`ApplicationContext` by adding the annotation to a field or method that expects an array
|
||||
of that type:
|
||||
@@ -4454,7 +4438,6 @@ of that type:
|
||||
private MovieCatalog[] movieCatalogs;
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4473,7 +4456,6 @@ The same applies for typed collections:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4501,7 +4483,6 @@ corresponding bean names:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4516,13 +4497,12 @@ indicating __required__ dependencies. This behavior can be changed as demonstrat
|
||||
|
||||
private MovieFinder movieFinder;
|
||||
|
||||
@Autowired(required=false)
|
||||
@Autowired(required = false)
|
||||
public void setMovieFinder(MovieFinder movieFinder) {
|
||||
this.movieFinder = movieFinder;
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4558,7 +4538,6 @@ automatically resolved, with no special setup necessary.
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4598,7 +4577,6 @@ _primary_ `MovieCatalog`.
|
||||
public MovieCatalog secondMovieCatalog() { ... }
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4614,7 +4592,6 @@ With such configuration, the following `MovieRecommender` will be autowired with
|
||||
private MovieCatalog movieCatalog;
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4668,7 +4645,6 @@ chosen for each argument. In the simplest case, this can be a plain descriptive
|
||||
private MovieCatalog movieCatalog;
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4692,7 +4668,6 @@ method parameters:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4809,6 +4784,7 @@ Then you can provide the custom qualifier on autowired fields and parameters:
|
||||
@Autowired
|
||||
**@Genre("Action")**
|
||||
private MovieCatalog actionCatalog;
|
||||
|
||||
private MovieCatalog comedyCatalog;
|
||||
|
||||
@Autowired
|
||||
@@ -4817,7 +4793,6 @@ Then you can provide the custom qualifier on autowired fields and parameters:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4889,7 +4864,6 @@ Then add the annotation to the field or property to be autowired:
|
||||
private MovieCatalog offlineCatalog;
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -4960,7 +4934,6 @@ for both attributes: `genre` and `format`.
|
||||
private MovieCatalog comedyBluRayCatalog;
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -5040,7 +5013,6 @@ configuration:
|
||||
public IntegerStore integerStore() {
|
||||
return new IntegerStore();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -5129,7 +5101,6 @@ demonstrated in this example:
|
||||
public void setMovieFinder(MovieFinder movieFinder) {
|
||||
this.movieFinder = movieFinder;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -5149,7 +5120,6 @@ name "movieFinder" injected into its setter method:
|
||||
public void setMovieFinder(MovieFinder movieFinder) {
|
||||
this.movieFinder = movieFinder;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -5189,7 +5159,6 @@ dependency type `ApplicationContext`.
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -5223,7 +5192,6 @@ pre-populated upon initialization and cleared upon destruction.
|
||||
public void clearMovieCache() {
|
||||
// clears the movie cache upon destruction...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -5381,7 +5349,6 @@ are eligible for such autodetection:
|
||||
public SimpleMovieLister(MovieFinder movieFinder) {
|
||||
this.movieFinder = movieFinder;
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -5565,7 +5532,6 @@ annotated classes. Here is a simple example:
|
||||
public void doWork() {
|
||||
// Component method implementation omitted
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -5621,7 +5587,6 @@ support for autowiring of `@Bean` methods:
|
||||
public TestBean requestScopedInstance() {
|
||||
return new TestBean("requestScopedInstance", 3);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6013,7 +5978,7 @@ used as follows:
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
@Named("movieListener") // @ManagedBean("movieListener") could be used as well
|
||||
@Named("movieListener") // @ManagedBean("movieListener") could be used as well
|
||||
public class SimpleMovieLister {
|
||||
|
||||
private MovieFinder movieFinder;
|
||||
@@ -6160,7 +6125,6 @@ The simplest possible `@Configuration` class would read as follows:
|
||||
public MyService myService() {
|
||||
return new MyServiceImpl();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6420,10 +6384,9 @@ the method name. The following is a simple example of a `@Bean` method declarati
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public TransferService transferService() {
|
||||
public TransferServiceImpl transferService() {
|
||||
return new TransferServiceImpl();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6446,6 +6409,39 @@ Both declarations make a bean named `transferService` available in the
|
||||
transferService -> com.acme.TransferServiceImpl
|
||||
----
|
||||
|
||||
You may also declare your `@Bean` method with an interface (or base class)
|
||||
return type:
|
||||
|
||||
[source,java,indent=0]
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public TransferService transferService() {
|
||||
return new TransferServiceImpl();
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
However, this limits the visibility for advance type prediction to the specified
|
||||
interface type (`TransferService`) then, with the full type (`TransferServiceImpl`)
|
||||
only known to the container 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 will only resolve once the "transferService" bean has been instantiated).
|
||||
|
||||
[TIP]
|
||||
====
|
||||
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
|
||||
implementing 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 referring to your bean).
|
||||
====
|
||||
|
||||
|
||||
[[beans-java-dependencies]]
|
||||
==== Bean dependencies
|
||||
@@ -6465,7 +6461,6 @@ parameter:
|
||||
public TransferService transferService(AccountRepository accountRepository) {
|
||||
return new TransferServiceImpl(accountRepository);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6498,12 +6493,14 @@ on the `bean` element:
|
||||
[subs="verbatim,quotes"]
|
||||
----
|
||||
public class Foo {
|
||||
|
||||
public void init() {
|
||||
// initialization logic
|
||||
}
|
||||
}
|
||||
|
||||
public class Bar {
|
||||
|
||||
public void cleanup() {
|
||||
// destruction logic
|
||||
}
|
||||
@@ -6521,7 +6518,6 @@ on the `bean` element:
|
||||
public Bar bar() {
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6562,6 +6558,7 @@ method directly during construction:
|
||||
----
|
||||
@Configuration
|
||||
public class AppConfig {
|
||||
|
||||
@Bean
|
||||
public Foo foo() {
|
||||
Foo foo = new Foo();
|
||||
@@ -6570,7 +6567,6 @@ method directly during construction:
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6604,7 +6600,6 @@ The default scope is `singleton`, but you can override this with the `@Scope` an
|
||||
public Encryptor encryptor() {
|
||||
// ...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6657,7 +6652,6 @@ resulting bean. This functionality can be overridden, however, with the `name` a
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6679,7 +6673,6 @@ annotation accepts a String array for this purpose.
|
||||
public DataSource dataSource() {
|
||||
// instantiate, configure and return DataSource bean...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6705,7 +6698,6 @@ annotation can be used:
|
||||
public Foo foo() {
|
||||
return new Foo();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6740,7 +6732,6 @@ as having one bean method call another:
|
||||
public Bar bar() {
|
||||
return new Bar();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6837,7 +6828,6 @@ The following example shows a `@Bean` annotated method being called twice:
|
||||
public ClientDao clientDao() {
|
||||
return new ClientDaoImpl();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6905,7 +6895,6 @@ another configuration class:
|
||||
public B b() {
|
||||
return new B();
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -6961,7 +6950,6 @@ classes, each depending on beans declared in the others:
|
||||
public TransferService transferService(AccountRepository accountRepository) {
|
||||
return new TransferServiceImpl(accountRepository);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -6971,7 +6959,6 @@ classes, each depending on beans declared in the others:
|
||||
public AccountRepository accountRepository(DataSource dataSource) {
|
||||
return new JdbcAccountRepository(dataSource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -6982,7 +6969,6 @@ classes, each depending on beans declared in the others:
|
||||
public DataSource dataSource() {
|
||||
// return new DataSource
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -7023,7 +7009,6 @@ work on the configuration class itself since it is being created as a bean insta
|
||||
public TransferService transferService() {
|
||||
return new TransferServiceImpl(accountRepository);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -7040,7 +7025,6 @@ work on the configuration class itself since it is being created as a bean insta
|
||||
public AccountRepository accountRepository() {
|
||||
return new JdbcAccountRepository(dataSource);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -7051,7 +7035,6 @@ work on the configuration class itself since it is being created as a bean insta
|
||||
public DataSource dataSource() {
|
||||
// return new DataSource
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
@@ -7100,7 +7083,6 @@ configuration classes themselves:
|
||||
// navigate 'through' the config class to the @Bean method!
|
||||
return new TransferServiceImpl(repositoryConfig.accountRepository());
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -7129,7 +7111,6 @@ abstract class-based `@Configuration` classes. Consider the following:
|
||||
|
||||
@Bean
|
||||
AccountRepository accountRepository();
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@@ -7139,11 +7120,10 @@ abstract class-based `@Configuration` classes. Consider the following:
|
||||
public AccountRepository accountRepository() {
|
||||
return new JdbcAccountRepository(...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
|
||||
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
|
||||
public class SystemTestConfig {
|
||||
|
||||
@Bean
|
||||
@@ -7259,7 +7239,6 @@ properly.
|
||||
public TransferService transferService() {
|
||||
return new TransferService(accountRepository());
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -7370,7 +7349,6 @@ bare minimum.
|
||||
public DataSource dataSource() {
|
||||
return new DriverManagerDataSource(url, username, password);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -7854,6 +7832,7 @@ a call to `testBean.getName()` will return "myTestBean".
|
||||
@Configuration
|
||||
**@PropertySource("classpath:/com/myco/app.properties")**
|
||||
public class AppConfig {
|
||||
|
||||
@Autowired
|
||||
Environment env;
|
||||
|
||||
@@ -7876,6 +7855,7 @@ environment. For example:
|
||||
@Configuration
|
||||
@PropertySource("classpath:/com/${my.placeholder:default/path}/app.properties")
|
||||
public class AppConfig {
|
||||
|
||||
@Autowired
|
||||
Environment env;
|
||||
|
||||
@@ -7935,7 +7915,6 @@ To enable load-time weaving add the `@EnableLoadTimeWeaving` to one of your
|
||||
@Configuration
|
||||
@EnableLoadTimeWeaving
|
||||
public class AppConfig {
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -8125,7 +8104,6 @@ converted into Strings and inserted into placeholders in the lookup message.
|
||||
new Object [] {"userDao"}, "Required", null);
|
||||
System.out.println(message);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -8271,7 +8249,6 @@ simple class that extends Spring's `ApplicationEvent` base class:
|
||||
}
|
||||
|
||||
// accessor and other methods...
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -8304,7 +8281,6 @@ example demonstrates such a class:
|
||||
}
|
||||
// send email...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -8332,7 +8308,6 @@ demonstrates such a class:
|
||||
public void onApplicationEvent(BlackListEvent event) {
|
||||
// notify appropriate parties via notificationAddress...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
@@ -8407,7 +8382,6 @@ follows:
|
||||
public void processBlackListEvent(BlackListEvent event) {
|
||||
// notify appropriate parties via notificationAddress...
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
Reference in New Issue
Block a user