【Spring教程】详解AOP的实现原理(动态代理)

4、通知(Advice)

它定义在连接点做什么,为切面增强提供织入接口。例如,日志记录、权限验证、事务控制、性能检测、错误信息检测等。

Spring切面可以应用5种类型的通知:

前置通知(Before):在目标方法被调用之前调用通知功能;

后置通知(After):在目标方法完成之后调用通知,此时不会关心方法的输出是什么;

返回通知(After-returning):在目标方法成功执行之后调用通知;

异常通知(After-throwing):在目标方法抛出异常后调用通知;

环绕通知(Around):通知包裹了被通知的方法,在被通知的方法调用之前和调用之后执行自定义的行为。

5、通知器(Advisor)

完成对目标方法的切面增强设计和关注点的设计以后,需要一个对象把它们结合起来,完成这个作用的就是Advisor。

6、代理(Proxy)

它为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理类的对象本身并不真正实现服务,而是通过调用委托类的对象的相关方法,来提供特定的服务。

三、静态代理和动态代理的区别


1、静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。

2、静态代理事先知道要代理的是什么,而动态代理不知道要代理什么东西,只有在运行时才知道。

3、静态代理,在程序运行前,代理类的.class文件就已经存在了;动态代理,在程序运行时,运用反射机制动态创建而成。

四、静态代理实例


1、举一个手机缴话费的例子,TelecomOperator 类是服务类。

package com.service;

/**

  • 定义一个电信运营商接口

*/

public interface TelecomOperator {

//查询话费余额

public void queryPhoneBal();

//缴话费

public void payPhoneBal();

}

2、TelecomOperatorImpl是实现类

package com.controller;

import com.service.TelecomOperator;

public class TelecomOperatorImpl implements TelecomOperator {

//查询话费余额

@Override

public void queryPhoneBal(){

System.out.println(“查话费方法…”);

}

//缴话费

@Override

public void payPhoneBal(){

System.out.println(“缴话费方法…”);

}

}

3、TelecomOperatorProxy是服务代理类

package com.controller;

import com.service.TelecomOperator;

/**

  • 第三方代理商

*/

public class TelecomOperatorProxy implements TelecomOperator {

private TelecomOperatorImpl telecomOperator;

public TelecomOperatorProxy(TelecomOperatorImpl telecomOperator) {

this.telecomOperator = telecomOperator;

}

//查询话费余额

@Override

public void queryPhoneBal(){

System.out.println(“切点:事务控制/日志输出”);

telecomOperator.queryPhoneBal();

System.out.println(“切点:事务控制/日志输出”);

}

//缴话费

@Override

public void payPhoneBal(){

System.out.println(“切点:事务控制/日志输出”);

telecomOperator.payPhoneBal();

System.out.println(“切点:事务控制/日志输出”);

}

}

4、TelecomOperatorTest是测试类

package com.controller;

public class TelecomOperatorTest {

public static void main(String[] args) {

TelecomOperatorImpl telecomOperator = new TelecomOperatorImpl();

TelecomOperatorProxy proxy = new TelecomOperatorProxy(telecomOperator);

proxy.queryPhoneBal();

proxy.payPhoneBal();

}

}

5、控制台输出

切点:事务控制/日志输出

查话费方法…

切点:事务控制/日志输出

切点:事务控制/日志输出

缴话费方法…

切点:事务控制/日志输出

五、aop的实现原理(动态代理)


1、JDK动态代理

package com.controller;

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

/**

  • JDK动态代理类

*/

public class TelecomOperatorJDKProxy implements InvocationHandler {

private Object target;

//返回代理对象

public Object newProxy(Object target) {

this.target = target;

return Proxy.newProxyInstance(target.getClass().getClassLoader(),

target.getClass().getInterfaces(), this);

}

/**

  • @param obj 目标对象代理类的实例

  • @param method 代理实例上调用父类方法的Method实例

  • @param args 代入到代理实例上方法参数值的数组

*/

@Override

public Object invoke(Object obj, Method method, Object[] args) throws Throwable{

Object result = null;

System.out.println(“切点:事务控制/日志输出”);

result=method.invoke(target,args);

System.out.println(“切点:事务控制/日志输出”);

return result;

}

}

package com.controller;

import com.service.TelecomOperator;

public class TelecomOperatorJDKTest {

public static void main(String[] args) {

TelecomOperatorJDKProxy proxy = new TelecomOperatorJD
KProxy();

TelecomOperator telecomOperator = (TelecomOperator)proxy.newProxy(new TelecomOperatorImpl());

telecomOperator.queryPhoneBal();

}

}

控制台输出:

切点:事务控制/日志输出

查话费方法…

切点:事务控制/日志输出

2、Cglib动态代理

package com.controller;

import org.springframework.cglib.proxy.Enhancer;

import org.springframework.cglib.proxy.MethodInterceptor;

import org.springframework.cglib.proxy.MethodProxy;

import java.lang.reflect.Method;

/**

  • Cglib动态代理类

*/

public class TelecomOperatorCglibProxy implements MethodInterceptor {

private Object target;//代理的目标对象

//创建目标对象的代理对象

public Object newProxy(Object target) {

this.target = target;

Enhancer enhancer = new Enhancer();//该类用于生成代理对象

enhancer.setSuperclass(this.target.getClass());//设置父类

enhancer.setCallback(this);//回调方法,设置回调对象为本身

return enhancer.create();//创建代理对象

}

/**

  • @param obj 目标对象代理类的实例(增强过)

  • @param method 代理实例上调用父类方法的Method实例

  • @param args 代入到代理实例上方法参数值的数组

  • @param proxy 使用它调用父类的方法

  • @throws Throwable

*/

@Override

public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值