十、AOP切面编程

一、原理

  AOP(Aspect Oriented Programming)面向切面编程,是对所有对象或者是一类对象编程,核心是在不增加代码的基础上,还增加新的功能

  汇编语言(伪机器指令)--面向机器

  c语言(系统软件)--面向过程

  java--面向对象

  aop--面向切面

  aop需要配置代理对象,被代理对象,通知

  被代理对象,指的是要被切入编辑处理的类,比如要在A类的某一个函数执行前都打一句hello world,那么A类就是被代理对象,代理对象一般继承某个代理接口。

  通知,通知说明了要对被代理对象做怎样的处理,通知分为前置(在目标方法调用前)、后置(在目标方法调用后)、异常(当目标方法抛出异常时调用)、最终()、环绕(拦截对目标方法调用)通知五类,只要实现相应的接口

  代理对象,是固定的类,org.springframework.aop.framework.ProxyFactoryBean,只需配置不需编写,但需要配置代理哪些接口,用哪个通知,被代理对象是谁(把通知织入到代理对象 )

  

二、前置通知案例

  1.建立代理接口

package com.beans;

public interface PeopleInter {
    public void sayHello();
}

  2.建立被代理对象

package com.beans;

public class People implements PeopleInter {
    private String name;
    
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public void sayHello() {
        // TODO Auto-generated method stub
        System.out.println("Hello "+name);
    }

}

  3.建立前置通知类

package com.aop;

import java.lang.reflect.Method;
import java.util.Date;

import org.springframework.aop.MethodBeforeAdvice;

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

    //前置通知
    @Override
    public void before(Method arg0, Object[] arg1, Object arg2)
            throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("记录日志,当前时间为"+new Date());
    }

}

  4.配置xml

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
    <!-- 配置被代理的对象 -->
    <bean id="people" class="com.beans.People">
        <property name="name" value="蔡文姬"></property>
    </bean>
    
    <!-- 配置前置通知 -->
    <bean id="myMethodBeforeAdvice" class="com.aop.MyMethodBeforeAdvice"></bean>
    
    <!-- 配置代理对象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.beans.PeopleInter</value>
            </list>
        </property>
        
        <!-- 把通知织入到代理对象 -->
        <property name="interceptorNames">
            <!-- 相当于把myMethodBeforeAdvice前置通知和代理对象关联 -->
            <value>myMethodBeforeAdvice</value>
        </property>
        
        <property name="target" ref="people"></property>
    </bean>
    
</beans>

  5.注意getBean的时候是获取代理对象

package com.test;


import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.beans.People;
import com.beans.PeopleInter;

public class Test {
    public static void main(String[] args) {
        ApplicationContext ac= new ClassPathXmlApplicationContext("applicationContext.xml");
        PeopleInter p=(PeopleInter) ac.getBean("proxyFactoryBean");
        p.sayHello();
    }
}

  6.运行触发前置通知,打出

记录日志,当前时间为Sun Jan 07 15:07:11 CST 2018
Hello 蔡文姬

三、后置通知

package com.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class MyAfterReturningAdvice implements AfterReturningAdvice {

    @Override
    public void afterReturning(Object arg0, Method arg1, Object[] arg2,
            Object arg3) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println(arg1.getName()+"函数执行完毕!");
    }

}
<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
    
    <!-- 配置被代理的对象 -->
    <bean id="people" class="com.beans.People">
        <property name="name" value="蔡文姬"></property>
    </bean>
    
    <!-- 配置前置通知 -->
    <bean id="myMethodBeforeAdvice" class="com.aop.MyMethodBeforeAdvice"></bean>
    <!-- 配置后置通知 -->
    <bean id="myAfterReturningAdvice" class="com.aop.MyAfterReturningAdvice"></bean>
    
    <!-- 配置代理对象 -->
    <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
        <!-- 代理接口集 -->
        <property name="proxyInterfaces">
            <list>
                <value>com.beans.PeopleInter</value>
            </list>
        </property>
        
        <!-- 把通知织入到代理对象 -->
        <property name="interceptorNames">
            <!-- 相当于把通知和代理对象关联,多个通知需要用list -->
            <list>
                <value>myMethodBeforeAdvice</value>
                <value>myAfterReturningAdvice</value>
            </list>
        </property>
        
        <property name="target" ref="people"></property>
    </bean>
    
</beans>

四、环绕通知

public class MyMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation arg0) throws Throwable {
        // TODO Auto-generated method stub
        System.out.println("调用方法前...");
        Object proceed = arg0.proceed();
        System.out.println("调用方法后...");
        return proceed;
    }

}
原文地址:https://www.cnblogs.com/myz666/p/8214822.html