How to enable <aop:aspectj-autoproxy> with java-based annotations - java

I am trying to set up Spring AOP without any XML.
I'd like to enable <aop:aspectj-autoproxy> in a class which is
annotated with #Configuration.
This is the way it would be defined in an XML-file:
<aop:aspectj-autoproxy>
<aop:include name="msgHandlingAspect" />
</aop:aspectj-autoproxy>
I tried to annotate my class with #Configuration and #EnableAspectJAutoProxy
but nothing happened.

Did you create an aspect bean in the same #Configuration class?
Here's what the docs suggest:
#Configuration
#EnableAspectJAutoProxy
public class AppConfig {
#Bean
public FooService fooService() {
return new FooService();
}
#Bean // the Aspect itself must also be a Bean
public MyAspect myAspect() {
return new MyAspect();
}
}

I used the accepted answer solution but I had unexpected problems and never understand untill to add this parameter to configuration.
#EnableAspectJAutoProxy(proxyTargetClass = true)
If you use annotation into #Controller you'll need to configure in this way
remember if you have java 8 you need to use a version of AspectJ greater than 1.8.X
#Configuration
#EnableAspectJAutoProxy(proxyTargetClass = true)
public class AppConfig {
#Bean
public AccessLoggerAspect accessLoggerAspect() {
return new AccessLoggerAspect();
}
}

Related

Is there any annotation equivalent of "default-lazy-init" attribute in Spring Framework?

How can I set this attribute in my JavaConfig application context?
<beans default-lazy-init="true">
<!-- no beans will be pre-instantiated... -->
</beans>
The Spring org.springframework.context.annotation.Lazy annotation indicates whether a bean is to be lazily initialized.
You can add it to a #Configuration class, a #Bean method or a #Component (for example #Service annotated class)
Example for a single bean:
#Configuration
public class MyConfig {
#Bean
#Lazy
public Example myLayzBean() {
return new Example();
}
}
Example for all beans in one configuration class
#Configuration
#Lazy
public class MyConfig {
#Bean
public Example1 myLayzBean1() {
return new Example1();
}
#Bean
public Example2 myLayzBean2() {
return new Example2();
}
}
Example for bean found by component scan
#Service
#Lazy
public class Example3 {
}

Eliminating Spring.xml from Spring Framework

In Spring Framework is it possible to eliminate the entire Spring.xml and use a configuration class with #Configuration and #Bean annotation for creating bean, and for all other purpose use a spring.xml?
Yes, you can have pure java configuration in Spring. You have to create a class and annotate it with #Configuration. We annotate methods with #Bean and instantiate the Spring bean and return it from that method.
#Configuration
public class SomeClass {
#Bean
public SomeBean someBean() {
return new SomeBean();
}
}
If you want to enable component scanning, then you can give #ComponentScan(basePackages="specify_your_package") under the #Configuration. Also the method name as someBean serves as bean id. Also if you have to inject a dependency, you can use constructor injection and do as following:
#Configuration
public class SomeClass {
#Bean
public SomeDependency someDependency() {
return new SomeDependency();
}
#Bean
public SomeBean someBean() {
return new SomeBean(someDependency());
}
}
Yes,most of (maybe all of)official guides uses absolutely no xml configuration file,just annotations.

Spring Boot read values from application properties

I'm not sure if I understand it correctly, but from what I got, is that I can use #Value annotations to read values from my application.properties.
As I figured out this works only for Beans.
I defined such a bean like this
#Service
public class DBConfigBean {
#Value("${spring.datasource.username}")
private String userName;
#Bean
public String getName() {
return this.userName;
}
}
When the application starts I'm able to retrieve the username, however - how can I access this value at runtime?
Whenever I do
DBConfigBean conf = new DBConfigBean()
conf.getName();
* EDIT *
Due to the comments I'm able to use this config DBConfigBean - but my initial problem still remains, when I want to use it in another class
#Configurable
public SomeOtherClass {
#Autowired
private DBConfigBean dbConfig; // IS NULL
public void DoStuff() {
// read the config value from dbConfig
}
}
How can I read the DBConfig in a some helper class which I can define as a bean
Thanks
As Eirini already mentioned you must inject your beans.
The #Value annotation only works on Spring beans.
There is another way of accessing configuration with #ConfigurationProperties.
There you define a class that holds the configuration.
The main advantage is, that this is typesafe and the configuration is in one place.
Read more about this:
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-vs-value
You shouldn't instantiate your service with the new operator. You should inject it, for example
#Autowired
private DBConfigBean dbConfig;
and then dbConfig.getName();
Also you don't need any #Bean decorator in your getName() method
You just need to tell spring where to search for your annotated beans. So in your configuration you could add the following:
#ComponentScan(basePackages = {"a.package.containing.the.service",
"another.package.containing.the.service"})
EDIT
The #Value, #Autowired etc annotations can only work with beans, that spring is aware of.
Declare your SomeOtherClass as a bean and add the package config in your #Configuration class
#Bean
private SomeOtherClass someOtherClass;
and then
#Configuration
#ComponentScan(basePackages = {"a.package.containing.the.service"
"some.other.class.package"})
public class AppConfiguration {
//By the way you can also define beans like:
#Bean
public AwesomeService service() {
return new AwesomeService();
}
}
Wrap your DBConfig with #Component annotation and inject it using #Autowired :
#Autowired
private DBConfig dbConfig;
Just add below annotation to your DBConfigBean class:
#PropertySource(value = {"classpath:application.properties"})

