Spring之AOP

AOP(面向切面编程)

1、连接点(Joinpoint):

    连接点是程序执行过程中可以插入切面的特定的点。这个点可以是调用方法时,抛出异常时,甚至修改字段时,

对于Spring而言,只支持方法连接点。

2、切点(Pointcut):

    一个类有很多方法,这些方法都是连接点,但是并不是每一个方法都要插入切面,那么就要经过特定的条件过滤,这些

经过过滤后要插入切面的方法被称为切点,所以切点是由一个活多个连接点组成,是连接点集合的一个子集。

3、通知(Advice):

    切面所要完成的工作称为通知,它定义的前切点前(before)还是切点后(after)做什么,可理解为”何时“、”干什么“。

    Spring有5种类型的通知:

    ① Before:前置通知,在切点方法之前执行。

    ② After  :后置通知,在切点方法返回后通知,无论方法是否执行成功。

    ③ After-returning:返回后通知,在切点方法成功执行之后调用通知。

    ④After-throwing:抛出后通知,在切点方法抛出异常后调用通知。

    ⑤Arount:环绕通知,既在方法调用前又在方法调用后调用通知。并且可以决定这个方法是否执行,什么时候执行。

4、切面(Aspect):

    通知和切点的结合就是切面。

5、引入(Introduction):

    引入就是为一个类添加新的方法和属性,从而在不改变现有类的情况下让他们具有新的行为和属性。

6、织入(Weaving):

    织入是切面应用到目标对象的过程,在目标对象的运行周期里有多个点可以进行织入。

    ①编译期:在切面目标类被编译的时候织入。AspectJ就是编译期织入。

    ②类加载期:切面目标类被加载到JVM是织入。

    ③运行时:切面在运行的某个时刻织入,Spring AOP就是通过这种方式织入的,AOP容器会为目标对象动态的创建一个代理对象

7、代理(Proxy):

 在实现上,SpringAOP其实就是使用JDK的动态代理(使用接口的方式完成代理操作),也可以使用CGLIB(使用继承的方式完成代理操作)。

8、目标(Target)

  业务操作的实际对象。


 <aop:config>
        <aop:pointcut id="cut" expression="execution(**(..))"/>
        <aop:aspect ref="serviceFactory">
            <aop:before method="before" pointcut-ref="cut"/>
            <aop:after method="after" pointcut-ref="cut"/>
        </aop:aspect>
    </aop:config>


Java的动态代理机制

代理模式是常用的Java设计模式。代理类主要负责为委托类预处理消息、过滤信息、把消息转发给委托类,以及事后处理信息等。

这里照前辈举了2个动态代理的例子,分别是 JDK和Cglib的代理

即通过 代理类来包装service实现AOP,ServiceFactory中相当于 AOP中的通知即要处理的事件

<span style="font-size:14px;">public class ServiceFactory {
    public static void before(){
        System.out.println("前置日志打印,启动事务等");
    }
    public static void after(){
        System.out.println("后置日志打印,关闭事务等");
    }
}</span>

JDK动态代理,此中涉及java的反射机制 

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class LearnProxyJDK implements InvocationHandler {
    // 目标对象,也就是我们主要的业务,主要目的要做什么事
    private Object delegate;
    /**
     * 和你额外需要做得事情,进行绑定,返回一个全新的对象
     */
    public Object bind(Object delegate){
        this.delegate = delegate;
        return Proxy.newProxyInstance(this.delegate.getClass().getClassLoader(),
        this.delegate.getClass().getInterfaces(),this);
    }
    /**
     * 你刚才需要执行的方法,都需要通过该方法进行动态调用
     */
    @Override
    public Object invoke(Object proxy,Method method,Object[] args) throws Throwable {
        Object obj = null;
        ServiceFactory.before();
        obj = method.invoke(this.delegate,args);
        ServiceFactory.after();
        return obj;
    }
}

Cglib代理还不是很明白,需要进一步理解,在此先留个印象
import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

public class LearnProxyCglib implements MethodInterceptor {
    private Object target;

    /**
     * 这里和JDK 绑定目标类 类似
     * 仅仅是创建了一个以继承了目标类的新对象
     */
    public Object bind(Object target) {
        this.target = target;
        Enhancer enhancer = new Enhancer();
        enhancer.setSuperclass(this.target.getClass());
        enhancer.setCallback(this);
        return enhancer.create();
    }

    @Override
    public Object intercept(Object arg0, Method method, Object[] arg2,
                            MethodProxy proxy) throws Throwable {
        ServiceFactory.before();
        Object obj = proxy.invokeSuper(arg0, arg2);
        ServiceFactory.after();
        return obj;
    }
}

测试类:
public class TestProxy {
    public static void main(String[] args) {
        // 这里使用 JDK代理  必须 通过接口 代理
        // 直接new 接口实现类   即不启用代理
        Service service = new ServiceImpl();
        Service serviceProxyJDK = (Service) new LearnProxyJDK().bind(new ServiceImpl());
        service.sayHello();
        System.out.println("-------------");
        serviceProxyJDK.sayHello();
        System.out.println("-----------");
        // 这里无论是使用接口 还是 实现类都可以接收
        // 这里我创建了接口  和实现类,都可以实现
        ServiceCglib serviceProxyCglib = (ServiceCglib) new LearnProxyCglib().bind(new ServiceCglib());
        serviceProxyCglib.sayHelloToo();
        // 这里顺便说说 spring aop 默认是jdk 的动态代理
        // 要强制使用cglib的 ,设置 proxy-target-class="true"
        // 使用aop 一般在事务控制,和 业务层控制两个地方
    }
}




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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值