欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JAVAEE之Spring学习(三)---aop切面(一)

程序员文章站 2022-05-24 09:49:41
...

先了解AOP的相关术语:
1.通知(Advice):
通知定义了切面是什么以及何时使用。描述了切面要完成的工作和何时需要执行这个工作。
2.连接点(Joinpoint):
程序能够应用通知的一 个“时机”,这些“时机”就是连接点,例如方法被调用时、异常被抛出时等等。
3.切入点(Pointcut)
通知定义了切面要发生的“故事”和时间,那么切入点就定义了“故事”发生的地点,例如某个类或方法的名称,spring中允许我们方便的用正则表达式来指定
4.切面(Aspect)
通知和切入点共同组成了切面:时间、地点和要发生的“故事”
5.引入(Introduction)
引入允许我们向现有的类添加新的方法和属性(spring提供了一个方法注入的功能)
6.目标(Target)
即被通知的对象,如果没有AOP,那么它的逻辑将要交叉别的事务逻辑,有了AOP之后它可以只关注自己要做的事(AOP让他做爱做的事)
7.代理(proxy)
应用通知的对象,详细内容参见设计模式里面的代理模式
8.织入(Weaving)
把切面应用到目标对象来创建新的代理对象的过程,织入一般发生在如下几个时机:
(1)编译时:当一个类文件被编译时进行织入,这需要特殊的编译器才可以做的到,例如AspectJ的织入编译器
(2)类加载时:使用特殊的ClassLoader在目标类被加载到程序之前增强类的字节代码
(3)运行时:切面在运行的某个时刻被织入,SpringAOP就是以这种方式织入切面的,原理应该是使用了JDK的动态代理技术

通过java语言实现aop切面:

package cn.hncu.v1;

import java.lang.reflect.Method;

import org.aopalliance.aop.Advice;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.junit.Test;
import org.springframework.aop.Advisor;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.aop.support.JdkRegexpMethodPointcut;

//AOP的一个公式:切面=切点+通知
//             Aspect=Pointcut(拦截哪些函数)+advice(在哪个时间点拦截:before,after,around)
//注意,通知Advice及其抽象类用的都是aop包中的接口
public class Demo1 {
    @Test
    public void t1() {
        // 1被代理对象--原型对象
        Person p = new Person();

        // 2实现代理的工具类 --bean的代理工厂
        // ProxyFactory factory = new ProxyFactory();// 低版本,不建议使用
        ProxyFactoryBean factory = new ProxyFactoryBean();

        // 3给代理工厂设置原型
        factory.setTarget(p);

        // 切面=切点+通知
        // 4声明切点
        JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();

        // 5为切点设置正则表达式
        pointcut.setPattern(".*run.*");

        // 6定义通知
        Advice advice = new MethodInterceptor() {
            @Override
            public Object invoke(MethodInvocation invocation) throws Throwable {
                System.out.println("前面拦拦");
                // 放行
                Object returnValue = invocation.proceed();
                System.out.println("后面拦拦");
                return returnValue;
            }
        };
        // Advisor = cut+advice
        // 7声明切面
        Advisor advisor = new DefaultPointcutAdvisor(pointcut, advice);

        // 8把切面设置到代理工厂中
        factory.addAdvisor(advisor);

        // 9从代理工厂中获取代理后的对象
        Person p2 = (Person) factory.getObject();

        // 10用代理后的对象去执行
        p2.run();
    }

    @Test
    public void t2() {
        // 1被代理对象--原型对象
        Person p = new Person();

        // 2实现代理的工具类 --bean的代理工厂
        // ProxyFactory factory = new ProxyFactory();// 低版本,不建议使用
        ProxyFactoryBean factory = new ProxyFactoryBean();

        // 3给代理工厂设置原型
        factory.setTarget(p);

        // 切面=切点+通知
        // 4声明切点
        JdkRegexpMethodPointcut pointcut = new JdkRegexpMethodPointcut();

        // 5为切点设置正则表达式
        pointcut.setPatterns(new String[] { ".*run.*", ".*hello.*" });

        // 6定义通知(前置通知)
        Advice before = new MethodBeforeAdvice() {

            @Override
            public void before(Method method, Object[] args, Object target)
                    throws Throwable {
                System.out.println("before...");
            }
        };
        Advice after = new AfterReturningAdvice() {

            @Override
            public void afterReturning(Object returnValue, Method method,
                    Object[] args, Object target) throws Throwable {
                System.out.println("方法执行完毕  ");
            }
        };

        // Advisor = cut+advice
        // 7声明切面
        Advisor advisor = new DefaultPointcutAdvisor(pointcut, before);
        Advisor advisor2 = new DefaultPointcutAdvisor(pointcut, after);

        // 8把切面设置到代理工厂中
        factory.addAdvisors(advisor, advisor2);

        // 9从代理工厂中获取代理后的对象
        Person p2 = (Person) factory.getObject();

        // 10用代理后的对象去执行
        p2.run();
        p2.hello();
    }
}

二、通过xml配置来实现aop切面

实现类:

package cn.hncu.v1;

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

/*
 * 用xml方式来实现aop
 */
public class demo2 {
    @Test
    public void t1() {
        ApplicationContext ctx = new ClassPathXmlApplicationContext(
                "cn/hncu/v1/v1.xml");
        Person p = ctx.getBean("proxiedPersonFactory", Person.class);
        p.run();// 拦
        p.hello();// 不拦
    }
}

advice定义通知类:

package cn.hncu.v1;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class AroundAdvice implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        System.out.println("前面拦拦");
        // 放行
        Object returnValue = invocation.proceed();
        System.out.println("后面拦拦");
        return returnValue;
    }

}

通过仿照java方式通过容器来进行xml配置aop切面:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:context="http://www.springframework.org/schema/aop" 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="p" class="cn.hncu.v1.Person">
    </bean>
    <bean id="cut" class="org.springframework.aop.support.JdkRegexpMethodPointcut">
        <property name="pattern" value=".*run.*"></property>
    </bean>
    <bean id="advice" class="cn.hncu.v1.AroundAdvice">
    </bean>
    <bean id="advisor" class="org.springframework.aop.support.DefaultPointcutAdvisor">
        <property name="pointcut" ref="cut"></property>
        <property name="advice" ref="advice"></property>
    </bean>
    <bean id="proxiedPersonFactory" class="org.springframework.aop.framework.ProxyFactoryBean">
        <property name="target" ref="p"></property>
        <property name="interceptorNames">
            <list>
                <value>advisor</value>
            </list>
        </property>
    </bean>

</beans>   
相关标签: spring aop