Spring Bean Alias in JavaConfig

I have a #Service annotated class which provides core functionality which I can use in all my projects:
#Service
public class MyService {}
and another one which extends it to implement project specific stuff:
#Service
public class ExtendedMyService extends MyService {}
Now I would like to configure a bean alias to be able to use #Qualifier("MyServiceAlias") when autowiring it using a property:
# MyService qualifier (default: myService)
myService.qualifier=extendedMyService
In XML it would look like:
<alias name="${myService.qualifier}" alias="MyServiceAlias" />
It is also discussed here, but I need to do it w/o XML, JavaConfig only.
Is it possible and how to realize?
There is an open Jira for this: https://jira.spring.io/browse/SPR-6736
The workaround is to use #Bean in #Configuration class:
#Configuration
public class AppConfig {
#Bean(name = { "dataSource", "subsystemA-dataSource", "subsystemB-dataSource" })
public MyService myService() {}
}
If you want to use the placeholder, another workaround is to use #Bean in a #Configuration class using #Value and the Spring applicationContext.
#Configuration
public class AppConfig {
#Autowired
private ApplicationContext context;
#Bean
public MyService myService(#Value("${myService.qualifier}") String qualifier) {
return (MyService) context.getBean(qualifier);
}
}
NB : special consideration must be taken for the placeholder bean which must be loaded at the beginning (cf javadoc)
With small amount of configuration and one ImportBeanDefinitionRegistrar you can configure bean aliases via Java configuration. You can check bean-alias library project for reference - developed for the needs of my projects. Feel free to modify and/or copy the source into your own project in case the spring version used in it does not work with your setup.
Once you have the library on your path, you declare an alias through the annotation:
#Configuration
#BeanAlias(name = "fromName", alias = "toName")
public class ExampleConfiguration {
}
That's it.
How it works is that with the annotation we import a ImportBeanDefinitionRegistrar implementation
#Import(BeanAliasBeanRegistrar.class)
public #interface BeanAlias {
}
which registers the alias in the BeanDefinitionRegistry
class BeanAliasBeanRegistrar implements ImportBeanDefinitionRegistrar, PriorityOrdered {
#Override
public void registerBeanDefinitions(AnnotationMetadata metadata, BeanDefinitionRegistry registry) {
...
registerAlias(registry, metadata.getAnnotationAttributes(BeanAlias.class.getName()));
}
private void registerAlias(BeanDefinitionRegistry registry, Map<String, Object> attributes) {
...
registry.registerAlias(name, alias);
}
}

Spring 3.1: How do I inject a bean created in a different configuration class

I'm just setting up a web application using Spring 3.1 and I'm trying to do this by using java configuration.
I have two configuration classes "AppConfig" (general bean definitions) and "WebConfig" (Spring MVC configuration). How can I reference a bean that has been declared in AppConfig in the WebConfig class?
Below, the validator in the AppConfig configuration class should use the messageSource fromn WebConfig.
AppConfig:
#Configuration
#ComponentScan(basePackages = { "com.example" })
public class AppConfig {
#Bean
public Validator validator() {
final LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
validator.setValidationMessageSource(messageSource());
return validator;
}
}
WebConfig:
#Configuration
#EnableWebMvc
#ComponentScan(basePackages = { "com.example.common.web", "com.example.web" })
public class WebConfig extends WebMvcConfigurerAdapter {
#Bean
public ReloadableResourceBundleMessageSource messageSource() {
final ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
messageSource.setBasename("classpath:messages");
return messageSource;
}
}
When I want to reference a bean from the same configuration class, I'd just call its setup method, but I obviously cannot do this when the bean is declared in another class.
Your advice will be greatly appreciated!
Configurations are beans, too, so you can use #Autowired
public class WebConfig extends WebMvcConfigurerAdapter {
#Autowired
private Validator validator;
...
}
There are two ways to do so:
public class WebConfig {
#Autowired
AppConfig appconfig;
...
}
or, as Aaron Digulla mentioned:
public class WebConfig {
#Autowired
Validator validator;
...
}
I prefer the first form, with one autowiring you can access the whole configuration, and then you can access its beans, by calling theNewBean.setValidator(appConfig.validator());.
I think Aaron Digulla and Amir Pashazadeh are both correct but there is also another annotation since JSR 330 was introduced. You can also use #Inject
#Inject
private Validator validator;
http://docs.spring.io/spring/docs/3.0.x/reference/beans.html#beans-autowired-annotation

Categories

Resources