AOP简介:java
面向切面的编程(也叫面向方面编程):Aspect Oriented Programming(AOP),是软件开发中的一个热点,也是 Spring框架中的一个重要内容。利用AOP能够对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度下降,提升程序的可重用性,AOP是OOP编程的延续。spring
与OOP的区别:express
面向对象编程主要用于为同一对象层次的公用行为建模。它的弱点是将公共行为应用于多个无关对象模型之间。而这偏偏是面向方面编程适合的地方。有了 AOP,咱们能够定义交叉的关系,并将这些关系应用于跨模块的、彼此不一样的对象模型。AOP 同时还可让咱们层次化功能性而不是嵌入功能性,从而使得代码有更好的可读性和易于维护。它会和面向对象编程合做得很好。编程
举个例子:app
学生的service类框架
public class StudentServiceImpl implements IStudentService{ @Override public void addStudent(String name) { // TODO Auto-generated method stub System.out.println("姓名:"+name); } }
如今有个需求:在添加方法的逻辑中,添加以前输出日志,添加完成以后输出添加成功日志,最简单的方法是:ide
public class StudentServiceImpl implements IStudentService{ @Override public void addStudent(String name) { // TODO Auto-generated method stub //输出日志逻辑代码 System.out.println("姓名:"+name); //添加成功日志代码 } }
如今咱们又有别的Service 类也须要一样的需求。须要修改的类足足有100个(开个玩笑) ,不可能一个个去修改,Service类,并且俩个输出日志的代码在其余Service类中是同样的,若是一直复制粘贴对代码没有作到可复用性。测试
这个时候AOP就派上用处了。spa
以Spring框架中为例:代理
spring.xml中AOP配置:
<?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:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.0.xsd"> <context:component-scan base-package="com.younchen.*" /> <bean id="StudentImpl" class="com.younchen.aop.StudentImpl" /> <bean id="DaliyLog" class="com.younchen.aop.DaliyLog"/> <bean id="Log" class="com.younchen.aop.Log"/> <aop:config> <!-- expression 括号 第一个 星号表示 全部返回值类型,第二个星号表示全部类,第三个星号表示全部的方法,括号俩点表示方法参数 --> <aop:pointcut expression="execution(* com.younchen.aop.*.*(..))" id="target" /> <aop:aspect id="Logger" ref="Log"> <aop:before method="beforeAdd" pointcut-ref="target" /> <aop:after method="afterAdd" pointcut-ref="target" /> </aop:aspect> </aop:config> </beans>
在config 标签中的第一个标签pointcut是切入点, expression是表达式, 看下括号中的第一个*号,意思是针对于全部的返回类型 ,紧接着是类所在的包名,以后的俩个星号分别表明类名和方法名 ,后面的括号中俩个点表明全部的参数。该标签的做用是声明在执行com.younchen.aop这个包下的全部类的全部方法时执行咱们要切入的方法 。
aspect标签是切面也就是咱们要切入的方法 ref指定咱们的切入方法的类,该标签中的子标签 before method的做用是expression表达式中指定的类的方法执行前执行, after method是以后执行。 pointcut-ref 是指定切入点,除了引用的切入点(表达式指定的范围外) 该切面是不执行的。
未给出的完整代码:
Log类:
package com.younchen.aop; public class Log { public void beforeAdd(){ System.out.println("准备添加数据"); } public void afterAdd(){ System.out.println("添加完成"); } }
SpringUtil类:
public class SpringUtil { private static ApplicationContext context = null; public static ApplicationContext getApplicationContext() { if (context == null) { context = new ClassPathXmlApplicationContext("spring.xml"); } return context; } public static ApplicationContext getApplicationContext(String path) { return new ClassPathXmlApplicationContext(path); } public static ApplicationContext getAnnotationConfigApplicationContext(String basePackages) { return new AnnotationConfigApplicationContext(basePackages); } }
其余service类:
public class DaliyLog { public void addLog(){ System.out.println("添加每日日志"); } }
测试类:
public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub ApplicationContext applicationContext=(ApplicationContext) SpringUtil.getApplicationContext("springaop.xml"); IStudent studentService=(IStudent) applicationContext.getBean("StudentImpl"); DaliyLog daliyLog=(DaliyLog) applicationContext.getBean("DaliyLog"); studentService.addStudent("麦克米兰"); System.out.println("-----------------------------------------------------------"); daliyLog.addLog(); } }
执行结果:
准备添加数据 姓名:麦克米兰 添加完成 ----------------------------------------------------------- 准备添加数据 添加每日日志 添加完成
以上是简单一个例子,AOP的原理实际上是动态代理。 切面是被动态代理的类, 在被动态代理时,产生一个新的类,在这个类中除了执行被代理的方法外,还注入了切面的方法。
欢迎指正。