AOP(Aspect Oriented Programming),面向切面编程,AOP基于IoC基础,是对OOP(Object-Oriented Programing,面向对象编程)的补充和完善。
是对所有对象或者是一类对象编程,核心是( 在不增加代码的基础上,还增加新功能 )
汇编(伪机器指令 mov jump) 面向机器
c语言(面向过程 底层开发,按语句顺序执行)->系统软件(操作系统,数据库, 杀毒软件,防火墙,驱动..)[开辟地址、指针、关闭地址]
java(面向对象 出现了类/对象 可以调用对象方法执行)
spring(面向切面 对一批类、对象 执行操作)
OOP允许你定义从上到下的关系,但并不适合定义从左到右的关系。例如fun()这个功能,这种散布在各个类中又无关(耦合)的代码称为横切(cross-cutting)代码,在OOP设计中,它导致了大量代码的重复,而不利于各个模块的重用。
使用“横切”技术,AOP把系统分为两个部分:核心关注点(Core business concerns 核心业务逻辑)和横切关注点(Crosscutting enterprise concerns 通用(业务支撑)逻辑 比如权限管理、日志、事务处理)。Aop 的作用将核心关注点和横切关注点分离开来。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
通知(Advice) :是一个接口,可以把业务支撑功能放在这个类中,采用动态代理技术,添加到对象的业务逻辑功能中,通知5类:
前置通知Before org.springframework.aop.MethodBeforeAdvice 在目标方法执行前 调用
后置通知After org.springframework.aop.AfterRetruingAdvice 在目标方法执行后 调用
环绕通知Around org.springframework.aop.MethodInterceptor 在目标方法执行前后 调用
异常通知Throws org.springframework.aop.ThrowsAdvice 当目标方法抛出异常时 调用
引入通知Introduction org.springframework.aop.IntroductionInterceptor 在目标类中添加新方法和属性
下面编写一个前置通知 来熟悉如何使用:
设计:
public interface Demo1 {
public void say();
}
public class DemoA implements Demo1 {
private String name ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public void say() {
System.out.println("i'm a :"+name );
}
}
public class MyMethodBeforeAdvice implements MethodBeforeAdvice {
/*
* 一定要实现通知接口
* method:目标方法
* args:目标方法参数
* target:目标对象
*/
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("前置通知:"+method.getName());
}
}
配置beans.xml 注意:全域、ref、value:
<?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:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"> <!-- 配置目标对象 --> <bean id="demoa" class="org.nickfover.test.DemoA"> <property name="name" value="skx"></property> </bean> <bean id="demob" class="org.nickfover.test.DemoB"> <property name="name" value="rrr"></property> </bean> <!-- 配置通知 --> <bean id="myMethodBeforeAdvice" class="org.nickfover.test.MyMethodBeforeAdvice"></bean> <!-- 配置代理 ,添加目标接口集、目标对象、织入通知--> <bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean"> <!-- 在代理对象中配置需要代理的接口集,属性为proxyInterfaces,要写全域 --> <property name="proxyInterfaces"> <list> <value>org.nickfover.test.Demo1</value> </list> </property> <!--代理的目标对象,ref上面的bean --> <!-- property name="target" ref="demoa"/ --> <property name="target" ref="demob"/> <!-- 通知,注意这里的value是引用上面的bean --> <property name="interceptorNames"> <value>myMethodBeforeAdvice</value> </property> </bean> </beans>测试:
public static void main(String[] args) throws Exception {
ApplicationContext ac = new ClassPathXmlApplicationContext("org/nickfover/test/beans.xml");
// DemoA a =(DemoA) ac.getBean("demoa");
// a.say();
//一定要用接口转义
Demo1 a =(Demo1) ac.getBean("proxyFactoryBean");
a.say();
}
输出:
前置通知:say
i'm b:rrr
在aop实现中,使用的核心技术是动态代理,在28章中,动态代理需要实现InvocationHandler接口,在创建代理类的时候需要引用Proxy的newProxyInstance()方法;这里的"proxyFactoryBean"与new ProxyImpl1().createProxy(new Impl1());是一样的作用;
##################################################################################################################