Spring AOP

什么是面向切面编程?


系统逻辑定义为切面,使业务逻辑不需要关注我们的系统逻辑的实现,由切面来负责系统逻辑的具体实现




Spring AOP 术语

> 通知 (Advice)

    通知定义了切面是什么,以及什么时候使用切面。

  • 前置通知 (Befor) : 目标方法调用前调用通知
  • 后置通知 (After) :  目标方法调用后调用通知
  • 返回通知 (After-returning) : 目标方法返回成功后调用通知
  • 环绕通知 (Around) : 目标方法调用前与调用后都会调用通知
  • 异常通知 (After-throwing) :  目标方法抛出异常后调用通知

> 连接点 (Join point)

    链接点是指在应用执行过程中能够插入切面的一个具体的点。

> 切点 (Poincut)

    切点定义了何处使用通知。定义匹配通知所要织入的一个或多个连接点。通常使用明确的类和方法名,或是 利用正则表达式配。

> 切面 (Aspect)

    切面就是通知和切点的结合

> 织入 (Weaving)

    把切面应用到目标对象,并创建新的代理对象的过程。

Spring 支持的 AOP

1.基于代理方式切面

2.纯POJO切面  -->常用

3.注解Aspect切面  -->常用

4. 注入式AspectJ切面

Spring 基于代理方式

