面向切面是什么
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();
}