今天的主要内容:
全是干货,整理不易!请各位走过路过点点赞!
例子中使用的代码大家可以随意自取。适合学习了java反射机制的同学观看 ,如果没有学习过,我的博客主页中有java的反射机制的我自己整理的学习日记可供观看嗷
今天我们要浅层理解AOP,对我一个第一次接触这个东西的萌新有点慌
总结的东西可能有不对的地方希望路过的大神能够指出!感激不尽!
理解面向切面编程AOP:
AOP全称:Aspect Oriented Programming
将散落在业务逻辑各个角落的、具有横切性特点的代码在合适的切入点、合适的时机切入到目标代码的执行过程中去,实现与业务逻辑的分离、解耦,更加便于维护、管理
反射机制->动态代理模式->AOP
java中动态代理模式的实现:
动态代理的核心类及接口:
java.lang.reflect.InvocationHandler
java.lang.reflect.Proxy
接下来我们就用一个买房子的例子来解释什么是动态代理模式:
我们用到三个类,一个接口:
1.Owner类:找代理人的人,业主
2.Buyable接口:代理人能做的方法,也是要被横向织入的各种方法的集合
所以这里Owner implements Buyable
3.OwnerProxyInvocationHandler类:业主代理的调用处理器
一般这个代理类都要实现一个接口叫InvocationHandler
通俗的将这个类是用来实现横向织入过程的,将业主要
被代理使用但不更改原来方法的动作在这个类里待命
4.Test类:功能测试类
这次例子的主要实现逻辑(重要!必看!):
首先我们创建一个Owner类,也就是业主类,业主类接上Buyable能力的接口,
得到Buyable接口中的方法,然后我们编写一个OwnerProxyInvocationHandler
类,这个类将业主需要找代理商去做的事情以自己的方式在保留业主的原来方法
的情况下做出来,然后在测试类里面创建一个代理人,这个代理人实例一般都是
业主的能力接口的对象。好下面我们开始。
本次动态代理例子中重要的几个方法 (重要!可以与代码一起看):
1.Proxy.newProxyInstance(ClassLoader loader, Class> interfaces, InvocationHandler h)
第一个参数:类加载器,就是我们当前所在类的加类载器,例子中为Test.getClass().getClassLoader()
第二个参数:被代理目标的所有接口,例子里是o1.getClass.getInterfaces()
第三个参数:代理对象的方法要被哪个类处理就填谁,例子中为new OwnerProxyInvcationHandler(o1)
2.public Object invoke(Object proxy, Method method, Object[] args) throws Throwable他是InvocationHandler接口中需要重写的方法,也是横向织入的核心方法。
第一个参数:可以将代理对象返回以进行连续调用,且不断允许反射产生Proxy实例。
第二个参数:我们需要被代理的哪个对象的方法那个方法被Method封装成了一个对象
第三个参数:被代理的方法参数
废话不多说!上代码!(结合前边知识点看效果更佳)
Owner类:
package LessonForDynamicProxyPattern;
//Owner类此时为被代理对象!
public class Owner implements Buyable
{
@Override
public void payCash()
{
System.out.println("---调用payCash()方法---");
}
@Override
public int makeMoney(int amount)
{
System.out.println("---调用makeMoney(int amount)方法---");
return amount*1000;
}
}
OwnerProxyInvocationHandler类:
package LessonForDynamicProxyPattern;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class OwnerProxyInvcationHandler implements InvocationHandler
{
/*
*public Object invoke(Object proxy, Method method, Object[] args) throws Throwable方法
* 第一个参数:产生了代理实例
* 第二个参数:我们需要被代理的那个方法的对象,那个方法被Method封装成一个对象
* 第三个参数:被代理的方法的参数
*/
private Object target;//帮忙代理的代理目标
public OwnerProxyInvcationHandler(Object target)
{
super();
this.target = target;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
System.out.println("被代理的方法执行前。。。。。");
Object result = method.invoke(target, args);
/*
* 这里第一个参数:是被代理目标
* 这里第二个参数:是被代理方法的参数,如果没有就这样摆着就行了
* 这里有返回值,返回值是什么呢,是被我们代理的目标方法的返回值,我们具体情况具体向下转型
*/
System.out.println("被代理方法执行之后我标记了一下");
/*
* 28~35行就是AOP的横切面逻辑,目标方法执行前我们要求有动作,目标方法执行后我们也要求有动作
* 但是这些前后要执行的动作没有被硬写到被代理的目标对象的那个方法中去,实现松耦合
*/
return result;
}
}
Buyable接口:
package LessonForDynamicProxyPattern;
public interface Buyable //核心业务接口
{
public void payCash();
public int makeMoney(int amount);
}
Test类:
package LessonForDynamicProxyPattern;
import java.lang.reflect.Proxy;
public class Test
{
public static void main(String[] args)
{
Owner o1 = new Owner();//找代理人的人
/*
*Proxy.newProxyInstance(ClassLoader loader, Class>[] interfaces, InvocationHandler h)
* 第一个参数:类加载器,就是我们当前的类,此时为Test.class.getClassLoader()
* 第二个参数:被代理目标的所有接口。在这个例子中为o1.getClass().getInterfaces()
* 第三个参数:代理对象的方法被代理之后。例子中为new OwnerProxyInvcationHandler(o1)
*
* newProxyInstance返回的就是我们的代理对象实例,一般要为我们的接口
*/
Buyable by1 = (Buyable)Proxy.newProxyInstance(Test.class.getClassLoader(),
o1.getClass().getInterfaces(),
new OwnerProxyInvcationHandler(o1));//新创建一个“代理人”实例
by1.payCash();//动态织入过程
System.out.println("----------------------------------");
int rent = by1.makeMoney(10);
System.out.println(rent);
}
}
部分文字来源于:
咕嘟咖啡杨海滨老师 — 《java编程语言高级特性》
在这里十分感谢老师能够给我带来学习的激情.
毕!
2020.10.08