AOP切面编程思想

AOP切面编程思想

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

  • 目的是在不修改原来代码的基础上添加某种额外的功能

可以理解为以前都是排一行队,现在想在第某行添加一个管理者,让其管理某个(或多个)人,所以让其并列到该位置即可。

润物细无声的执行,而在业务代码中没有表现出来,直接通过配置就能够动态的获得对象,并执行。

  • 优点:不用在原来的代码上修改,下次也容易找到,修改一处,多处使用,降低了代码的耦合度
  • 缺点:配置文件任务重

与OOP编程思想比较来看,aop可以看做是对oop的补充和完善。

AOP编程思想在spring中应的比较广泛

已经完成的业务

  • dao层
package com.wenhua.spring.dao;

import org.springframework.stereotype.Repository;

@Repository(value = "userDao")
public class UserDao {

	/**
	 * 当我们业务功能实现后,后期添加一些新的功能(与业务关系不大)
	 * 		记录每次操作后的日志信息
	 * 		开启事务
	 * 		提交事务
	 */
	
	public void insert() {
		System.out.println("保存用户");
	}

	public void update() {
		System.out.println("修改用户");
		// 一般情况 直接添加到业务代码中,而且代码不断的要重复
		// LogUtil.saveLog();
	}

	public void find() {
		System.out.println("查询用户");
		int num = 10/0;
		// LogUtil.saveLog();
	}
}
  • service层
package com.wenhua.spring.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.wenhua.spring.dao.UserDao;
/**
 * 用户服务层
 * @author ASUS
 *
 */
@Service(value="userService")
public class UserService {
	
	@Autowired// spring中自动注入,根据UserDao类型去Spring容器中寻找UserDao中可以没有标签和set和get方法
	private UserDao userDao;
	
	public void save(){
		userDao.insert();
	}

	public void update(){
		userDao.update();
	}
	
	public void find(){
		userDao.find();
	}
	public UserDao getUserDao() {
		return userDao;
	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}
	
}
  • test层
package com.wenhua.spring.test;

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

import com.wenhua.spring.service.UserService;

public class UserTest {
	public static void main(String[] args) {
		// 加载spring配置文件,创建一个ApplicaionContext
		ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");

		// 此测试方法可以没有User类
			UserService userService = context.getBean(UserService.class);
			userService.save();
			System.out.println("--------环绕通知--------------");
			userService.update();
			System.out.println("----------注意异常通知不要和环绕通知一起用-------------");
			userService.find();
	}
}

实现aop切面编程

  • 在pom.xml配置文件中添加jar包
<!-- spring切面实现 -->
  	<dependency>
  		<groupId>org.springframework</groupId>
  		<artifactId>spring-aspects</artifactId>
  		<version>5.2.2.RELEASE</version>
  	</dependency>
  • 在.xml配置文件中添加响应功能的约束
xmlns:aop="http://www.springframework.org/schema/aop"

http://www.springframework.org/schema/aop
                    http://www.springframework.org/schema/aop/spring-aop.xsd
  • 编写将要通知的类(logUtil)以及方法
package com.wenhua.spring.util;

import org.aspectj.lang.ProceedingJoinPoint;

public class LogUtil {

	// 定义为静态的,便于在其他业务类中调用
	public static void saveLog(){
		System.out.println("保存日志");
	}
	
	// 环绕通知
	public void aroundAdvice(ProceedingJoinPoint point){
		System.out.println("开启事务");
		
		try {
			point.proceed();
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		System.out.println("提交事务");	
	}
	
	// 异常通知
	public static void exceptionAdvice(Throwable e){
		System.out.println("异常通知"+e.getMessage());
	}
}

通过bean标签将该类注入到spring框架中,以供使用

<!-- 配置装有公共功能的切面LogUtil对象 -->
        <bean id="logUtil" class="com.wenhua.spring.util.LogUtil"></bean>
  • 在配置文件中进行织入配置
 <!-- 织入 -->
   <aop:config>
      <!-- 配置切入点 -->
        	<aop:pointcut expression="execution(* com.wenhua.spring.dao.UserDao.insert(..))" id="insert"/>
        	<aop:pointcut expression="execution(* com.wenhua.spring.dao.UserDao.update(..))" id="update"/>
        	<aop:pointcut expression="execution(* com.wenhua.spring.dao.UserDao.find(..))" id="find"/>
        	<!-- 对该类下的所有方法进行统一配置
        	<aop:pointcut expression="execution(* com.wenhua.spring.dao.UserDao.*(..))" id="all"/> -->
        	
        	<!-- 配置通知和切入点 -->
        	<aop:aspect ref="logUtil">
        		<!-- 在执行事务之前   -->
        		<!-- <aop:before method="saveLog" pointcut-ref="insert"/> -->
        		<!-- 在执行事务之后 -->
        		 <aop:after method="saveLog" pointcut-ref="insert"/>
        	    <!-- 环绕通知 -->
        	    <aop:around method="aroundAdvice" pointcut-ref="update"/>
        	    <!-- 异常通知 -->
        	    <aop:after-throwing method="exceptionAdvice" pointcut-ref="find" throwing="e"/>
        	</aop:aspect>
        </aop:config>

名词解释

  • 连接点(Joinpoint): 类中可以被增强的方法
  • 切入点(poincut): 类中已经被增强了的方法
  • 通知(Advice): 切面要完成的工作(额外的工作)
  • 切面(Aspect): 把通知添加到切入点的过程
  • 目标(Target): 代理的目标对象(要增强的类)
  • 织入(Weaving): 将通知应用到目标的过程
  • 代理(Proxy): 向目标对象应用通知之后创建的代理对象
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值