AOP(Aspect Oriented Programming),即面向切面编程,可以说是OOP(Object Oriented Programming,面向对象编程)的补充和完善。AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常发生在核心关注点的多处,而各处都基本相似。比如权限认证、日志、事务处理。Aop 的作用在于分离系统中的各种关注点,将核心关注点和横切关注点分离开来。正如Avanade公司的高级方案构架师Adam Magee所说,AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”
面向切面编程:所谓”切面编程”,简单说就是我们在开发中将重复代码抽取出来形成一个类, 这个类就叫做切面类。然后当我们的代码执行的时候 ,动态的将我们抽取出来的代码,植入到程序运行中的这个编程方法就叫做面向切面的编程。
面向切面编程的优点:与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块之间的耦合度,并有利于未来的可操作性和可维护性。
实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以代理的方式取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。
注:在Spring中我们要使用AOP来进行编程的话那么我们的代理对象不需要写了,是由我们的Spring自动生成的。
实现步骤:
1、注释的方式实现:
(1)、在我们的配置文件中添加我们的aop的注解扫描
bean.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" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!--添加我们的ioc/di的注解扫描 --> <context:component-scan base-package="com.wc.aop4"></context:component-scan> <!--添加我们的aop的注解扫描--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
(2)、将我们的aop,userDao添加到IOC容器 并且将aop制定为切面类
UserDao.java(实现了IUserDao接口)
@Repository public class UserDao implements IUserDao{ @Override public void test() { System.out.println("这是test方法"); } }
Aop.java
@Component //放入ioc容器 @Scope("singleton")//设置为单例模式 @Aspect//设置为切面类 public class Aop { /** * 切入点表达式 * (execution (:语法规则就是这样写的 * *:代表的是返回值的数据类型是任意的 * com.qf.aop_04.UserDao:代表的是定位到了类上面 * *:任意的方法 * (..):表示的这些方法的参数是任意类型 */ @Pointcut("(execution (* com.wc.aop4.UserDao.*(..)))") public void ptMethod() {} //Before("") 这里面的这个值是要引入我们的切入点表达式,切入点前执行 @Before("ptMethod()") public void start() { System.out.println("这是执行前"); } //@After("")切入点后执行 @After("ptMethod()") public void end() { System.out.println("这是执行后"); } /** * 抛出异常的时候植入的代码 */ @AfterThrowing("ptMethod()") public void throwExcetion(){ System.out.println("抛出异常的时候植入代码..."); } /** * 返回值的时候植入的代码 */ @AfterReturning("ptMethod()") public void returnValue(){ System.out.println("返回值的时候植入代码...."); } /** * 环绕的时候植入的代码 * @throws Throwable */ @Around("ptMethod()") public void around(ProceedingJoinPoint point) throws Throwable{ System.out.println("环绕前...."); point.proceed(); System.out.println("环绕后...."); } }
Test.java
public class Test { public static void main(String[] args) { ClassPathXmlApplicationContext context=new ClassPathXmlApplicationContext("com/wc/aop4/bean.xml"); IUserDao userDao=(IUserDao) context.getBean("userDao"); userDao.test(); context.close(); }
2、配置方式实现:
java类中将所有的注解全部去掉
bean.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" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <!-- 把dao放入ioc容器 --> <bean id="userDao" class="com.wc.aop5.UserDao"></bean> <!-- 配置模式实现aop编程 --> <!-- 把AOP放入ioc容器 --> <bean id="aop" class="com.wc.aop5.Aop"></bean> <!-- 配置aop --> <aop:config> <!-- 配置切入点表达式 --> <aop:pointcut expression="(execution (* com.wc.aop5.UserDao.*(..)))" id="pt"/> <!-- 配置切面类 ref:引用切面类在IOC容器中 id:整了个名字--> <aop:aspect ref="aop" id="aop"> <!--aop:before 表示的是在切入点执行之前来植入下面的代码 pointcut-ref:这个表示的是引用我们的切入点的表达式--> <aop:before method="startTransaction" pointcut-ref="pt"/> <aop:after method="stopTransaction" pointcut-ref="pt"/> <aop:after-returning method="returnValue" pointcut-ref="pt"/> <aop:after-throwing method="throwExcetion" pointcut-ref="pt"/> <aop:around method="around" pointcut-ref="pt"/> </aop:aspect> </aop:config> </beans>