spring模块(四)Spring AOP

一、介绍

为什么有AOP
在面向对象编程的系统中,会使用对象来封装一些对象。并通过对象的协作进行完成系统的功能。如员工管理、部门管理、请假管理等功能。现在需要对系统中的所有的新增,修改,删除,等记录下操作的记录,这样需要这样写代码:

而这些操作都是通过“复制黏贴式”的开发。面向对象在处理这样的业务时由于其封装性导致代码并无法被公用。需要有一种技术来实现方法的扩展(功能增强)。AOP就正是这样的一种技术,它能够配合OOP进行这些通用功能的分离和织入,对业务代码不会造成污染。
AOP的基本概念
什么是AOP?
AOP Aspect-Oriented Programming 面向切面编程。它是一种编程思想能使软件简单,容易维护,更加容易被复用的一种编程方式;AOP只是OOP编程方式的一种补充,并非什么新的技术。
AOP编程方式解决问题的关键在于对关注点的抽象。对系统中的一些分散在多个不相关业务模块中的共同问题(关注点),将这些关注点从各个业务模块中抽象出来是AOP编程的精髓。如日志记录功能,事务管理功能,方法的性能分析等功能从系统业务模块的分离。
对于OOP和AOP的的主要开发流程做一个对比:A B C
OOP 编程基本流程
1)归纳分析系统,抽象领域模型;
2)使用class 来封装领域模型,实现类的功能;
3)把各个类相互协作,组装形成一个完整的功能。


AOP 编程基本流程
1)归纳分析系统中的关注点;
2)分离方面对象,使用OOP 将这些方面封装成一个公用的类;
3)织入到业务功能,按配置织入规则将切面对象(织入或集成)到系统功能中,形成一个增强后的功能。
AOP中的一些关键的专业术语
1)关注点:就是系统中要解决的问题。比如在电子商务系统中,安全验证、日志记录等都属于关注点(Core Concerns);

2)切面(Aspect):用来组织多个Advice,负责管理切入点和增强的关系;

3)增强(Advice):定义何时在切入点执行“织入关注点”;如,在执行方法前执行before,在执行方法后执行after等等。

4)连接点(Joinpoint):明确的某一个被织入代码的点,如方法调用,异常抛出,方法返回等等时间点;

5)切入点(cutpoint):可以织入增强方法的连接点。当连接点满足被增强的要求时,会在该连接点添加增强,此时的连接点就成为切入点。

6)织入(weaving) :织入是指把解决横切问题的切面模板,与系统中的其它核心模块通过一定策略或规则组合到一起的过程;具体的技术方案有:a.动态代理;b.类加载器织入c.编译器织入:AspectJ主要就是是使用这种织入方式

spring模块(四)Spring AOP_第1张图片

Spring对AOP的支持

Spring中AOP默认是使用动态代理的方式创建AOP代理的。Spring的AOP代理是由IOC容器负责创建和管理,这样的好处是可以使用容器中的任何一个bean作为“方面”目标。Spring的AOP的设计目标是将AOP的实现和IOC容器进行整合,帮助解决在企业开发中遇到的此类问题。Spring中的AOP也支持AspectJ(面向方面的真正始祖级框架)。

在Spring的AOP开发中,程序员需要做以下三件事情:
1)定义普通的业务类
2)定义切入点,对多个关注点进行横切
3)定义增强,在普通的业务功能中织入关注点的处理


Spring依然提供两种对AOP的配置:
1)XML的方式
2)使用注解进行标注的方式

场景:

Employee balance

现在系统中已经有了很多的业务功能,比如其中的一个EmployeeService类,里面就有方法;addEmployeeBalance()、//添加初始化的薪资 updateEmployeeBalance ()、每次加100,findEmployeeBalance ()。查询工资。
如果在系统完成差不多的时候,这个时候需要对系统中的所有的更新操作(新增,修改,删除)进行记录操作日志,因为数据比较重要,每一部都记录下来,数据变了到底是谁干的一查就清楚了。

