一、原理
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; } }