Interface callback
The listener essentially uses the callback mechanism to execute some of our own code before or after an action occurs. In Java language, interfaces can be used.
Implement a listener case
For convenience, directly define in the spring environment: take the work as an example to define the listener at the beginning (or at the end) of the work.
1. Define the interface for the callback
package com.yawn.demo.listener;/** * @author Created by yawn on 2018-01-21 13:53 */public interface WorkListener { void onStart(String name);}2. Define the action
package com.yawn.demo.service;import com.yawn.demo.listener.WorkListener;/** * @author Created by yawn on 2018-01-21 13:39 */@Servicepublic class MyService { @Resource private PersonService personService; private WorkListener listener; public void setWorkListener(WorkListener workListener) { this.listener = workListener; } public void work(String name) { listener.onStart(name); personService.work(); }}Action work is a specific method. At the appropriate time of the work() method, the interface defined above is called. In addition, in this action definition class, it is necessary to improve the method of setting the listener.
3. Listen to test
@RunWith(SpringRunner.class)@SpringBootTestpublic class DemoSpringAnnotationApplicationTests { @Resource private MyService myService; @Test public void test1() { // Interface settings listener myService.setWorkListener(new WorkListener() { @Override public void onStart(String name) { System.out.println("Start work for " + name + " !"); } });// // Lambda expression settings listener// myService.setWorkListener(name -> System.out.println("Start work for " + name + " !")); // Work myService.work("boss"); } @Test public void test2() { // Inherit the implementation class to set the listener myService.setWorkListener(new myWorkListener()); // Work myService.work("boss"); } class myWorkListener extends WorkListenerAdaptor { @Override public void onStart(String name) { System.out.println("Start work for " + name + " !"); } }}Using the above two methods to test, the results were obtained:
Start work for boss !working hard ...
This shows that before the action work occurs, the listening code we wrote in the test class is executed to achieve the purpose of class listening.
Implementing the listener with annotations
In the above code, calling the setWorkListener(WorkListener listener) method is generally called setting (register) listener, which is to set the listening code you wrote as an action listener. However, every time you register a listener, you generally need to write a class to implement a defined interface or inherit the class that implements the interface, and then rewrite the interface definition method. Therefore, smart programmers wanted to simplify this process, so they came up with a way to use annotations. Using annotations, write the listening code segment in a method, and use annotation to mark this method.
Indeed, use has become simple, but implementation is not necessarily true.
1. Define an annotation
package com.yawn.demo.anno;@Target(ElementType.METHOD)@Retention(RetentionPolicy.RUNTIME)public @interface WorkListener {}2. Analytical annotations
package com.yawn.demo.anno;import com.yawn.demo.service.MyService;import org.springframework.beans.BeansException;import org.springframework.beans.factory.InitializingBean;import org.springframework.context.ApplicationContext;import org.springframework.context.ApplicationContextAware;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.lang.annotation.Annotation;import java.lang.reflect.Method;import java.util.LinkedHashMap;import java.util.Map;/** * @author Created by yawn on 2018-01-21 14:46 */@Componentpublic class WorkListenerParser implements ApplicationContextAware, InitializingBean { @Resource private MyService myService; private ApplicationContext applicationContext; @Override public void afterPropertiesSet() throws Exception { Map<String, Object> listenerBeans = getExpectListenerBeans(Controller.class, RestController.class, Service.class, Component.class); for (Object listener : listenerBeans.values()) { for (Method method : listener.getClass().getDeclaredMethods()) { if (!method.isAnnotationPresent(WorkListener.class)) { continue; } myService.setWorkListener(name -> { try { method.invoke(listener, name); } catch (Exception e) { e.printStackTrace(); } }); } } } } /** * Find beans that are possible to use annotations * @param annotationTypes Class-level annotation type that needs to be scanned* @return Map of the beans scanned */ private Map<String, Object> getExpectListenerBeans(Class<? extends Annotation>... annotationTypes) { Map<String, Object> listenerBeans = new LinkedHashMap<>(); for (Class<? extends Annotation> annotationType : annotationTypes) { Map<String, Object> annotatedBeansMap = applicationContext.getBeansWithAnnotation(annotationType); listenerBeans.putAll(annotatedBeansMap); } return listenerBeans; } @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { this.applicationContext = applicationContext; }}During the analysis of the annotation, set up the listener.
In the parsing class, the interface ApplicationContextAware is implemented. In order to obtain the reference to ApplicationContext in the class, it is used to obtain the bean in the IOC container; and the implementation of the interface InitializingBean is implemented to execute the code of parsing annotations and setting the listener at a suitable time. If you do not do this, you can call the parsed and set code when the CommandLineRunner is executed, and the ApplicationContext can also be automatically injected.
3. Test
After executing the above code, the listener is already set up and can be tested.
package com.yawn.demo.controller;import com.yawn.demo.anno.WorkListener;import com.yawn.demo.service.MyService;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;/** * @author Created by yawn on 2018-01-21 13:28 */@RestControllerpublic class TestController { @Resource private MyService myService; @GetMapping("/work") public Object work() { myService.work("boss"); return "done"; } @WorkListener public void listen(String name) { System.out.println("Start work for " + name + " !"); }}Write a monitoring method, the parameter type and number are the same as the interface, and then add custom annotations. After the environment is started, the listener is already set.
Then call the work() method of myService through url and you can see the result:
Start work for boss !working hard ...
The listening method has been called. In the next development, you can use this annotation to register the listener.
The above is all the content of this article. I hope it will be helpful to everyone's learning and I hope everyone will support Wulin.com more.