AOP(Aspect-Oriented Programming)面向切面编程

将分散在各个方法中的重复代码提取出来,在程序编译或运行时,再提取代码应用到需要执行的地方。

一个AOP程序(基于代理类,配置麻烦)

  1. 创建目标类,待增强的类。
//接口
public interface UserDao {
	public void addUser();
	public void deleteUser();
}

import org.springframework.stereotype.Repository;
// 目标类
@Repository("userDao")
public class UserDaoImpl implements UserDao {
	public void addUser() {
//		int i = 10/0;
		System.out.println("添加用户");
	}
	public void deleteUser() {
		System.out.println("删除用户");
	}
}
  1. 创建切面类MyAspect,实现org.aopalliance.intercept.Methodinterceptor接口,并实现其中invoke()方法。注意不同的通知要继承不同的接口,包括org.springframework.aop.MethodBeforeAdvice,org.springframework.aop.AfterReturningAdvice等等
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
// 切面类
public class MyAspect implements MethodInterceptor {
	@Override
	public Object invoke(MethodInvocation mi) throws Throwable {
		check_Permissions();
		// 执行目标方法
		Object obj = mi.proceed();
		log();
		return obj;
	}
	public void check_Permissions(){
		System.out.println("模拟检查权限...");
	}
	public void log(){
		System.out.println("模拟记录日志...");
	}
}
  1. 配置bean,并指定代理对象。
	<!-- 1 目标类 -->
	<bean id="userDao" class="com.itheima.jdk.UserDaoImpl" />
	<!-- 2 切面类 -->
	<bean id="myAspect" class="com.itheima.factorybean.MyAspect" />
	<!-- 3 使用Spring代理工厂定义一个名称为userDaoProxy的代理对象 -->
	<bean id="userDaoProxy" 
            class="org.springframework.aop.framework.ProxyFactoryBean">
		<!-- 3.1 指定代理实现的接口-->
		<property name="proxyInterfaces" 
                      value="com.itheima.jdk.UserDao" />
		<!-- 3.2 指定目标对象 -->
		<property name="target" ref="userDao" />
		<!-- 3.3 指定切面,织入环绕通知 -->
		<property name="interceptorNames" value="myAspect" />
		<!-- 3.4 指定代理方式,true:使用cglib,false(默认):使用jdk动态代理 -->
		<property name="proxyTargetClass" value="true" />
	</bean>
  1. 测试调用,和一般调用一致,但是结果被增强了。
	public static void main(String args[]) {
	   String xmlPath = "com/itheima/factorybean/applicationContext.xml";
	   ApplicationContext applicationContext = 
                                 new ClassPathXmlApplicationContext(xmlPath);
	   // 从Spring容器获得内容
	   UserDao userDao = 
                       (UserDao) applicationContext.getBean("userDaoProxy");
	   // 执行方法
	   userDao.addUser();
	   userDao.deleteUser();
	}
}
AOP术语解释
Aspect(切面)封装的用于横向插入系统功能的类。
Joinpoint(连接点)可以被拦截的点,可以被增强的方法。
Pointcut(切入点)真正被拦截的点。
Advice(增强、通知)增强的方法。(方法前后)
Introduction(引介)类层面的增强。(加属性或方法)
Target(目标)被增强的对象。
Proxy(代理)将通知应用到目标对象之后,被动态创建的对象。
Weaving(织入)将切面代码插入目标对象,生成代理对象的过程。

什么是代理

AspectJ:AOP框架(更简便)

一个AspectJ示例程序

  1. 创建切面类
public class MyAspect {
	// 前置通知
	public void myBefore(JoinPoint joinPoint) {
		System.out.print("前置通知 :模拟执行权限检查...,");
		System.out.print("目标类是:"+joinPoint.getTarget() );
		System.out.println(",被织入增强处理的目标方法为:"
                            +joinPoint.getSignature().getName());
	}
}
  1. 配置bean,以及<aop:config>
	<!-- 1 目标类 -->
	<bean id="userDao" class="com.itheima.jdk.UserDaoImpl" />
	<!-- 2 切面 -->
	<bean id="myAspect" class="com.itheima.aspectj.xml.MyAspect" />
	<!-- 3 aop编程 -->
	<aop:config>
        <!-- 配置切面 -->
		<aop:aspect ref="myAspect">
		  <!-- 3.1 配置切入点,通知最后增强哪些方法 -->
		  <aop:pointcut expression="execution(* com.itheima.jdk.*.*(..))"
				                                      id="myPointCut" />
			<!-- 3.2 关联通知Advice和切入点pointCut -->
			<!-- 3.2.1 前置通知 -->
			<aop:before method="myBefore" pointcut-ref="myPointCut" />
		</aop:aspect>
	</aop:config>
  1. 测试调用

使用注解

AspectJ注解解释
@Aspect切面类
@Pointcut切入点表达式
@before前置通知
@AfterReturning后置通知
@Around环绕通知
@AfterThrowing异常通知
@afterfinal通知,无论异常否,都会执行
@DeclareParents引介通知

一个使用注解的示例

  1. 创建切面类
@Aspect
@Component
public class MyAspect {
	// 定义切入点表达式
	@Pointcut("execution(* com.itheima.jdk.*.*(..))")
	// 使用一个返回值为void、方法体为空的方法来命名切入点
	private void myPointCut(){}
	// 前置通知
	@Before("myPointCut()")
	public void myBefore(JoinPoint joinPoint) {
		System.out.print("前置通知 :模拟执行权限检查...,");
		System.out.print("目标类是:"+joinPoint.getTarget() );
		System.out.println(",被织入增强处理的目标方法为:"
		               +joinPoint.getSignature().getName());
	}
}
  1. 配置文件中
      <!-- 指定需要扫描的包,使注解生效 -->
      <context:component-scan base-package="com.itheima" />
      <!-- 启动基于注解的声明式AspectJ支持 -->
      <aop:aspectj-autoproxy />
  1. 测试调用
// 测试类
public class TestAnnotationAspectj {
	public static void main(String args[]) {
		String xmlPath = 
                  "com/itheima/aspectj/annotation/applicationContext.xml";
		ApplicationContext applicationContext = 
                 new ClassPathXmlApplicationContext(xmlPath);
		// 1 从spring容器获得内容
		UserDao userDao = (UserDao) applicationContext.getBean("userDao");
		// 2 执行方法
		userDao.addUser();
	}
}

execution表达式

[访问修饰符] 方法返回值 包名.类名.方法名(参数)
execution(* com.itheima.jdk.*.*(…)),*表示任意返回类型类型,括号中(…)表示任意输入参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值