1.12 based on Java container configuration
This section covers how to use annotations to configure spring containers in your Java code. It includes the following topics:
- Basic concepts:
@Bean
and@Configuration
- use
AnnotationConfigApplicationContext
Instantiating spring container - use
@Bean
annotation - use
@Configuration
annotation - Configuration combination based on Java
- Bean definition profile
PropertySource
abstract- use
@PropertySource
- Place holder resolution
1.12.1 basic concepts: @ bean and @ configuration
The main components in spring’s new Java configuration support are@Configuration
Class and annotation@Bean
The method of annotation.
@Bean
Annotations use to represent a method instance, configure, and instantiate new objects managed by the spring IOC container. These are similar to spring’s < beans / > XML configuration,@Bean
Annotations play the same role as the < bean / > element. You can use it@Bean
Annotation methods replace any spring@Component
Component. However, they are most often used with @ configuration. Annotation @Configuration
The annotation indicates that its main purpose is the source of the bean definition. In addition,@Configuration
Class allows you to call other@Bean
To define the relationship between bean methods. The simplest@Configuration
example:
@Configuration
public class AppConfig {
@Bean
public MyService myService() {
return new MyServiceImpl();
}
}
The previous AppConfig class is equivalent to the following spring < beans / > XML definition:
<beans>
<bean id="myService" class="com.acme.services.MyServiceImpl"/>
</beans>
complete
@Configuration
And “streamlining”@Bean
pattern?When
@Bean
When methods are declared in classes, these classes are not annotated@Configuration
They are referred to as “streamlined” processing. stay@Component
Or a bean method declared in a simple old class is considered a “compact version” in which the main purpose of the class is different, and@Bean
The method has some advantages there. For example, the service component exposes the management view to the container by adding an additional @ bean method to each applicable component class. In this scenario,@Bean
Method is a general factory method mechanism.It’s not like the whole thing
@Configuration
, simplify@Bean
Method cannot declare dependencies between beans. Instead, they operate on the internal state of the components they contain and (optional) parameters that may be declared. Therefore, this kind of@Bean
Method should not call other@Bean
method. Each of these methods is actually a factory method referenced by a particular bean, without any special runtime semantics. The positive side effect here is that there is no need to apply cglib subclasses at run time, so there are no restrictions on class design (that is, the containing class may be final).In common scenarios,
@Bean
Methods are declared in the @ configuration class to ensure that full mode is always used, < U > so cross method references are redirected to lifecycle management of the container < / u >. This prevents accidental calls to the same@Bean
Method, which helps to reduce subtle errors that are difficult to trace when operating in Lite mode. Note: in@Configuration
Call others in class@Bean
Methods are directed to lifecycle management of the container.
@Bean
and@Configuration
This is discussed in depth in the following sections. First, we’ll cover various ways to create spring containers based on Java annotations.
1.12.2 by usingAnnotationConfigApplicationContext
Initialize spring container
The following sections introduce spring’sAnnotationConfigApplicationContext
。 This generic ApplicationContext implementation can not only receive@Configuration
Class as input, it can also receive normal@Component
Classes and classes annotated with jsr-330 metadata
When@Configuration
Class is provided as input,@Configuration
The class itself is registered as a bean definition and all are registered in the class@Bean
Declared methods are also registered in the container as bean definitions.
When provided@Component
And jsr-330 classes, they are registered as bean definitions and assume Di metadata (such as@Autowired
or@Inject
)Use in these classes.
Simple construction
And instantiationClassPathXmlApplicationContext
The spring XML file is used as input in almost the same wayAnnotationConfigApplicationContext
You can change@Configuration
Class is used as input. This allows spring containers to be used without XML at all, as shown in the following example:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
As mentioned earlier,AnnotationConfigApplicationContext
Not limited to use with @ configuration. whatever@Component
Or jsr-330 annotated classes are supported as input constructs, similar to the following example:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(MyServiceImpl.class, Dependency1.class, Dependency2.class);
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
The previous example assumes thatMyServiceImpl
、Dependency1
, andDependency2
Use spring dependency injection annotation, for example:@Autowired
。
through the use ofregister(Class<?>…)
Build container for programming
You can instantiate it by using a nonparametric constructorAnnotationConfigApplicationContext
And through the use ofregister()
Method configuration. When programmatically builtAnnotationConfigApplicationContext
This method is particularly useful. How to use it is shown in the following classes:
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(AppConfig.class, OtherConfig.class);
ctx.register(AdditionalConfig.class);
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
myService.doStuff();
}
adoptscan(String…)
Scan active components
Scan the active component and you can annotate your@Configuration
Class:
@Configuration
@ComponentScan(basePackages = "com.acme") //1
public class AppConfig {
...
}
- This annotation activates component scanning
Experienced spring users may be familiar with the equivalent XML declaration in spring context: namespace, similar to the following example:
<beans> <context:component-scan base-package="com.acme"/> </beans>
In the previous example,com.acm
Packets are scanned to find annotations@Component
And these classes are registered in the container as spring bean definitions.AnnotationConfigApplicationContext
exposescan(String…)
Methods provide the same function of component scanning, similar to the following example:
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.scan("com.acme");
ctx.refresh();
MyService myService = ctx.getBean(MyService.class);
}
remember
@Configuration
Class is used to@Component
Meta annotated, so they are candidates for component scanning. In the previous example, suppose AppConfig is declared in thecom.acme
Package (or anycom.acme
It will call thescan()
During this period, they were selected. stayrefresh()
After that, all of them@Bean
Methods are processed and registered as bean definitions within the container.
adoptAnnotationConfigWebApplicationContext
Support for web applications
AnnotationConfigWebApplicationContext
ProvidedAnnotationConfigApplicationContext
OfWebApplicationContext
variant. When configuring spring’sContextLoaderListener
Servlet listener, spring MVCDispatcherServlet
When you wait, you can use this implementation, belowweb.xml
Fragment to configure a typical spring MVC web application (Note:contextClass
usecontext-param
andinit-param
):
<web-app>
1.12.3 using @ bean annotation
@Bean
Is a method level annotation and a direct analogy to the XML < bean / > element. This annotation supports some properties provided through < bean / > such as init method, destroy method, autowiring
You can@Configuration
and@Component
Annotation is used on the class@Bean
Notes.
Statement bean
To declare a bean, you can annotate a method@Bean
。 You use this method in theApplicationContext
To register the bean definition of a method return value of the specified type. <u> By default, the bean name is the same method name < / u >. The following example shows one@Bean
Method statement:
@Configuration
public class AppConfig {
@Bean
public TransferServiceImpl transferService() {
return new TransferServiceImpl();
}
}
The previous configuration is exactly equivalent to the following spring XML:
<beans>
<bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>
Both statements make atransferService
The bean ofApplicationContext
And bind aTransferServiceImpl
Type, similar to the following text image display:
transferService -> com.acme.TransferServiceImpl
You can also declare your@Bean
Method is an interface (or base class) return type, similar to the following example:
@Configuration
public class AppConfig {
@Bean
public TransferService transferService() {
return new TransferServiceImpl();
}
}
However, this limits the visibility of advanced type prediction to the specified interface type(TransferService
)。 However, all types(TransferServiceImpl
)In only one container, the affected singleton bean is initialized. Non lazy load singleton beans get initialized instances according to their declaration order. When other components try to match through non declared types, you may see different type matching result dependencies (for example,@Autowired
TransferServiceImpl
, only when instantiatedtransferService
Bean).
If you always refer to your type through the declared service interface, your
@Bean
Return types can safely participate in the design decision. However, for components that implement multiple interfaces or are potentially referenced by their implementation types, it is safer to declare the most specific return type (at least as specific as the injection point that references your bean requires). Note: this means that if a component is referenced by an implementation type, the@Bean
Method, the return type is the specific implementation type.
Bean dependency
A quilt@Bean
Annotated methods can have any number of parameters that describe the dependencies needed to build the bean. For example, if ourTransferService
You need oneAccountRepository
We can implement this dependency through method parameters, such as the following example:
@Configuration
public class AppConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
The parsing mechanism is almost the same as constructor based dependency injection. See the more detailed sections.
Accept lifecycle callback
Any declared@Bean
Annotated classes support normal lifecycle callbacks and can use jsr-250’s@PostConstruct
And @ predestroy annotations. See the jsr-250 annotation for more details.
Regular spring lifecycle callbacks are fully supported. If the bean implementsInitializingBean
、DisposableBean
orLifecycle
Their respective methods are called back by the container.
Standard set*Aware
Interfaces (such as beanfactory aware, beanname aware, message source aware, applicationcontextaware, etc.) are also fully supported.
@Bean
Annotations support arbitrary initialization and destruction callback methods, which are very similar to the init method and the init method of XML < bean > element in springdestroy-method
Property, similar to the following example:
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();
}
}
By default, these beans are defined through Java configuration, and they have a common
close
orshutdown
Method is added to the destroy callback. If you have a publicclose
orshutdown
Method and do not want to be called back when the container is closed, you should add@Bean(destroyMethod="")
Go to your bean definition to disable the default(inferred
)Mode.By default, you may want to do this on resources acquired through JNDI, because their lifecycle is managed outside the application. In particular, make sure that you always do this for the data source, as this is problematic on the Java EE application server.
The following example shows how to prevent datasource from automatically destroying callbacks.
@Bean(destroyMethod="")
public DataSource dataSource() throws NamingException {
return (DataSource) jndiTemplate.lookup("MyDS");
}
In addition, for
@Bean
Method, usually using a JNDI lookup programmatically, using springJndiTemplate
orJndiLocatorDelegate
Helper, or use JNDI directlyInitialContext
Use, not useJndiObjectFactoryBean
Variant (this forces you to declare the return type asFactoryBean
Type, not the actual type. The target type, so it’s difficult to use cross reference calls in other @ bean methods that intend to reference the resources provided here.
During the construction of beanone, it is equivalent to theinit()
Method, similar to the following example:
@Configuration
public class AppConfig {
@Bean
public BeanOne beanOne() {
BeanOne beanOne = new BeanOne();
beanOne.init();
return beanOne;
}
// ...
}
When you work directly in Java, you can do anything with your objects without relying on the container lifecycle.
Specify bean scope
Spring includes@Scope
Annotation, so you can use the scope of the bean.
use@Scope
annotation
You can specify that your bean definition passes through@Bean
Annotations can also specify a scope. You can use the scope in any part of the standard bean.
The default scope issingleton
But you can override this through@Scope
Note, similar to the following example:
@Configuration
public class MyConfiguration {
@Bean
@Scope("prototype")
public Encryptor encryptor() {
// ...
}
}
@Scope
andscoped-proxy
Spring provides a convenient way to handle scope dependencies through scope proxies. When using XML configuration< aop:scoped-proxy/>
Is the easiest way to create a proxy. use@Scope
Annotations configure beans in Java, which can beproxyMode
Property provides equal support. The default is no agent(ScopedProxyMode.NO
), but you can specifyScopedProxyMode.TARGET_CLASS
orScopedProxyMode.INTERFACES
If you use Java, migrate the scope proxy example from the XML reference document (see scope proxy) to our@Bean
, which is similar to the following:
//HTTP session scoped beans are exposed as proxies
Custom bean name
By default, the configuration class uses the@Bean
Method as the bean name. This function can be overridden by@Bean
The name attribute is similar to the following example:
@Configuration
public class AppConfig {
@Bean(name = "myThing")
public Thing thing() {
return new Thing();
}
}
Bean alias
Similar to the discussion in bean naming, sometimes giving a simple bean multiple names is also called bean alias.@Bean
The name attribute of the annotation accepts an array of strings for this alias. The following example shows how to set the alias of a bean:
@Configuration
public class AppConfig {
@Bean({"dataSource", "subsystemA-dataSource", "subsystemB-dataSource"})
public DataSource dataSource() {
// instantiate, configure and return DataSource bean...
}
}
@Bean description
Sometimes it helps to provide a more detailed textual description of the bean. These beans are useful when exposed for monitoring purposes.
To add a description to@Bean
You can use@Description
Note, similar to the following example:
@Configuration
public class AppConfig {
@Bean
@Description("Provides a basic example of a bean")
public Thing thing() {
return new Thing();
}
}
1.12.4 use@Configuration
annotation
@Configuration
Is a class level annotation that indicates that the object is the source of the bean definition.@Configuration
Class declares that the bean is passed through the@Bean
Annotation method. stay@Configuration
Call on class@Bean
Methods can be used to define dependencies between beans. View the basic concepts: @ bean and @ configuration
Dependencies injected between beans
When beans depend on each other, expressing this dependency is as simple as letting one bean method call another, as shown in the following example:
@Configuration
public class AppConfig {
@Bean
public BeanOne beanOne() {
return new BeanOne(beanTwo());
}
@Bean
public BeanTwo beanTwo() {
return new BeanTwo();
}
}
In the previous example,beanOne
Injecting references through constructorsbeanTwo
。
Only if
@Bean
Method is declared in@Configuration
Class, this method declares that the dependencies between beans are valid. You can’t do this by using the normal@Component
Declare dependencies between beans.
Find method injection
As mentioned earlier, lookup method injection is an advanced feature that is rarely used. It is useful in some scenarios where singleton scope beans depend on prototype scope beans. Using Java provides a natural way to implement this pattern for configuration types. The following example shows how to find method injection:
public abstract class CommandManager {
public Object process(Object commandState) {
// grab a new instance of the appropriate Command interface
Command command = createCommand();
// set the state on the (hopefully brand new) Command instance
command.setState(commandState);
return command.execute();
}
// okay... but where is the implementation of this method?
protected abstract Command createCommand();
}
In this subclass, you can create aCommandManager
Subclass, abstractcreateCommand()
Method is overridden so that it looks for a new (prototype) command object. By using java configuration. The following example shows how to do this:
@Bean
@Scope("prototype")
public AsyncCommand asyncCommand() {
AsyncCommand command = new AsyncCommand();
// inject dependencies here as required
return command;
}
@Bean
public CommandManager commandManager() {
// return new anonymous implementation of CommandManager with createCommand()
// overridden to return a new prototype Command object
return new CommandManager() {
protected Command createCommand() {
return asyncCommand();
}
}
}
More about how Java based configuration works internally
Consider the following example, which shows a@Bean
The annotated method is called twice.
@Configuration
public class AppConfig {
@Bean
public ClientService clientService1() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientService clientService2() {
ClientServiceImpl clientService = new ClientServiceImpl();
clientService.setClientDao(clientDao());
return clientService;
}
@Bean
public ClientDao clientDao() {
return new ClientDaoImpl();
}
}
clientDao(
)InclientService1()
Called once and inclientService2()
Also called once. Because this method creates a newClientDaoImpl
Instance and return it, you usually want to have two instances (one for each service). There must be a problem: in spring, the default instantiation bean scope issingleton
。 That’s the magic: all@Configuration
Class is a subclass of cglib at run time. In subclasses, the subclass method first checks the container cache bean before calling the parent method to create the instance.
This behavior may vary depending on your bean scope. The singleton bean we’re talking about here.
After spring 3.2, there is no need to add cglib to your classpath, because cglib classes have been repackaged in
org.springframework.cglib
And directly contained inspring-core
Jar.Because cglib dynamically adds functionality at startup, there are some limitations. In particular, configuration classes cannot be
final
。 However, after spring 4.3, any constructor is allowed on the configuration class, including@Autowired
Or constructors without default arguments declare the use of default injection.If you want to avoid cglib restrictions, consider
@Configuration
Class (for example, a normal@Component
(replace) with your@Bean
method. stay@Bean
Cross method calls between methods are not intercepted, so you have to rely only on what needs to be injected at the constructor or method level.Code example:
com.liyong.ioccontainer.starter.BaseJavaConfigIocContainer
1.12.5 writing Java based configuration
Spring’s Java based configuration feature allows you to write annotations, which can reduce your configuration complexity.
Use @ import annotation
Similar to the < import / > elements are used in spring XML files to help with modular configuration,@Import
Annotations can be loaded in other configuration classes@Bean
Definition, similar to the following example:
@Configuration
public class ConfigA {
@Bean
public A a() {
return new A();
}
}
@Configuration
@Import(ConfigA.class)
public class ConfigB {
@Bean
public B b() {
return new B();
}
}
When initializing the context, it is not necessary to specifyConfigA.class
andConfigB.class
, just to be provided visuallyConfigB
, similar to the following example:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(ConfigB.class);
// now both beans A and B will be available...
A a = ctx.getBean(A.class);
B b = ctx.getBean(B.class);
}
This approach simplifies the instantiation of containers, and only one class needs to be handled, rather than potentially remembering a large number of them during construction@Configuration
Class.
After spring 4.2,
@Import
It also supports reference to regular component classes, similar toAnnotationConfigApplicationContext.register
method. This is very useful if you want to avoid component scanning by using some configuration classes as entry points to display and define all components.
In the imported@Bean
Injecting dependencies into definitions
The previous example works, but it’s too simple. In most time scenarios, beans depend on each other between configuration classes. When using XML, this is not a problem, because there is no compiler involved and you can declare itref="someBean"
And trust spring to handle during container initialization. When using@Configuration
Class, the java compiler constrains on the configuration model, because references to other beans must be valid Java syntax.
Fortunately, solving this problem is very simple. As we discussed before,@Bean
Methods can have any number of parameters that describe the bean’s dependencies. Consider the following more realistic scenarios for these@Configuration
Class, each bean is defined in other classes:
@Configuration
public class ServiceConfig {
@Bean
public TransferService transferService(AccountRepository accountRepository) {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
@Bean
public AccountRepository accountRepository(DataSource dataSource) {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return new DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
There are other ways to achieve the same result. remember@Configuration
Classes end up just another bean in the container: that means they can take advantage of@Autowired
and@Value
Injection and other features that are the same as other beans.
Make sure that dependencies injected in this way are the simplest.
@Configuration
Classes are processed very early during context initialization, and forcing dependencies to be injected in this way can result in unexpected early initialization. As shown in the example above, use parameter based injection whenever possible.In addition, through
@Bean
definitionBeanPostProcessor
And beanfactory postprocessor. These should normally be declared asstatic
@Bean
Method, do not trigger the initialization of the configuration class they contain. besides,@Autowired
and@Value
It may not work on a configuration class because it was created as a bean instance earlier thanAutowiredAnnotationBeanPostProcessor
。
The following example shows how a bean can be assembled to other beans:
@Configuration
public class ServiceConfig {
@Autowired
private AccountRepository accountRepository;
@Bean
public TransferService transferService() {
return new TransferServiceImpl(accountRepository);
}
}
@Configuration
public class RepositoryConfig {
private final DataSource dataSource;
public RepositoryConfig(DataSource dataSource) {
this.dataSource = dataSource;
}
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(dataSource);
}
}
@Configuration
@Import({ServiceConfig.class, RepositoryConfig.class})
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return new DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
// everything wires up across configuration classes...
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
stay
@Configuration
Class construction method injection is only supported after spring 4.3. Note: if the target bean definition has only one constructor, you do not need to specify it@Autowired
。Code example:
com.liyong.ioccontainer.starter.BeanAndConfigurationImportContainer
Fully qualified import beans for easier navigation
In the previous scenario, use the@Autowired
It works well and provides the expected modularity, but determining where the definition of the autoassemble bean is declared is still somewhat ambiguous. For example, as a developer, seeServiceConfig
How to know exactly@Autowired
AccountRepository
Where are beans defined? It’s not explicit in the code, which might be good. Remember, spring tools provides eclipse with tools to render graphics that show how all the objects are connected, which may be what you need. Your Java ide makes it easier to find all the declarations and usesAccountRepository
Type and display it quickly@Bean
Method and the return type.
If this ambiguity is unacceptable, and you want to get it directly from within the IDE@Configuration
Class to navigate to another@Configuration
Class, consider the autoassemble configuration class itself. The following example shows how to do this:
@Configuration
public class ServiceConfig {
@Autowired
private RepositoryConfig repositoryConfig;
@Bean
public TransferService transferService() {
// navigate 'through' the config class to the @Bean method!
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}
In the previous case,AccountRepository
Complete display definition. But,ServiceConfig
Now tightly coupled toRepositoryConfig
。 This is the trade-off. By using interface based or abstract class based@Configuration
Class can alleviate this tight coupling to some extent. Consider the following example:
@Configuration
public class ServiceConfig {
@Autowired
private RepositoryConfig repositoryConfig;
@Bean
public TransferService transferService() {
return new TransferServiceImpl(repositoryConfig.accountRepository());
}
}
@Configuration
public interface RepositoryConfig {
@Bean
AccountRepository accountRepository();
}
@Configuration
public class DefaultRepositoryConfig implements RepositoryConfig {
@Bean
public AccountRepository accountRepository() {
return new JdbcAccountRepository(...);
}
}
@Configuration
@Import({ServiceConfig.class, DefaultRepositoryConfig.class}) // import the concrete config!
public class SystemTestConfig {
@Bean
public DataSource dataSource() {
// return DataSource
}
}
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(SystemTestConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
transferService.transfer(100.00, "A123", "C456");
}
Now?ServiceConfig
And specificDefaultRepositoryConfig
Loosely coupled, and the built-in ide tools are still very useful: you can easily access themRepositoryConfig
The level of implementation. In this way, navigation@Configuration
Classes and their dependencies are no different from the usual process of navigating interface based code.
If you want to smoothly start the order in which these beans are created, consider declaring them as
@Lazy
(for first access rather than creation at startup) or@DependsOn
Other beans (make sure that the other specified beans are created before the current bean is created and are not affected by the latter’s direct dependencies).
Conditionally include@Configuration
Class or@Bean
method
Conditional enable or disable complete, depending on some system state@Configuration
Class or even single@Bean
Method, usually very useful. Note: can be enabled / disabled@Configuration
Class or@Configuration
Class@Bean
method. A common example is to use@Profile
Annotations to activate beans, only when in springEnvironment
designatedprofile
When activated (view bean definition profiles details).
@Profile
Annotations are called annotations by using a very flexible annotation called@Conditional
Realized.@Conditional
NOTE indicates that the@Bean
Specific information should be consulted beforeorg.springframework.context.annotation.Condition
realization.
Condition
The implementation interface provides amatches(…)
Method, which returns true or false. For example, the following listing showsCondition
Yes@Profile
Real implementation:
@Override
public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
// Read the @Profile annotation attributes
MultiValueMap<String, Object> attrs = metadata.getAllAnnotationAttributes(Profile.class.getName());
if (attrs != null) {
for (Object value : attrs.get("value")) {
if (context.getEnvironment().acceptsProfiles(((String[]) value))) {
return true;
}
}
return false;
}
return true;
}
see@Conditional
The documentation is more detailed.
Combining Java and XML configuration
Spring’s@Configuration
Class cannot100%
To replace spring XML. Some tools, such as spring XML namespaces, are still ideal ways to configure containers. When it is convenient or necessary to use XML, you can choose: use“ClassPathXmlApplicationContext
Instantiate the container as XML centric or by using theAnnotationConfigApplicationContext
And Java configuration center.@ImportResource
Annotations can be imported into XML as needed.
XML centric@Configuration
Use of class
Boot the spring container from XML and include it in a special way@Configuration
Class might be better. For example, in a large existing code base that uses spring XML, create as needed@Configuration
And it’s easier to include existing classes in XML files. Later in this section, we’ll show you how to use it in this “XML centric” context@Configuration
Class.
-
statement
@Configuration
It is similar to the common spring < bean / > elementremember
@Configuration
Class is ultimately a bean definition in the container. In this series of examples, we create@Configuration
Name the classAppConfig
And include it in system test- config.xml Similar to the < bean / > definition in. because<context:annotation-config/>
Opened, container inAppConfig
Medium recognition@Configuration
Annotate and handle the @ bean method declaration.The following example shows the normal configuration in Java:
@Configuration public class AppConfig { @Autowired private DataSource dataSource; @Bean public AccountRepository accountRepository() { return new JdbcAccountRepository(dataSource); } @Bean public TransferService transferService() { return new TransferService(accountRepository()); } }
The following example shows
system-test-config.xml
Part of the document:<beans> <!-- enable processing of annotations such as @Autowired and @Configuration --> <context:annotation-config/> <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> <bean class="com.acme.AppConfig"/> <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> </beans>
The following example shows the possible
jdbc.properties
Document:jdbc.url=jdbc:hsqldb:hsql://localhost/xdb jdbc.username=sa jdbc.password=
public static void main(String[] args) { ApplicationContext ctx = new ClassPathXmlApplicationContext("classpath:/com/acme/system-test-config.xml"); TransferService transferService = ctx.getBean(TransferService.class); // ... }
stay
system-test-config.xml
In the file, AppConfig < bean / > does not declare an ID element. While this is acceptable, it is unnecessary because no other beans refer to it, and it is unlikely to get it explicitly from the container by name. Again,DataSource
Beans can only be assembled automatically by type, so explicit beans are not strictly requiredid
。 -
use
<context:component-scan/>
choice@Configuration
classbecause
@Configuration
Meta annotations are@Component
, by@Configuration
Annotated classes are candidates for automatic scanning of components. Using the same scenario as described in the previous example, we can redefine itsystem-test-config.xml
To use component scanning. Note that in this scenario, we do not need to display the declaration of<context:annotation-config/>
Because<context:component-scan/>
Activate the same function.The following example shows the modified
system-test-config.xml
Document:<beans> <!-- picks up and registers AppConfig as a bean definition --> <context:component-scan base-package="com.acme"/> <context:property-placeholder location="classpath:/com/acme/jdbc.properties"/> <bean class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> </beans>
@Configuration
Class centered XML and@ImportResource
Combined use of
In application,@Configuration
Classes are the main mechanism for configuring containers, but you may still need to use at least some XML. In this scenario, you can use the@ImportResource
And define the XML you need. This implements a “Java centric” approach to configuring containers and keeping XML to a minimum. The following example shows how to use it@ImportResource
Annotations to implement Java centric configuration and use XML when needed:
@Configuration
@ImportResource("classpath:/com/acme/properties-config.xml")
public class AppConfig {
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String username;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource() {
return new DriverManagerDataSource(url, username, password);
}
}
properties-config.xml
:
<beans>
<context:property-placeholder location="classpath:/com/acme/jdbc.properties"/>
</beans>
jdbc.properties
:
public static void main(String[] args) {
ApplicationContext ctx = new AnnotationConfigApplicationContext(AppConfig.class);
TransferService transferService = ctx.getBean(TransferService.class);
// ...
}
Code example:
com.liyong.ioccontainer.starter.BaseJavaConfigAndXmlIocContainer
author
Personally engaged in the financial industry, I have worked in Chongqing’s first-class technical team, such as yijifu, Sijian technology, a car Hailing platform, etc. at present, I am in charge of the construction of unified payment system in a bank. I have a strong interest in the financial industry. At the same time, it also practices big data, data storage, automatic integration and deployment, distributed microservices, responsive programming, artificial intelligence and other fields. At the same time, it is also keen to share technology and create official account and blog site.
Blog address: http://youngitman.tech
CSDN: https://blog.csdn.net/liyong1…
The official account of WeChat:
Technical exchange group: