面向切面

面向切面是什么

AOP即面向切面编程。

让你只专注于核心业务功能的实现,而不用花太多精力去管像日志、事务等各个项目通用的功能。

把非核心的业务逻辑抽象成一个切面,在程序运行过程中自动注入该功能,这就是面向切面,其底层是通过动态代理的机制来实现的,支持jdk和cglib两种。

将分散于业务代码各处的日志、事务、安全等功能代码抽离出成为一个单独的工具组件,在Spring的配置中将其进行声明为一个功能切面,再告诉Spring你想在哪些地方、什么时机使用这些可重用组件。

什么是代理模式?代理模式是常用的java设计模式,它的特征是代理类与委托类有同样的接口,代理类主要负责为委托类预处理消息、过滤消息、把消息转发给委托类,以及事后处理消息等。代理类与委托类之间通常会存在关联关系,一个代理类的对象与一个委托类的对象关联,代理类的对象本身并不真正实现服务,而是通过调用委托列的对象的相关方法,来提供特定服务。

按照代理类的创建时期,代理类可分为两种,第一种是静态代理,友臣古西亚UN创建或特定工具自动生成源代码,再对其编译,在程序运行之前,代理类的.class文件就已经存在了。第二种是动态代理,在程序运行时,运用反射机制动态创建而成。

静态代理通常只代理一个类,动态代理是代理一个接口下的多个实现类。静态代理事先知道要代理什么,而动态代理不需要知道代理什么,只有在运行时才知道。

JDK动态代理

1、在dao层新建一个演戏的Act接口

写出演戏的抽象方法

//演戏的接口
public interface Act {
    //抽象方法
    public void act(); //演戏的方法
}
2、在domain层新建一个演员的抽象类,名字为Actorr.class

写出演戏的抽象方法

// 演员抽象类
public abstract class Actor implements Act {

}
3、在domain层新建一个Bean类,名字为ChengLong.class

继承Actor接口,重写抽象方法

//成龙类
public class ChengLong extends Actor {

    @Override
    public void act() {
        System.out.println("我是成龙,我正在拍戏....");
    }
}
4、在proxy代理层新建一个成龙代理类,名字为ChengLongProxy

实现调用处理器InvocationHandler接口,重写抽象方法

//成龙的经纪人
public class ChengLongProxy implements InvocationHandler {

    // 目标对象,成龙经纪人目标对象肯定是成龙
    private Object targetObject;

    //传入一个代理之前的对象,返回一个被代理对象。
    public Object newProxyInstance(Object targetObject){
        this.targetObject=targetObject;

        return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
                targetObject.getClass().getSuperclass().getInterfaces(),this);
    }

    //演戏之前要做的事情
    private void beforeAct(){
        System.out.println("谈档期..");
        System.out.println("谈片酬");
        System.out.println("谈广告合作");
    }

    //演戏之后要做的事情
    private void afterAct(){
        System.out.println("谈出席首映仪式");
        System.out.println("谈出席颁奖典礼..");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        Object ret = null;

        this.beforeAct();
        ret=method.invoke(targetObject, args); //调用真正成龙演戏的方法
        this.afterAct();

        return ret;
    }
}
5、写主方法
public static void main(String[] args) {

    //创建一个没有经纪人的成龙
    Act actor = new ChengLong();
    //获得有经纪人的成龙
    actor = (Act) new ChengLongProxy().newProxyInstance(actor);
    //执行演戏方法,经纪人自动帮成龙处理演戏前后的事情,成龙只需专注演戏
    actor.act();
}
6、运行结果

在这里插入图片描述

cglib动态代理

1、在dao层新建一个演员抽象类,名字为Player.class

写出演戏的抽象方法

//演员类,是抽象类
public abstract class Player {
    //演戏的方法
    public abstract void play();
}
2、在domain层新建一个MovieStar抽象类
public abstract class MovieStar extends Player {

}
3、在domain层新建JackChen类

继承MovieStar 抽象方法

public class JackChen extends MovieStar {
    @Override
    public void play() {
        System.out.println("我是JackChen,我正在拍戏....");
    }
}
4、在proxy层新建JackChen的代理对象,名字为JackChenProxy.class

实现方法拦截器MethodInterceptor 接口

public class JackChenProxy implements MethodInterceptor {

    // 目标对象,成龙经纪人目标对象肯定是成龙
    private Object targetObject;

    //传入一个代理之前的对象,返回一个被代理对象
    public Object newProxyInstance(Object targetObject){
        this.targetObject=targetObject;
        //创建enhancer对象(增强器)
        Enhancer enhancer = new Enhancer();
        // 设置enhancer对象的父类
        enhancer.setSuperclass(this.targetObject.getClass().getSuperclass().getSuperclass());
        // 设置enhancer的回调对象
        enhancer.setCallback(this);
        // 创建代理对象
        return (Player)enhancer.create();
    }

    //演戏之前要做的事情
    private void beforeAct(){
        System.out.println("谈档期..");
        System.out.println("谈片酬");
        System.out.println("谈广告合作");
    }

    //演戏之后要做的事情
    private void afterAct(){
        System.out.println("谈出席首映仪式");
        System.out.println("谈出席颁奖典礼..");
    }

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
        Object ret = null;
        this.beforeAct();

        //调用成龙真正的演戏方法
        ret =method.invoke(this.targetObject,objects);

         this.afterAct();
        return ret;
    }
}
5、写主方法
public static void main(String[] args) {
        //通过cglib实现的动态代理
        //没有经纪人的JackChen对象
         Player actor = new JackChen();
        //获得有经纪人的JackChen
        actor = (Player) new JackChenProxy().newProxyInstance(actor);
         actor.play();
    }
7、运行程序,输出结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值