面向切面是什么
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 {@Overridepublic 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("谈出席颁奖典礼..");}@Overridepublic 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 {@Overridepublic 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("谈出席颁奖典礼..");}@Overridepublic 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();//获得有经纪人的JackChenactor = (Player) new JackChenProxy().newProxyInstance(actor);actor.play();}