• Spring(二)


    原教程: https://www.w3cschool.cn/wkspring/

    spring中的事件处理

    如果一个 bean 实现 ApplicationListener,那么每次 ApplicationEvent 被发布到 ApplicationContext 上,那个 bean 会被通知。

    标准事件:


     

    标准事件 激活时机
    ContextRefreshedEvent ApplicationContext 被初始化或刷新时,或调用ConfigurableApplicationContext接口的refresh()
    ContextStartedEvent 调用ConfigurableApplicationContext接口的start()时
    ContextStoppedEvent 调用ConfigurableApplicationContext接口的stop()时
    ContextClosedEvent 调用ConfigurableApplicationContext接口的close()时
    RequestHandledEvent 暂无

    Spring 的事件处理是单线程的

    监听上下文标准事件:

    • 创建实现ApplicationListener接口的事件处理类,并在接口方法onApplicationEvent()中实现接收到事件的逻辑
    • 将事件处理类声明为bean
    • 事件处理类无需其他类继承,当applicationContext发生变化时事件自动激活。

     spring自定义事件

    • class CustomEvent extends ApplicationEvent
    • class CustomEventPublisher implements ApplicationEventPublisherAware
    • class CustomEventHandler implements ApplicationListener<CustomEvent>
    • 在beans.xml中将CustomEventPublisher ,CustomEventHandler声明为bean
    • 当调用ApplicationEventPublisher的publishEvent(CustomEvent)时,自定义事件被激活
     1 // CustomEvent.java
     2 public class CustomEvent extends ApplicationEvent{
     3 
     4     public CustomEvent(Object source) {
     5         super(source);
     6     }
     7     
     8     public String toString() {
     9         return "My Custom Event";
    10     }
    11 
    12 }
    13 
    14 // CustomEventHandler .java
    15 public class CustomEventHandler implements ApplicationListener<CustomEvent> {
    16 
    17     @Override
    18     public void onApplicationEvent(CustomEvent arg0) {
    19         System.err.println(arg0.toString());
    20     }
    21     
    22 }
    23 
    24 // CustomEventPublisher.java
    25 public class CustomEventPublisher implements ApplicationEventPublisherAware{
    26     private ApplicationEventPublisher publisher;
    27 
    28     @Override
    29     public void setApplicationEventPublisher(ApplicationEventPublisher arg0) {
    30         this.publisher = arg0;
    31     }
    32     
    33     public void publish() {
    34         CustomEvent ce = new CustomEvent(this);
    35         publisher.publishEvent(ce);
    36     }
    37 
    38 }
    39 
    40 // MainApp.java
    41 public class MainApp {
    42     public static void main(String[] args) {
    43         ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    44         CustomEventPublisher publisher = (CustomEventPublisher) context.getBean("customEventPublisher");
    45         publisher.publish();
    46         publisher.publish();
    47     }
    48 }
    49 
    50 // beans.xml
    51 <bean id="customEventPublisher" class="com.tutorialspoint.CustomEventPublisher"></bean>
    52 <bean id="CustomEventHandler" class="com.tutorialspoint.CustomEventHandler"></bean>

    spring框架的AOP

    通知描述
    前置通知 在一个方法执行之前,执行通知。
    后置通知 在一个方法执行之后,不考虑其结果,执行通知。
    返回后通知 在一个方法执行之后,只有在方法成功完成时,才能执行通知。
    抛出异常后通知 在一个方法执行之后,只有在方法退出抛出异常时,才能执行通知。
    环绕通知 在建议方法调用之前和之后,执行通知。

    1. spring中基于AOP的xml架构

    重点是beans.xml文件

    • <aop:config>标签
    • <aop:aspect id="" ref="某个bean-id">
    • <aop:pointcut expression="execution(* com.tutorialspoint.*.*(..))" id="pointcut-id">
    • <aop:before method="" pointcut-ref="pointcut-id">
    • <aop:after method="" pointcut-ref="pointcut-id">
    • <aop:after-returning method="" pointcut-ref="pointcut-id" returning="">
    • <aop:after-throwing method="" pointcut-ref="pointcut-id" throwing="" >

    returning与throwing要指定method中返回的对象,拼写要一致

      1 // beans.xml
      2 <?xml version="1.0" encoding="UTF-8"?>
      3 <beans
      4     xmlns="http://www.springframework.org/schema/beans"
      5     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
      6     xmlns:aop="http://www.springframework.org/schema/aop"
      7     xsi:schemaLocation="http://www.springframework.org/schema/beans
      8     http://www.springframework.org/schema/beans/spring-beans-3.0.xsd 
      9     http://www.springframework.org/schema/aop 
     10     http://www.springframework.org/schema/aop/spring-aop-3.0.xsd ">
     11     
     12     <aop:config>
     13         <aop:aspect id="log" ref="logging">
     14             <aop:pointcut expression="execution(* com.tutorialspoint.*.*(..))" id="selectAll"/>
     15             <aop:before method="beforeAdvice" pointcut-ref="selectAll"/>
     16             <aop:after method="afterAdvice" pointcut-ref="selectAll"/>
     17             <aop:after-returning 
     18                 method="afterReturningAdvice" 
     19                 returning="retVal"
     20                 pointcut-ref="selectAll"/>
     21             <aop:after-throwing 
     22                 method="afterThrowingAdvice"
     23                 throwing="excep"
     24                 pointcut-ref="selectAll"/>
     25         </aop:aspect>
     26     </aop:config>
     27     
     28     <bean id="student" class="com.tutorialspoint.Student">
     29         <property name="name" value="Zara"/>
     30         <property name="age" value="11"/>
     31     </bean>
     32     
     33     <bean id="course" class="com.tutorialspoint.Course">
     34         <property name="courseName" value="English"/>
     35         <property name="courseId" value="12"/>
     36     </bean>
     37     
     38     <bean id="logging" class="com.tutorialspoint.Logging"/>
     39 
     40 </beans>
     41 
     42 // Logging.java
     43 public class Logging {
     44     public void beforeAdvice() {
     45         System.out.println("Going to setup student profile.");
     46     }
     47     public void afterAdvice() {
     48         System.out.println("Student profile has been setup.");
     49     }
     50     public void afterReturningAdvice(Object retVal) {
     51         System.out.println("Returning:"+retVal.toString());
     52     }
     53     public void afterThrowingAdvice(IllegalArgumentException excep) {
     54         System.out.println("There has been an exception: "+excep.toString());
     55     }
     56     
     57 }
     58 
     59 // Student.java
     60 public class Student {
     61     private Integer age;
     62     private String name;
     63     public Integer getAge() {
     64         System.out.println("Studetn getAge()   Age : " + age );
     65         return age;
     66     }
     67     public void setAge(Integer age) {
     68         this.age = age;
     69     }
     70     public String getName() {
     71         System.out.println("Student getName()  Name : " + name );
     72         return name;
     73     }
     74     public void setName(String name) {
     75         this.name = name;
     76     }
     77     public void printThrowException() {
     78         System.out.println("Student printThrowException()   Exception raised");
     79         throw new IllegalArgumentException();
     80     }
     81 }
     82 
     83 // Course.java
     84 public class Course {
     85     String courseName;
     86     int courseId;
     87     public String getCourseName() {
     88         System.out.println("Course getCouseName() "+courseName);
     89         return courseName;
     90     }
     91     public void setCourseName(String courseName) {
     92         System.out.println("Course setCourseName() "+courseName);
     93         this.courseName = courseName;
     94     }
     95     public int getCourseId() {
     96         System.out.println("Couse getCourseId() "+courseId);
     97         return courseId;
     98     }
     99     public void setCourseId(int courseId) {
    100         System.out.println("Course setCouseId() "+courseId);
    101         this.courseId = courseId;
    102     }
    103 }
    104 
    105 //MainApp.java
    106 public class MainApp {
    107     public static void main(String[] args) {
    108         ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
    109         Student student = (Student) context.getBean("student");
    110         student.getName();
    111         student.getAge();
    112         
    113         Course course = (Course) context.getBean("course");
    114         course.getCourseName();
    115         course.getCourseId();
            // 出现此异常的原因是setCourseName()返回值是void类型。spring的afterReturningAdvice(object retVal)中的参数是setCourseName()的返回值
    116 course.setCourseName("math"); 会报空指针异常 117 course.setCourseId(15); 118 119 student.printThrowException(); 120 } 121 }
    运行结果:

    Course setCourseName() English
    Course setCouseId() 12
    Going to setup student profile.
    Student getName() Name : Zara
    Student profile has been setup.
    Returning:Zara
    Going to setup student profile.
    Studetn getAge() Age : 11
    Student profile has been setup.
    Returning:11
    Going to setup student profile.
    Course getCouseName() English
    Student profile has been setup.
    Returning:English
    Going to setup student profile.
    Couse getCourseId() 12
    Student profile has been setup.
    Returning:12
    Going to setup student profile.
    Course setCouseId() 15
    Student profile has been setup.
    Exception in thread "main" java.lang.NullPointerException

    其中的Logging类定义了<aop:advice>的method

    <aop:pointcut expression="execution(* com.tutorialspoint.*.*(..))"作用于beans.xml中下student bean之外的bean的所有方法,即student bean和coursebean
    也可以指定
    expression="execution(* com.tutorialspoint.Student.getName(..))"只作用于Student类下的getName()

     2. spring中基于AOP的@AspectJ

    • @Aspect注解Logging类,类中方法注解为Advice方法。注意@Pointcut声明一个函数为切入点,函数名类似于xml方式中切入点的id。
    • 在beans.xml中添加<aop:aspectj-autoproxy/>,而省去了xml方式中<sop:config>的一大坨配置。
      1 // Logging.java
      2 @Aspect
      3 public class Logging {
      4     @Pointcut("execution(* com.tutorialspoint.*.*(..))")
      5     private void selectAll() {
      6         
      7     }
      8     @Before("selectAll()")
      9     public void beforeAdvice() {
     10         System.out.println("Logging beforeAdvice()");
     11     }
     12     @After("selectAll()")
     13     public void afterAdvice() {
     14         System.out.println("Logging afterAdvice()");
     15     }
     16     @AfterReturning(pointcut="selectAll()", returning="retVal")
     17     public void afterReturningAdvice(Object retVal) {
     18         System.out.println("Logging afterReturningAdvice():"+retVal.toString()+"
    ");
     19     }
     20     @AfterThrowing(pointcut="selectAll()", throwing="excep")
     21     public void afterThrowingAdvice(IllegalArgumentException excep) {
     22         System.out.println("Logging afterThrowingAdvice()"+excep.toString());
     23     }
     24     
     25 }
     26 
     27 // Student.java
     28 public class Student {
     29     private Integer age;
     30     private String name;
     31     public Integer getAge() {
     32         System.out.println("Studetn getAge()   Age : " + age );
     33         return age;
     34     }
     35     public int setAge(Integer age) {
     36         System.out.println("Student setAge() "+ age);
     37         this.age = age;
     38         return age;
     39     }
     40     public String getName() {
     41         System.out.println("Student getName()  Name : " + name );
     42         return name;
     43     }
     44     public String setName(String name) {
     45         System.out.println("Student setName() "+name);
     46         this.name = name;
     47         return name;
     48     }
     49     public void printThrowException() {
     50         System.out.println("Student printThrowException()   Exception raised");
     51         throw new IllegalArgumentException();
     52     }
     53 }
     54 
     55 // Course.java
     56 public class Course {
     57     String courseName;
     58     int courseId;
     59     public String getCourseName() {
     60         System.out.println("Course getCouseName() "+courseName);
     61         return courseName;
     62     }
     63     public String setCourseName(String courseName) {
     64         System.out.println("Course setCourseName() "+courseName);
     65         this.courseName = courseName;
     66         return courseName;
     67     }
     68     public int getCourseId() {
     69         System.out.println("Couse getCourseId() "+courseId);
     70         return courseId;
     71     }
     72     public int setCourseId(int courseId) {
     73         System.out.println("Course setCouseId() "+courseId);
     74         this.courseId = courseId;
     75         return courseId;
     76     }
     77 }
     78 
     79 //MainApp.java
     80 public class MainApp {
     81     public static void main(String[] args) {
     82         ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");
     83         Student student = (Student) context.getBean("student");
     84         student.getName();
     85         student.getAge();
     86         student.setAge(5);
     87         student.setName("zhangfan");
     88         
     89         Course course = (Course) context.getBean("course");
     90         course.getCourseName();
     91         course.getCourseId();
     92         course.setCourseName("math");
     93         course.setCourseId(15);
     94         
     95         student.printThrowException();
     96     }
     97 }
     98 
     99 // beans.xml
    100     <aop:aspectj-autoproxy/>
    101     
    102     <bean id="student" class="com.tutorialspoint.Student">
    103         <property name="name" value="Zara"/>
    104         <property name="age" value="11"/>
    105     </bean>
    106     
    107     <bean id="course" class="com.tutorialspoint.Course">
    108         <property name="courseName" value="English"/>
    109         <property name="courseId" value="12"/>
    110     </bean>
    111     
    112     <bean id="logging" class="com.tutorialspoint.Logging"/>
    运行结果:
    Student setName() Zara
    Student setAge() 11
    Course setCourseName() English
    Course setCouseId() 12
    Logging beforeAdvice()
    Student getName()  Name : Zara
    Logging afterAdvice()
    Logging afterReturningAdvice():Zara
    
    Logging beforeAdvice()
    Studetn getAge()   Age : 11
    Logging afterAdvice()
    Logging afterReturningAdvice():11
    
    Logging beforeAdvice()
    Student setAge() 5
    Logging afterAdvice()
    Logging afterReturningAdvice():5
    
    Logging beforeAdvice()
    Student setName() zhangfan
    Logging afterAdvice()
    Logging afterReturningAdvice():zhangfan
    
    Logging beforeAdvice()
    Course getCouseName() English
    Logging afterAdvice()
    Logging afterReturningAdvice():English
    
    Logging beforeAdvice()
    Couse getCourseId() 12
    Logging afterAdvice()
    Logging afterReturningAdvice():12
    
    Logging beforeAdvice()
    Course setCourseName() math
    Logging afterAdvice()
    Logging afterReturningAdvice():math
    
    Logging beforeAdvice()
    Course setCouseId() 15
    Logging afterAdvice()
    Logging afterReturningAdvice():15
    
    Logging beforeAdvice()
    Student printThrowException()   Exception raised
    Logging afterAdvice()
    Logging afterThrowingAdvice()java.lang.IllegalArgumentException

    小结:

    • xml方式:切入点及Advice方法的指定在beans.xml的<aop:config>元素中;
    • @AspectJ方式:切入点及Advice方法的指定在类中;beans.xml中添加<aop:aspectj-autoproxy/>启动AspectJ方式。
    • afterReturningAdvice(object retVal)要求切入点expression中所有的方法都要有返回值,不能是void,否则报参数错误异常。
    • afterThrowingAdvice()不要求切入点expression中所有方法的返回值可以为void。
    • 五种通知类型,分别代表着在pointcut expression指定方法的前后要调用Advice方法
  • 相关阅读:
    如何同步共享同一个list
    Java多线程生产者消费者模式(一)之两个线程交替执行
    Java多线程之如何在线程间共享数据
    Java多线程(四)实现多线程的三种方法之JUC的Callable接口
    Java线程的6种状态
    Java lambda表达式的进化论
    Java内部类
    Java多线程(五)锁机制之synchronized 同步方法和同步块
    Java装饰者模式
    Java多线程(三)实现多线程的三种方法之Runnable接口
  • 原文地址:https://www.cnblogs.com/yfs123456/p/10667885.html
Copyright © 2020-2023  润新知