Java自学之spring:面向切面编程(AOP)

Part 1

什么叫面向切面?

AOP 即 Aspect Oriented Program 面向切面编程
首先,在面向切面编程的思想里面,把功能分为核心业务功能,和周边功能
所谓的核心业务,比如登陆,增加数据,删除数据都叫核心业务
所谓的周边功能,比如性能统计,日志,事务管理等等

周边功能在Spring的面向切面编程AOP思想里,即被定义为切面

在面向切面编程AOP的思想里面,核心业务功能和切面功能分别独立进行开发

然后把切面功能和核心业务功能"编织"在一起,这就叫AOP

Part 2

思路

1. 功能分两大类,辅助功能和核心业务功能

2. 辅助功能和核心业务功能彼此独立进行开发

3. 比如登陆功能,即便是没有性能统计和日志输出,也可以正常运行

4. 如果有需要,就把"日志输出" 功能和 "登陆" 功能编织在一起,这样登陆的时候,就可以看到日志输出了

5. 辅助功能,又叫做切面,这种能够选择性的,低耦合的把切面和核心业务功能结合在一起的编程思想,就叫做切面编程

v2-1257a70d83e9b618e3b78d8bafc454f4_b.jpg

Part 3

准备业务接口,和实现类,模拟实现一个对一个用户的CURD。

业务接口

package cn.vaefun.service;

public interface UserService {
	public void add();	//添加用户
	public void delete();	//删除用户
	public void update();	//更新用户
	public void search();	//查找用户
}

实现类

package cn.vaefun.dao;

import cn.vaefun.service.UserService;

public class UserServiceImpl implements UserService {

	public void add() {
		System.out.println("添加用户");
	}

	public void delete() {
		System.out.println("删除用户");
	}

	public void update() {
		System.out.println("更新用户");
	}

	public void search() {
		System.out.println("查找用户");
	}

}

Part 6

准备一个自定义的切面类,定义before()和after()。

package cn.vaefun.aspect;

public class LoggerAspect {
	public void before(){
		System.out.println("方法执行前");
	}
	public void after(){
		System.out.println("方法执行后");
	}
}

Part 5

在src下准备配置文件

<?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:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="
   http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
   http://www.springframework.org/schema/tx
   http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
   http://www.springframework.org/schema/context     
   http://www.springframework.org/schema/context/spring-context-3.0.xsd
   http://www.springframework.org/schema/aop
   http://www.springframework.org/schema/aop/spring-aop.xsd"
   >
   
   <bean name="userServiceImpl" class="cn.vaefun.dao.UserServiceImpl"></bean>
   <bean id="loggerAspect" class="cn.vaefun.aspect.LoggerAspect"></bean>
   
   <aop:config>
       
       <aop:aspect ref="loggerAspect"><!-- 为aspect切面类注入依赖位置 -->
           <aop:pointcut id="point" 
               expression="execution(* cn.vaefun.dao.UserServiceImpl.*(..))" />
                   <!-- 切面的切入点,cn.vaefun.dao.UserServiceImpl里方法执行的时候 -->
               <aop:before method="before" pointcut-ref="point"/><!-- 切入点方法执行前 -->
               <aop:after method="after" pointcut-ref="point"/><!-- 切入点方法执行后 -->
       </aop:aspect>
   
   </aop:config>
   
</beans>

Part 6

准备测试类,需要注意的是在获取userServiceImpl对象的时候,只能是其实现的接口的对象。这里牵扯到一个知识点:

Spring AOP实现方式有两种

1:使用JDK动态代理,如果被代理的目标实现了至少一个接口,则会使用JDK动态代理,所有该目标类型实现的接口都将被代理。

2:通过CGLIB来为目标对象创建代理,若该目标对象没有实现任何接口,则创建一个CGLIB代理,创建的代理类是目标类的子类。

我的UserServiceImpl实现了UserService接口,如果使用UserServiceImpl接收对象,会报一个错误:com.sun.proxy.$Proxy cannot be cast to *****。

报错的原因,是不能用接口的实现类(UserServiceImpl)来转换Proxy的实现类,它们是同级,应该用共同的接口(UserService)来转换。

除了使用UserService之外,还有另一种解决方案:强制使用CGLIB创建代理,需要引用jar包并修改spring配置文件。此方法日后再深究。

package cn.vaefun.test;

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

//import cn.vaefun.dao.UserServiceImpl;
import cn.vaefun.service.UserService;

public class TestSpring {

	public static void main(String[] args) {
		ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
		UserService userService = (UserService) context.getBean("userServiceImpl");
		userService.add();
                userService.search();
	}

}

Part 7

运行测试,得到以下结果:

v2-a2524faf96a314cd757920d91ab0b600_b.jpg

cn.vaefun.dao.UserServiceImpl的每一个方法执行前,都会执行cn.vaefun.aspect.LoggerAspect中的before(),cn.vaefun.dao.UserServiceImpl的每一个方法执行后,都会执行cn.vaefun.aspect.LoggerAspect中的after()。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值