MethodBeforAdvice 前置拦截器       

 befor (Method method, Object[] args, Object target)  throws  Throwable {                

    method : 被代理的方法名               

    args : 被代理方法的参数数组                

    target : 具体被代理的对象        

AfterReturningAdvice 后置拦截器       

 afterReturning (Method method, Object[] args, Object target)  throws  Throwable {           

     returnValue 被代理方法的返回值            

    method 被代理的方法名              

    args : 被代理方法的参数数组                

    target : 具体被代理的对象        

MethodInterceptor 环绕拦截器       

 invoke (MethodInvacation invacation)  throws  Throwable {           

    invacation.proceed() 执行被代理的具体方法            

    invacation.getMethod() 被代理的方法名               

    invacation.getArguments() : 被代理方法的参数数组                

    invacation.getThis() : 具体被代理的对象        

applicationContext配置信息

<?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:c="http://www.springframework.org/schema/c"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:p="http://www.springframework.org/schema/p"
	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-4.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">

	<bean id="Student" class="com.prosay.entity.Student">
		<property name="age" value="18"></property>
		<property name="name" value="刘亿"></property>
	</bean>
	<bean id="StudentService" class="com.prosay.service.StudentService">
		<property name="student" ref="Student"></property>
	</bean>
	<bean id="LogAspect" class="com.prosay.aspect.LogAspect"></bean>
	<!-- 切点  -->
	<bean id="StudentAspect" class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- 代理的接口 -->
		<property name="interfaces">
			<value>com.prosay.service.impl.StudentServiceImpl</value>
		</property>
		<!-- 实现类 -->
		<property name="target" ref="StudentService"></property>
		<!-- 通知 -->
		<property name="interceptorNames">
			<list>
				<value>LogAspect</value>
			</list>
		</property>
	</bean>
</beans>


LogAspect类


package com.prosay.aspect;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;

public class LogAspect implements MethodBeforeAdvice,AfterReturningAdvice,MethodInterceptor{
        //前置通知
	@Override
	public void before(Method method, Object[] args, Object target) throws Throwable {
		System.out.println("开始");
	}
        //后置通知
	@Override
	public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
		System.out.println("关闭");
	}
        //环绕通知
	@Override
	public Object invoke(MethodInvocation invocation) throws Throwable {
		System.out.println("1");
		invocation.proceed();
		System.out.println("2");
		return null;
	}

}


Demo类


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

import com.prosay.service.impl.StudentServiceImpl;

public class Demo01 {
	public static void main(String[] args) {
		AbstractApplicationContext app = new ClassPathXmlApplicationContext("applicationContext.xml");
                //这里使用的是代理对象 
		StudentServiceImpl ssi = (StudentServiceImpl) app.getBean("StudentAspect");
		ssi.insertStudent();
	}
}


纯POJO代理


通知配置:            

    <aop:pointcut /> :  配置一个切点           

    <aop:befor /> :  配置前置拦截器           

    <aop:after /> :  配置后置拦截器          

    <aop:after-throwing />  配置后置异常拦截器            

    <aop:after-returning /> :  配置后置正常拦截器          

    <aop:around />  配置环绕拦截器   

     

切面参数获取:            

    ProceedingJoinPoint.proceed() : 执行被代理的具体方法         

    JoinPoint.getSignature().getName() : 被代理的方法名           

    JoinPoint.getArgs() : 被代理方法的参数数组           

    JoinPoint.getTarget : 具体被代理的对象


applicationContext配置文件


<?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:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<bean id="Student" class="com.pojo.entity.Student">
		<property name="age" value="18"></property>
		<property name="name" value="刘亿"></property>
	</bean>
	<bean id="StudentService" class="com.pojo.service.StudentService">
                <!-- 通过构造函数注入 -->
		<constructor-arg ref="Student"></constructor-arg>
	</bean>
        <!-- 代理类 -->
	<bean id="LogAspect" class="com.pojo.aspect.LogAspect"></bean>
	<!-- aop配置 -->
	<aop:config>
		<!-- 切面 -->
		<aop:aspect ref="LogAspect">
			<!-- 切点   ** 什么都行 ..参数 -->
			<aop:pointcut id="Mypointcut" expression="execution(** com.pojo.service.StudentService.insertStudent(..))"/>
			<!-- 通知方式 -->
			<aop:after method="after" pointcut-ref="Mypointcut"/>
			<aop:before method="before" pointcut-ref="Mypointcut"/>
			<aop:around method="around" pointcut-ref="Mypointcut"/>
		</aop:aspect>
	</aop:config>
</beans>


LogAspect类


package com.pojo.aspect;

import org.aspectj.lang.ProceedingJoinPoint;

public class LogAspect {
	public void before() {
		System.out.println("开始切面");
	}
	public void after() {
		System.out.println("结束切面");
	}
	public void around(ProceedingJoinPoint point) {
		before();
		try {
			point.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		after();
	}
}

Test类


package com.pojo;

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

import com.pojo.service.StudentService;
import com.pojo.service.impl.StudentServiceImpl;

public class Test {
	public static void main(String[] args) {
		AbstractApplicationContext app = new ClassPathXmlApplicationContext("com\\pojo\\applicationContext.xml");
		//1.使用配置中的名字 StudentService.class会报错 
		//2.StudentServiceImpl 使用接口去接收 生成的是代理对象
		StudentServiceImpl ss = (StudentServiceImpl) app.getBean("StudentService");
		ss.insertStudent();
	}
}



Spring 注解AOP


通知配置:            

    @Pointcut : 切点配置            

    @Befor : 前置拦截器注解            

    @After : 后置拦截器注解            

    @AfterThrowing : 后置异常拦截器注解           

    @AfterReturning : 后置正常拦截器注解           

    @Around : 环绕拦截器注解


applicationContext配置文件


<?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:c="http://www.springframework.org/schema/c"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:p="http://www.springframework.org/schema/p"
	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-4.1.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd">
	<context:component-scan base-package="com.annotation"></context:component-scan>
</beans>

LogAspect类


package com.annotation;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
@Component
@Aspect
//启动代理
@EnableAspectJAutoProxy
public class LogAspect {
	//这种写法简单

	@Pointcut("execution(** com.annotation.StudentService.insertStudent(..))")
	public void point() {}
	
	@Before("point()")
	public void before() {
		System.out.println("开始切面");
	}
	@After("point()")
	public void after() {
		System.out.println("结束切面");
	}
	@Around("point()")
	public void around(ProceedingJoinPoint point) {
		before();
		try {
			point.proceed();
		} catch (Throwable e) {
			e.printStackTrace();
		}
		after();
	}
} 

获得参数和使用

@Pointcut("execution(** com.prosay.aop.aspectj.Computer.work(..)) && args(arg)")

@Around("aopDemo(arg)")
 public void aroundMethod(ProceedingJoinPoint proc,Person arg){}


Test类


package com.annotation;

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


public class Test {
	public static void main(String[] args) {
		AbstractApplicationContext app = new ClassPathXmlApplicationContext("com\\annotation\\applicationContext.xml");
		//1.使用配置中的名字 StudentService.class会报错 
		//2.StudentServiceImpl 使用接口去接收 生成的是代理对象
		//3.动态代理的名字首字母小写
		StudentServiceImpl ss = (StudentServiceImpl) app.getBean("studentService");
		ss.insertStudent();
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值