Spring学习之AOP代理创建

一、AOP简介

AOP(Aspect Oriented Programming),即面向切片编程。AOP采用横向抽取机制,取代了传统纵向继承体系重复性代码,主要体现在事务处理日志管理权限控制异常处理等方面,使开发人员可以专注于核心业务,提高了代码的可维护性。
AOP的专业术语包括Jointpoint、Pointcut、Advice、Target、Weaving、Proxy和Aspect

  • Jointpoint(连接点):是指那些被拦截到的点,在Spring中,可以被动态代理拦截目标类的方法。
  • Pointcut(切入点):是指要对哪些Jointpoint进行拦截,即被拦截的连接点。
  • Advice(通知):是指拦截到Joingpoint之后要做的事情,即对切入点增强的内容。
  • Target(目标):是指代理的目标对象。
  • Weaving(织入):是指把增强代码应用到目标上,生成代理对象的过程。
  • Proxy(代理):是指生成的代理对象。
二、Spring 通知类型

通知(Advice)就是对目标切入点增强的内容,AOP联盟为Advice定义了org.aopalliance.aop.Advice接口,Spring通知按照在目标类方法的连接点位置,可以分为5种,如下:

  • org.springframework.aop.MethodBeforeAdvice(前置通知)
    在目标方法执行前实施增强,可以运用于权限管理等功能。
  • org.springframework.aop.AfterReturningAdvice(后置通知)
    在目标方法执行后实施增强,可以运用于关闭流,上传文件、删除临时文件等功能。
  • org.aopalliance.intercept.MethodInterceptor(环绕通知)
    在目标方法执行前后执行实施增强,可以运用于日志、事务管理等功能。
  • org.springframework.aop.ThrowsAdvice(异常抛出通知)
    在方法抛出异常后实施增强,可以运用于处理异常记录日志等功能。
  • org.springframework.aop.IntroductionInterceptor(引介通知)
    在目标类中添加一些新的方法和属性,可以运用于修改老版本程序。
三、声明式 Spring AOP

在Spring中创建一个AOP代理的基本方法是:使用org.springframework.aop.framework.ProxyFactoryBean,ProxyFactoryBean类中的常用可配置属性如下表

属性名称描述
target代理的目标对象
proxyInterfaces代理要实现的接口
proxyTargetClass是否对类代理而不是接口,设值为true时,使用CGLIB代理
interceptorNames需要织入目标的Advice
singleton删除 index 索引处的元素
optimize当设置为 true 时,强制使用 CGLIB
四、代码实现

在项目src目录下创建包cn.test.factorybean,在该包下创建切面类MyAspect,内容如下:

// MyAspect.java
package cn.test.factorybean;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyAspect implements MethodInterceptor{
   @Override
   public Object invoke(MethodInvocation mi) throws Throwable{
       System.out.println("方法执行之前");
       Object obj = mi.proceed();
       System.out.println("方法执行之后");
       return obj;
   }
}

在cn.test.factorybean包中创建UserDao接口和UserDaoImpl实现类,内容分别为:

// UserDao.java
package cn.test.factory;

public interface UserDao{
	public void save();
	public void update();
	public void delete();
	public void find();
}

// UserDaoImpl.java
package cn.test.factory;

public class UserDaoImpl implements UserDao {
    @Override
    public void save() {
        System.out.println("save 添加用户");
    }

    @Override
    public void update() {
        System.out.println("update 修改用户");
    }

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

    @Override
    public void find() {
        System.out.println("find 查询用户");
    }
}

在cn.test.factorybean包中创建xml配置文件applicationContext.xml,内容如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
	<!--    目标类-->
    <bean id="userDao" class="cn.test.factorybean.UserDaoImpl"></bean>
	<!--    通知 advice-->
    <bean id="myAspect" class="cn.test.factorybean.MyAspect"></bean>
	<!--    生成代理对象-->
    <bean id="userDaoProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
	<!--        代理实现的接口-->
        <property name="interfaces" value="cn.test.factorybean.UserDao"></property>
	<!--        目标-->
        <property name="target" ref="userDao"></property>
	<!--        用通知增强目标-->
        <property name="interceptorNames" value="myAspect"></property>
	<!--        如何生成代理,true;使用cglib,false;使用jdk动态代理-->
        <property name="proxyTargetClass" value="false"></property>
    </bean>
</beans>

然后我们在cn.test.factorybean下创建测试类TestFactoryBean

// TestFactoryBean.java
package cn.test.factoryebean

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

public class TestFactoryBean{
	@Test
	public void demo(){
		String xmlPath = "cn/test/factorybean/applicationContext.xml";
		ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
		// 从spring容器中获取内容
		UserDao userDao = (UserDao)applicationContext.getBean("userDaoProxy");
		// 执行方法
		userDao.save();
		userDao.update();
		userDao.delete();
		userDao.find();
	}
}
五、运行结果在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值