栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

spring的AOP是什么

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

spring的AOP是什么

 一、什么是AOP

1. 简介

AOP 为 Aspect Oriented Programming 的缩写,意思为面向切面编程,是通过预编译方式和运行期动态代理 实现程序功能的统一维护的一种技术。

AOP 是 OOP 的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍 生范型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序 的可重用性,同时提高了开发的效率

2. 作用及优势

作用:在程序运行期间,在不修改源码的情况下对方法进行功能增强优势:减少重复代码,提高开发效率,并且便于维护

3. 底层实现原理

spring提供的一种动态代理技术实现功能的增强

(1)JDK代理:基于接口的动态代理技术

 我们先来写一个简单的目标接口:

public interface TargetInterface {
    public void save();
}

我们再写一个目标对象,实现刚才那个目标接口:

public class Target implements TargetInterface{
    @Override
    public void save() {
        System.out.println("save....");
    }
}

最后我们实现一个动态代理方法使其功能增强,比如前置增强和后置增强。

public class ProxyTest {
    public static void main(String[] args) {
        //目标对象
        Target target = new Target();
        TargetInterface tagetInterface = (TargetInterface) Proxy.newProxyInstance(target.getClass().getClassLoader(), target.getClass().getInterfaces(), new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("前置增强...."); //前置增强
                Object invoke = method.invoke(target, args); //执行目标方法
                System.out.println("后置增强...."); //后置增强
                return invoke;
            }
        });
        //调用代理对象的方法
        tagetInterface.save();
    }
}

查看运行结果可以看到方法被增强了! 

(2)cglib代理:基于父类的动态代理技术

我们还是先写一个简单的目标对象

public class Target {
    public void save() {
        System.out.println("save running.....");
    }
}

 然后实现动态代理方法实现功能增强

public class ProxyTest {
    public static void main(String[] args) {
        //目标对象
        final Target target = new Target();       
        //1、创建增强器
        Enhancer enhancer = new Enhancer();
        //2、设置父类(目标)
        enhancer.setSuperclass(Target.class);
        //3、设置回调
        enhancer.setCallback(new MethodInterceptor() {
            public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
                System.out.println("前置增强...."); 
                Object invoke = method.invoke(target, args); //执行目标
                System.out.println("后置增强...."); 
                return invoke; //返回值 就是动态生成的代理对象  基于cglib
            }
        });
        //4、创建代理对象
        Target proxy = (Target) enhancer.create();
        proxy.save();
    }
}

查看运行结果可以看到方法被同样增强了!

二、基于XML的AOP开发

1. 导入AOP相关坐标

找到 pom.xml,将下面两个坐标导入

(1)spring的context坐标,context依赖aop

    org.springframework
    spring-context
    5.0.5.RELEASE

(2)aspectj的织入

    org.aspectj
    aspectjweaver
    1.8.4

2. 创建类和方法

(1)目标接口
public interface TargetInterface {
    public void save();
}

(2)目标类(也就是切点)
public class Target implements TargetInterface{
    @Override
    public void save() {
        System.out.println("save....");
    }
}

(3) 切面类(也就是增强方法)
public class InvokeDemo {
    public void before(){
        System.out.println("前置增强....");
    }

    public void afterReturning(){
        System.out.println("后置增强....");
    }
}

3. 面向切面编程 

(1)将目标类和切面类的对象创建权交给 spring

找到 applicationContext.xml,写入以下代码:




(2)在 applicationContext.xml 中配置织入关系,

首先导入aop命名空间:

然后配置切点表达式和前置增强的织入关系:

先写出大体的格式:

    
        
    

  注意这里的切点表达式的写法:        

execution([修饰符] 返回值类型 包名.类名.方法名(参数))

访问修饰符可以省略返回值类型、包名、类名、方法名可以使用星号* 代表任意包名与类名之间一个点 . 代表当前包下的类,两个点 .. 表示当前包及其子包下的类参数列表可以使用两个点 .. 表示任意个数,任意类型的参数列表

通知类型:

切点表达式的抽取:

当多个增强的切点表达式相同时,可以将切点表达式进行抽取,在增强中使用 pointcut-ref 属性代替 pointcut 属性来引用抽取后的切点表达式 。

比如下面的完整写法中,把切点命名为 myPointCut 并放入  标签中,直接再下面的前置通知或后置通知 pointcut-ref="myPointCut" 调用即可。

最后,完整写出配置切点表达式和前置增强的织入关系: 

    
    
        
        
            
            
            
            
            
        
    -->

4. 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
    @Autowired
    private TargetInterface target;
    @Test
    public void test1(){
        target.save();
    }
}

运行结果: 

 这样我们就实现了基于XML的AOP开发!不过我们一般使用更为方便的注解开发。

三、基于注解的 AOP 开发

1. 导入AOP相关坐标

与XML开发完全相同

2. 创建类和方法

(1)创建目标接口和目标类(与XML开发相同)
// 目标接口
public interface TargetInterface {
    public void save();
}
// 目标类(也就是切点)
// @Component("target")
public class Target implements TargetInterface{
    @Override
    public void save() {
        System.out.println("save....");
    }
}

注意这里的切点类也可以使用下面说到的的 @Component() 注解,不加也行!

(3) 切面类

首先我们需要用到 @Component() @Pointcut() @Aspect() 注解

@Component():实现bean的注入@Pointcut():抽取切面表达式@Aspect():表明当前类是一个切面类

@Component("myAspect") 
@Aspect //标注切面类
public class MyAspect {
    @Pointcut("execution(* aop.*.*(..))") // 抽取切面表达式
    public void pointCut(){};
    @Before("MyAspect.pointCut()")
    public void before(){
        System.out.println("前置增强....");
    }
    @AfterReturning("MyAspect.pointCut()")
    public void afterReturning(){
        System.out.println("后置增强....");
    }
}

 然后通知方法的注解:

3. 在配置文件中开启组件扫描和 AOP 的自动代理

打开 applicationContext.xml 文件,将基于 xml 的AOP开发加注释,然后加上以下两行配置。

base-package 的值是需要扫描的切面和切点类所在的package包。



4. 测试
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
public class AopTest {
    @Autowired
    private TargetInterface target;
    @Test
    public void test1(){
        target.save();
    }
}

编写测试代码,可以看到也能实现方法增强。 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/778016.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号