当这个需求下来的时候估计很头疼,要在系统中上百个类中去查找到更新的操作,并更改其方法——插入日志记录操作方法。并且要进行测试等等。你是不是顿时觉得天要塌下来了。

AOP就专门治疗这些疑难杂症,你只需要专心编写记录日志的方法,然后使用Spring进行配置能在原有的业务上添加这些增强操作。

二、实例:

1、创建一个maven工程;

2、在pox.xml中引入相关jar包依赖:


	4.0.0
	com.iflytek
	myaop
	0.0.1-SNAPSHOT

	
		
			org.springframework
			spring-core
			4.3.13.RELEASE
		
		
			org.springframework
			spring-context
			4.3.13.RELEASE
			runtime
		
		
		
			org.springframework
			spring-aop
			4.3.13.RELEASE
		
		
		
			org.aspectj
			aspectjrt
			1.8.10
		

		
			aopalliance
			aopalliance
			1.0
		
		
			org.aspectj
			aspectjweaver
			1.8.10
		



		
			log4j
			log4j
			1.2.17
		
	

3、在applicationContext.xml配置文件中引入头:




	
	
	


4、代码:

(1)实体类:

package com.iflytek.domain;

public class Employee {

}

(2)service:

package com.iflytek.service;

import org.springframework.stereotype.Service;

import com.iflytek.domain.Employee;

@Service
public class EmployeeService {
	
   public int addEmployee(Employee emp) {
      System.out.println("添加员工成功");
      return 0;
   }
   public int delEmployee(Employee emp) {
      System.out.println("删除员工成功");
      return 0;
   }
   public int updateEmployee(Employee emp) {
      System.out.println("修改员工成功");
      return 0;
   }
   public Employee findEmployee(String empno) {
      System.out.println("查询员工成功");
      return new Employee();
   }
}
package com.iflytek.service;

import org.springframework.stereotype.Service;

@Service("optLogger")
public class OptLogger {
   public void writeOpt(String msg){
      System.out.println("日志记录成功");
   }
}

package com.iflytek.service;

import org.springframework.stereotype.Service;

@Service
public class PersonService{
	
	public void save(String name) {
        System.out.println("我是save()方法");
    }

    public void update(String name, Integer id) {
        System.out.println("我是update()方法");
    }

    public String getPersonName(Integer id) {
        System.out.println("我是getPersonName()方法");
        return "xxx";
    }

}

(3)aop:

package com.iflytek.service;

import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class MyInterceptor {
    @Pointcut("execution (* com.iflytek.service.PersonService.add*(..))")
    private void anyMethod() {} // 声明一个切入点,anyMethod为切入点名称
    
    @Pointcut("execution (* com.iflytek.service.EmployeeService.update*(..))")
    private void anotherMethod() {}
    
    // 声明该方法是一个前置通知:在目标方法开始之前执行 
    @Before("anyMethod()")
    public void doAccessCheck() {
        System.out.println("前置通知");
    }
    
    @After(value = "anyMethod()")
    public void closeResource() {
    	System.out.println("关闭数据库连接");
    }
    
    @Before("anotherMethod()")
    public void openSession() {
    	System.out.println("开启session");
    }
}

(4)测试:

package com.iflytek.test;

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

import com.iflytek.domain.Employee;
import com.iflytek.service.EmployeeService;
import com.iflytek.service.PersonService;

public class SpringAOPTest {
	@Test
	public void interceptorTest() {
		ApplicationContext cxt = new ClassPathXmlApplicationContext("applicationContext.xml");
		EmployeeService employeeService = (EmployeeService) cxt.getBean("employeeService");
//		personService.save("xxx");
//		personService.update("zhangsan", 1);
//		personService.getPersonName(1);
		
		employeeService.updateEmployee(new Employee());
	}
}

输出:


 

你可能感兴趣的:(Spring,spring,java,数据库)