首先
@Value
注解可以方便的获取配置文件*.properties
的参数。
在写代码的时候遇到这样一个问题。为了减少重复代码,我们通常需要写一个抽象类把共有的方法抽象到Abstract 类中。
AbstractDao<T>
如果遇到需要向这个class的构造方法注入参数。且这个参数是通过抽象方法获取的。且这个数据是使用 Spring的 @Value 注解获取的。这个描述比较绕,我们直接看代码:
|
|
|
|
代码运行起来以后,我们发现 userTableId,并不能取到相应的值,这个时候
@Value
失效了。实际上这个问题的根源是因为@Value
的加载是发生在对象实例化之后。也就是首先调用对象的构造函数,然后再获取配置文件中的数据。
解决的方案是使用注解
@PostConstruct
,意思是构造函数执行完以后再 执行注解标记的方法。我们可以吧抽象函数做如下修改:
|
|
http://olivergierke.de/2009/05/using-springs-configurable-in-three-easy-steps/
3. Enable load-time weaving
To actually get the injection working you need to weave some Spring aspects in your domain class. While you could do this by compile time weaving, i chose load time weaving as it is much simpler to set up in development environment. To get it up and running you declare
https://tamasgyorfi.net/2013/11/13/spring-dependency-injection-configurable/<context:load-time-weaver aspectj-weaving="autodetect"/>
that pretty much tells Spring to look around for some available load time weaver an use it. The cruicial part now is to activate a Java agent for your runtime that now weaves the aspects into the domain class during class loadingwhether it is possible to inject dependencies into objects that are not created by Spring
In the EJB world, there is no way to inject dependencies into a bean created with the new operator
In a default Spring setup, an @Autowired class instantiated with the new keyword will behave just like in an enterprise application: all the dependencies will be left untouched; they will not be injected but left with their default values (a.k.a. null)
in Spring there is an awesome way to inject dependencies into objects created with the new keyword: the @Configurable annotation.
It tells Spring to inject dependencies into the object before the constructor is run.
- Add the following jars to your classpath (Spring will use aspect orientation in order to work around default behavior, and make your object eligible for dependency injection): aspectj-x.x.x.jar, aspectjrt.jar, aspectjveawer-x.x.x.jar
- Add a Spring-based java agent to your run configuration like this: -javaagent:”PATH\spring-instrument-x.x.x.jar”
The core idea behind domain object DI is : An AspectJ-woven aspect selects join points corresponding to creation or deserialization of any object matching certain specification. Advice to those join points inject dependencies into the object being created or deserialized.
You need to have org.springframework.aspects-3.0.4.RELEASE.jar in your classpath. This jar contains a class called AnnotationBeanConfigurerAspect which acts on this annotation . AnnotationBeanConfigurerAspect needs to be configured in spring application context xml to obtain a reference to the bean factory that is to be used to configure new objects. Also, we need to configure the auto scanning of User entity and dao class so that they can be auto-registered. You also need to activate the Spring LoadTimeWeaver which is also present in context namespace.
https://www.javacodegeeks.com/2013/09/spring-configurable-magic.html
Spring introduce an annotation with name Configurable. Using this annotation on our domain objects make them Managed by spring.
But how does it work: Configurable for its purpose needs AspectJ Compiler, your class needs Byte Code Enhancement in Compile Time or Load Time until can satisfy your requirements.
But how does it work: Configurable for its purpose needs AspectJ Compiler, your class needs Byte Code Enhancement in Compile Time or Load Time until can satisfy your requirements.
AbstractJUnit4SpringContextTests
http://docs.spring.io/autorepo/docs/spring-framework/4.3.0.RC2/spring-framework-reference/html/aop.html
aspectjweaver
@Component
@Aspect
@EnableAspectJAutoProxy
@ComponentScan(basePackages = {"com.spring_cookbook.aspect"})
@EnableAspectJAutoProxy in the Spring configuration will make Spring actually use the aspects and execute their advices.
http://www.jianshu.com/p/8551e0ea9ad6
http://www.baeldung.com/spring-performance-logging
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/aop.html
The @AspectJ style supports additional instantiation models, and richer pointcut composition. It has the advantage of keeping the aspect as a modular unit.
On balance the Spring team prefer the @AspectJ style whenever you have aspects that do more than simple "configuration" of enterprise services.
ProxyFactory factory = new ProxyFactory(new SimplePojo()); factory.addInterface(Pojo.class); factory.addAdvice(new RetryAdvice()); Pojo pojo = (Pojo) factory.getProxy(); // this is a method call on the proxy! pojo.foo();
It means that self-invocation is not going to result in the advice associated with a method invocation getting a chance to execute.
Okay, so what is to be done about this? The best approach (the term best is used loosely here) is to refactor your code such that the self-invocation does not happen
The next approach is absolutely horrendous, and I am almost reticent to point it out precisely because it is so horrendous. You can (choke!) totally tie the logic within your class to Spring AOP by doing this:
public class SimplePojo implements Pojo { public void foo() { // this works, but... gah! ((Pojo) AopContext.currentProxy()).bar(); } public void bar() { // some logic... } }
factory.setExposeProxy(true);
Advisors seem to be an old "AOP lite" type of defining cross-cutting concerns from Spring 1.2 when Java 5 usage was still somewhat uncommon and thus @AspectJ syntax (via Java annotations) not used in Spring. The concept has still survived for lovers of schema-based AOP rather than annotation-based AOP or pure AspectJ syntax, see Spring documentation on advisors.
Advice
is the way you take an action on your Pointcut
. You can use before, after or even around advice to apply any action you defined. Talking about Spring Aspect
, it is only a class which is a high level and merge two concepts : jointpoint
and advice
. It can be done through XML based blueprint, or programmatically. Also you should specify your point where you want to plug in an aspect, it is done by using Jointpoint
.
Also Spring
Aspects
and Advice
aren't substitute for each other, because Aspects is only merger for jointpoint and advice.
Most aspects are a combination of advice that defines the aspect’s behavior and a pointcut defining where the aspect should be executed.
AdvisorSpring recognizes this and offers advisors, which combine advice and pointcuts into one object.
More specifically, the
PointcutAdvisor
does this.public interface PointcutAdvisor {
Pointcut getPointcut();
Advice getAdvice();
}
Most of Spring’s built-in pointcuts also have a corresponding
PointcutAdvisor
. This is convenient if you want to define a pointcut and the advice it is managing in one place.http://stackoverflow.com/questions/22852657/configuring-aspectj-aspects-using-spring-ioc-with-javaconfig
http://www.jianshu.com/p/62f22d821333
@Aspect
public class Monitor {
private static final Logger logger = LoggerFactory.getLogger(Monitor.class);
@Pointcut("execution(public * *(..)) && @annotation(demo.APM)")
private void apmHandler(){}
@Around("apmHandler()")
public Object apmRecordTime(ProceedingJoinPoint pjp) throws Throwable{
Object ret = null;
MethodSignature signature = (MethodSignature) pjp.getSignature();
Method method = signature.getMethod();
APM apmAnnotation = method.getAnnotation(APM.class);
String commandName = apmAnnotation.value();
try {
long startTime = System.nanoTime();
ret = pjp.proceed();
long processTime = (System.nanoTime() - startTime); // avg_time unit: nano seconds
logger.trace("command[{}] spend avg_time:{} ms", commandName, processTime/1000000d);
} finally{
}
return ret;
}
@AfterThrowing(pointcut="apmHandler()", throwing= "error")
public void apmRecordException(JoinPoint jp, Throwable error){
MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
APM apmAnnotation = method.getAnnotation(APM.class);
String commandName = apmAnnotation.value();
logger.trace("command[{}] throw exception: {}", commandName, error);
}
}
有一段说Aspect类的实例化是由AspectJ接管的!
Like classes, aspects may be instantiated, but AspectJ controls how that instantiation happens -- so you can't use Java's new form to build new aspect instances. By default, each aspect is a singleton, so one aspect instance is created. This means that advice may use non-static fields of the aspect, if it needs to keep state around
The aspect is a singleton object and is created outside the Spring container. A solution with XML configuration is to use Spring's factory method to retrieve the aspect.
<bean id="syncLoggingAspect" class="uk.co.demo.SyncLoggingAspect"
factory-method="aspectOf" />
With this configuration the aspect will be treated as any other Spring bean and the autowiring will work as normal.
You have to use the factory-method also on Enum objects and other objects without a constructor or objects that are created outside the Spring container.
You have to use the factory-method also on Enum objects and other objects without a constructor or objects that are created outside the Spring container.
通过如此如下方式是可以成功拿到AOP的bean
import org.aspectj.lang.Aspects;
@configure
public AppConfig{
@Bean
public Monitor monitor(){
Monitor monitor = Aspects.aspectOf(Monitor.class);
// monitor.config(xxx);
// monitor.register(xxxx);
return monitor;
}
}
https://blog.jayway.com/2015/09/08/defining-pointcuts-by-annotations/
@Around("@annotation(YourAnnotation) && execution(* *(..))")
http://www.onlinetutorialspoint.com/spring/spring-aop-around-advice-example.htmlhttps://segmentfault.com/a/1190000006914183
MethodInterceptor
方法拦截器, 继承了Interceptor
接口,Interceptor
接口又继承了Advice
接口,Interceptor
和Advice
都是标识接口没有属性和方法public interface MethodInterceptor extends Interceptor {
Object invoke(MethodInvocation invocation) throws Throwable;
}
这里的
invoke
方法有代理的责任,也就是说在invoke
方法内部会调用代理的那个方法,也就是去执行连接点MethodInvocation
继承了Invocation
接口,Invocation
接口继承了Joinpoint
接口,注意这里是Joinpoint
,是java
语言的java.lang.reflect.AccessibleObject.Pointcut
而Joinpoint
接口内部有 Object proceed() throws Throwable
这样一个方法,调用这个方法会执行JoinPoint描述的那个被代理的方法。
//5 配置器
Advisor
是Pointcut
和Advice
的配置器,将 某个具体的 Advice
注入到 Pointcut
所指定的位置ProxyFactoryBean
, 创建代理对指定的某个类的对象进行代理,或者对符合规则的一堆类进行代理使用时只需进行配置。
当启用了@AspectJ支持后,只要我们在Spring容器中配置一个带@AspectJ注释的Bean,Spring将会自动识别该Bean,并将该Bean作为切面处理。下面是一个例子:
@Aspect
public class LogAspect {
}
切面类(用@Aspect修饰的类)和其他类一样可以有方法和属性的定义,还可能包括切入点、增强处理的定义。当我们使用@Aspect来修饰一个Java类后,Spring将不会把该Bean当成组件Bean处理,因此当Spring容器检测到某个Bean使用了@AspectJ标注之后,负责自动增强的后处理Bean将会忽略该Bean,不会对该Bean进行任何增强处理。
Spring AOP采用基于代理的AOP实现方案,而AspectJ则采用编译时增强的解决方案。
Spring2.0可以无缝的整合Spring AOP、IoC和AspectJ,是的所有的AOP应用完全融入基于Spring的框架,这样的集成不会影响Spring AOP API或者AOP Alliance API,Spring AOP保持了向下兼容性,依然允许直接使用Spring AOP API来完成AOP编程。
一旦我们掌握了AOP的概念,不难发现进行AOP编程是一件很简单的事情。纵观AOP编程,其实需要程序员参与的只有三个部分:
- 定义普通的业务组件
- 定义切入点(PointCut),一个切入点可能横切多个业务组件
- 定义增强处理(Advice),增强处理及时在AOP框架为普通业务组件织入时的处理动作
第一部分是最为平常的事情了,无需说明。第二、三部分就是AOP的关键:一旦定义了合适的切入点和增强处理,AOP框架将会自动生成代理,而AOP代理的方法大致有如下公式:
代理对象的方法 = 增强处理 + 被代理对象的方法
Spring 1.x采用自身提供的AOP API来定义切入点和增强处理,程序可以直接使用Spring AOP API来定义切入点和增强处理,但这种方式似乎有些过时了,现在通常建议使用AspectJ方式来定义切入点和增强处理,在这种方式下,Spring依然有如下两种选择来定义切入点和增强处理:
- 基于注解的配置方式:使用@Aspect ,@Pointcut等注解来标注切入点和增强处理
当不同的切面中的多个增强处理需要在同一个连接点被织入时,Spring AOP将以随机的顺序来织入这些增强处理。如果应用需要指定不同切面类里的增强处理的优先级,Spring提供了如下两种解决方案:
- 让切面类实现org.springframework.core.Ordered接口:实现该接口只需要实现一个int getOrder()方法,该方法返回值越小,优先级越高
- 直接使用@Order注解来修饰一个切面类:使用这个注解时可以配置一个int类型的value属性,该属性值越小,优先级越高
优先级高的切面类里的增强处理的优先级总是比优先级低的切面类中的增强处理的优先级高。例如:优先级为1的切面类Bean1包含了@Before,优先级为2的切面类Bean2包含了@Around,虽然@Around优先级高于@Before,但由于Bean1的优先级高于Bean2的优先级,因此Bean1中的@Before先被织入。
同一个切面类里的两个相同类型的增强处理在同一个连接点被织入时,Spring AOP将以随机的顺序来织入这两个增强处理,没有办法指定它们的织入顺序。如果确实需要保证它们以固有的顺序被织入,则可以考虑将多个增强处理压缩为一个增强处理;或者将不同增强处理重构到不同切面中,通过在切面级别上定义顺序。
如果只要访问目标方法的参数,Spring还提供了一种更加简洁的方法:我们可以在程序中使用args来绑定目标方法的参数。如果在一个args表达式中指定了一个或多个参数,该切入点将只匹配具有对应形参的方法,且目标方法的参数值将被传入增强处理方法
http://www.baeldung.com/spring-aop-annotation
http://docs.spring.io/autorepo/docs/spring-framework/4.3.0.RC2/spring-framework-reference/html/aop.html
http://www.baeldung.com/spring-aop-annotation
@Aspect
@Component
public
class
ExampleAspect {
}@Around
(
"@annotation(LogExecutionTime)"
)
public
Object logExecutionTime(ProceedingJoinPoint joinPoint)
throws
Throwable {
return
joinPoint.proceed();
- Join Points: A Join Point is a point in the execution of the application where an aspect can be plugged in. This point could be a method being called, an exception being thrown, or even a field being modified.
- Pointcuts: Pointcuts are expressions that are matched with Join points to determine whether advice needs to be executed or not. This is a set of more than one Join point where an advice should be executed.
- Advice: Advice defines both the when and where of an aspect. The actual action to be taken before or after method execution. Actual piece of code that is invoked during program execution by Spring's Aspect Oriented Programming framework.
- Aspects: An aspect is the merger of Advice and Pointcuts. Advice and pointcuts define everything known about an aspect, what it does and where and when it does it.
- Introductions: An Introduction allows adding new methods or attributes to existing classes. The new method and instance variable can be introduced to existing classes without having to change them, giving them new state and behavior.
- Weaving: Weaving is the process of applying aspects to a target object to create a new proxied object. The target object at the specified Join points.
The weaving can occur at several points in the target object’s lifetime:
- Compile Time: Aspects are woven in as the target class is compiled. It requires a special compiler. AspectJ’s weaving compiler weaves aspects this way.
- Classload Time: Aspects are woven in as the target class is loaded into the JVM. It requires a special ClassLoader that enhances that target class's bytecode before the class is introduced into the application. AspectJ 5’s load-time weaving (LTW) support weaves aspects this way.
- Runtime: Aspects are woven in sometime during the execution of the application. An AOP container will dynamically generate a proxy object that will delegate to the target object while weaving in the aspects.
http://forum.spring.io/forum/spring-projects/aop/80627-methodinterceptor-invoke-method-called-twice
Further investigation revealed that the issue was because of Advisors. If I directly use the Advice in proxyFactoryBean and remove pointcutAdvisor tag the invoke() method is called only once whereas even if I only use Advice in proxyFactoryBean but keep the Advisor tag (although not using it) the invoke() method is called twice. Please let me know if you can provide a reason for such behavior by Advisor.
I don't annotate aspects with @Component annoation, try to remove it, maybe because of that is being processed twice by Spring.
Implementing the
org.springframework.beans.factory.DisposableBean
interface allows a bean to get a callback when the container containing it is destroyed. The DisposableBean
interface specifies a single method:void destroy() throws Exception;
It is recommended that you do not use the
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.htmlDisposableBean
callback interface because it unnecessarily couples the code to Spring. Alternatively, use the @PreDestroy
annotation or specify a generic method that is supported by bean definitions. With XML-based configuration metadata, you use the destroy-method
attribute on the <bean/>
. With Java config, you use the destroyMethod
attribute of @Bean
https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-external-config.html#boot-features-external-config-typesafe-configuration-properties
You also need to list the properties classes to register in the
@EnableConfigurationProperties
annotation:@Configuration @EnableConfigurationProperties(FooProperties.class) public class MyConfiguration { }
To work with
@ConfigurationProperties
beans you can just inject them in the same way as any other bean.private final FooProperties properties;
Before Spring 4.0 there were also JpaTemplate and JpaDaoSupport classes; however they have been removed in favor of using plain JPA
use spring jpa CrudRepository
@EnableTransactionManagement
@EnableJpaRepositories
https://github.com/spring-projects/spring-retry/issues/32
https://dzone.com/articles/spring-retry-ways-integrate
spring.aop.proxy-target-class=true
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId></dependency>
可以看下面关于AOP的默认配置属性,其中
spring.aop.auto
属性默认是开启的,也就是说只要引入了AOP依赖后,默认已经增加了@EnableAspectJAutoProxy
。
Spring doesn't contains cglib dependency, both cglib and spring cglib has the
Enhancer
class, one is net.sf.cglib.proxy.Enhancer
while the another is org.springframework.cglib.proxy
, what's the difference between them?
Spring shipped with repackaged cglib. You can see actual cglib version in Gradle buildfile. Search for word "cglib" and you find it:
This is called repackaging: instead of using some library as a dependency, a project makes a copy of the dependency as part of their own project and places it in a different package.
The reason for doing this is that a project using Spring might want to use cglib itself. If Spring had a particular version of cglib as a dependency, it would be impossible for the project using Spring to pick a different version. But if Spring uses repackaged cglib which is in a different package, there is no version conflict and the project can use any version of cglib if they like.
debug bean creation
<category name="org.springframework.beans">
<priority value="debug" />
</category>
Looks like
http://thecopsjava.blogspot.com/2016/08/non-compatible-bean-instance-of-type.htmlorg.springframework.beans.factory.support.DefaultListableBeanFactory
logger is the best you can get.java.lang.IllegalStateException: @Bean method SomeConfig.beanCreateMethod called as a bean reference for type [com.example.BeanType] but overridden by non-compatible bean instance of type [com.sun.proxy.$Proxy123]. Overriding bean of same name declared in: com.example.SomeConfig
The problem is that you use spring aop at your application (either directly or indirectly via using spring transactions).
Spring aop is proxy-based. It uses jdk proxies by default.
Jdk proxies can be casted only to the target interfaces. If you try to cast a proxy to the concrete class you get ClassCastException.
Bean named 'timedUserSync' is processed by spring aop and every time you try to use it at the application, you use jdk proxy instead. That produces the problem when the framework tries to use the bean as an object of concrete class.
Solution is to setup cglib usage for your aop infrastructure - set 'proxy-target-class="true''' for all used <aop:config>, <aop:aspectj-autoproxy> or <tx:annotation-driven> elements. Also you must be sure that cglib binaries are available at classpath.
So adding proxyTargetClass = true to the @EnableTransactionManagement annotation solved the problem.
2. If CGLIB is available on the classpath (which comes by default with Spring Boot) and there is no interface to implement a proxy with, CGLIB will be used to make a new object that extends the target bean’s class and acts as a delegate to that original bean.
By default, Spring Boot will use JDK proxies if the bean has an interface and CGLIB proxies if the bean does not. If you try to inject a bean using its concrete class and that bean has an interface, Spring will fail to find the bean with a NoSuchBeanDefinitionException because it will fail to create a JDK proxy using the concrete class.
To get around this limitation and be able to inject concrete classes that have interfaces, you have to tell Spring to always use CGLIB for all beans. This will disable Spring’s use of JDK proxies entirely, making Spring always extend concrete classes even if an interface is injected. To enable this in Spring Boot, just add the following Java property, as seen in the spring-aop-proxy-cglib sample project’s application.properties file:
spring.aop.proxy-target-class=true
http://cliffmeyers.com/blog/2006/12/29/spring-aop-cglib-or-jdk-dynamic-proxies.html
Spring can use two
different techniques for creating proxies at runtime: CGLIB or JDK dynamic proxies.
different techniques for creating proxies at runtime: CGLIB or JDK dynamic proxies.
If the target class implements one or more interfaces, then Spring will create a JDK dynamic proxy that implements every interface. If the target class implements no interfaces, Spring will use CGLIB to create a new class on the fly that is a subclass ("extends") the target class. This leads to one important difference: a JDK dynamic proxy cannot be casted to the original target class because it's simply a dynamic proxy that happens to implement the same interface(s) as the target. This has the effect of "nudging" you to program to interfaces if they're being used in your application's model, since proxies will usually be invoked through those interfaces.
On the other hand, if interfaces are completely absent from your model, Spring will create CGLIB proxies that can be treated more-or-less just like the target class itself. There is also a way to force creation of CGLIB proxies in either scenario that is detailed in the Spring docs right here.
If you're receiving strange ClassCastExceptions when working with your Spring-managed service layer, hopefully this tip will help you!
https://github.com/spring-projects/spring-retry/blob/master/README.md
The
@EnableRetry
annotation creates proxies for @Retryable
beans, and the proxies (so the bean instances in the application) have the Retryable
interface added to them. This is purely a marker interface, but might be useful for other tools looking to apply retry advice (they should usually not bother if the bean already implements Retryable
).@Retryable(maxAttempts=12, backoff=@Backoff(delay=100, maxDelay=500))
@Retryable(exceptionExpression="#{message.contains('this can be retried')}")
@Retryable(exceptionExpression="#{@exceptionChecker.shouldRetry(#root)}", maxAttemptsExpression = "#{@integerFiveBean}", backoff = @Backoff(delayExpression = "#{1}", maxDelayExpression = "#{5}", multiplierExpression = "#{1.1}"))
Expressions can contain property placeholders such as
#{${max.delay}}
or #{@exceptionChecker.${retry.method}(#root)}
exceptionExpression
is evaluated against the thrown exception as the#root
object.maxAttemptsExpression
and the@BackOff
expression attributes are evaluated once, during initialization; there is no root object for the evaluation but they can reference other beans in the context.
@Retryable(maxAttempts=10,value=Exception.class,backoff=@Backoff(delay = 2000,multiplier=2))
http://www.mscharhag.com/spring/spring-retry@EnableRetry
@Retryable
(value = {FooException.
class
, BarException.
class
}, maxAttempts =
5
)
http://stackoverflow.com/questions/38088449/how-can-i-make-spring-retryable-configurable
with the release of Spring-retry version 1.2, it's possible. @Retryable can be configured using SPEL.
@Retryable(value = { SomeException.class,AnotherException.class }, maxAttemptsExpression = "#{@myBean.getMyProperties('retryCount')}", backoff = @Backoff(delayExpression = "#{@myBean.getMyProperties('retryInitalInterval')}"))
AOP
https://www.mkyong.com/spring3/spring-aop-aspectj-annotation-example/
@Aspect
public class LoggingAspect {
@Before("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
public void logBefore(JoinPoint joinPoint) {
@After("execution(* com.mkyong.customer.bo.CustomerBo.addCustomer(..))")
public void logAfter(JoinPoint joinPoint) {
http://stackoverflow.com/questions/2401489/execute-method-on-startup-in-spring
Starting with Spring 4.2+ you can also use the
@EventListener
annotation to observe the ContextRefreshedEvent
(thanks to @bphilipnyc for pointing this out):import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;
@Component
public class StartupHousekeeper {
@EventListener(ContextRefreshedEvent.class)
public void contextRefreshedEvent() {
// do whatever you need here
}
}
@AfterReturning(
pointcut = "execution(* com.mkyong.customer.bo.CustomerBo.addCustomerReturnValue(..))",
returning= "result")
@AfterThrowing(
pointcut = "execution(* com.mkyong.customer.bo.CustomerBo.addCustomerThrowException(..))",
throwing= "error")
public void logAfterThrowing(JoinPoint joinPoint, Throwable error)
@Around("execution(* com.mkyong.customer.bo.CustomerBo.addCustomerAround(..))")
public void logAround(ProceedingJoinPoint joinPoint) throws Throwable {
http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html#context-functionality-eventsContextRefreshedEvent | Published when the ApplicationContext is initialized or refreshed, for example, using the refresh() method on the ConfigurableApplicationContext interface. "Initialized" here means that all beans are loaded, post-processor beans are detected and activated, singletons are pre-instantiated, and the ApplicationContext object is ready for use. As long as the context has not been closed, a refresh can be triggered multiple times, provided that the chosen ApplicationContext actually supports such "hot" refreshes. For example, XmlWebApplicationContext supports hot refreshes, butGenericApplicationContext does not. |
ContextStartedEvent | Published when the ApplicationContext is started, using the start() method on the ConfigurableApplicationContext interface. "Started" here means that all Lifecycle beans receive an explicit start signal. Typically this signal is used to restart beans after an explicit stop, but it may also be used to start components that have not been configured for autostart , for example, components that have not already started on initialization. |
@EventListener public void processBlackListEvent(BlackListEvent event) { // notify appropriate parties via notificationAddress... }
the method signature actually infer which even type it listens to. This also works for nested generics as long as the actual event resolves the generics parameter you would filter on.
If your method should listen to several events or if you want to define it with no parameter at all, the event type(s) can also be specified on the annotation itself:
@EventListener({ContextStartedEvent.class, ContextRefreshedEvent.class}) public void handleContextStart() { }
It is also possible to add additional runtime filtering via the
condition
attribute of the annotation that defines a SpEL
expression that should match to actually invoke the method for a particular event.
For instance, our notifier can be rewritten to be only invoked if the
test
attribute of the event is equal to foo
:@EventListener(condition = "#blEvent.test == 'foo'") public void processBlackListEvent(BlackListEvent blEvent) { // notify appropriate parties via notificationAddress... }http://stackoverflow.com/questions/39846314/contextrefreshedevent-is-invoking-every-time-instead-of-contextstartedevent
ContextStartedEvent is published when you explicitly invoke ConfigurableAppicationContext.start() on the context
ContextRefreshedEvent may be published more than once, and therefore it may be also published before all the beans are initialized
start() is a method of Lifecycle interface which is extended by ConfigurableApplicationContext and explicitly implemented by org.springframework.context.support.AbstractApplicationContext.It is mainly used to support asynchronous processing
Distinction between start and refresh is that:refresh is usually called implicitly during creation of concrete ApplicationContext, so we (developers) are more used to it.start is always explicit So - if you want to get ContextStartedEvent, you should call start() on ApplicationContext.
http://forum.spring.io/forum/spring-projects/container/77684-difference-between-contextstartedevent-contextrefreshedevent
start() is a method of Lifecycle interface which is extended by ConfigurableApplicationContext and explicitly implemented by org.springframework.context.support.AbstractApplic ationContext.
Maybe the most difficult (not obvious) distinction between start and refresh is that:
- refresh is usually called implicitly during creation of concrete ApplicationContext, so we (developers) are more used to it
- start is always explicit
Also - some beans may implement SmartLifecycleInterface - when they say (through that interface) that they should "autoStartup", then they're started during ApplicationContext.refresh() - but this has nothing to do with generation of ContextStartedEvent.
http://stackoverflow.com/questions/17656046/autowired-in-servletcontextlistener
Since it is created by the servlet outside of the Spring container it is not managed by Spring hence @Autowire members is not possible.
If you setup your bean as a managed @Component then Spring will create the instance and the listener wont register with the external servlet.
weatherConfService = applicationContext.getBean(ConfigrationService.class);
http://stackoverflow.com/questions/17676025/how-to-properly-utilize-dependency-injection-within-static-context
If you can use your
init()
method in non-static way then you can do it using SpringBeanAutowiringSupport
helper class:
There is another option: you can use
SpringBeanAutowiringSupport
as a base class for your Production
class. In this case you do not need to call manually SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
. Just add dependencies and go.
@PostConstruct
public void init() {
SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);
}