AOP---面向切面
大致理解
面向切面【AOP】就是在不更改源代码的前提实现对内部功能的添加和更新,降低代码耦合性、提高代码复用性
AOP底层
1、AOP底层用了动态代理实现,动态代理有两种方式:【有接口的动态代理】、【无接口的动态代理】
A)、有接口的动态代理实现过程【JDK动态代理】
现有一个接口和一个对应的实现方法,想要对接口的方法进行增强功功能,平时会重新创建一个方法,然后添加功能。使用动态代理就能通过创建接口的实现类的代理对象,功能相同但是省去了创建【new】新的对象的过程
B)、无接口的动态代理实现过程【CGLIB动态代理】
现有一个类,希望不改动他的前提下增强功能和修改相关功能,普通方法是,创建一个子类继承,super.方法名重写方法更改和添加功能。使用动态代理,创建一个子类的代理对象。
实现有接口的实现类的方法增强【JDK动态代理】
创建一个类A和实现类AImpl,通过Proxy接口中的【newProxyInstance】方法实现建立需要增强的A的代理对象
在代码中
当需要对AImpl类的方法进行增强时,使用Proxy的【newProxyInstance】方法创建动态代理对象。参数介绍
ClassLoader loader【类加载器】, Class<?>[] interfaces【AImpl实现类实现的接口数组】, InvocationHandler h【接口对象】。
后面使用method.invoke得到要增强的类对象【AImpl】和需要用到的参数。在执行这一个代码的前后对方法进行更新增强内容。
这个【newProxyInstance】方法最终返回对象类型变量,将它强转为A类型的对象【a】。通过这个【a】对象调用A中的方法,填写参数,实现方法继续跑还能添加别的内容.
在method.invoke方法中可以获取方法名所以也能根据方法名做判断对应增强功能
public class JDKProxy {
public static void main(String[] args) {
// 在newProxyInstance方法中有三个参数,第一个参数是类加载器,得到当前类
// 第二个参数是一个实现类类型的数组,它里面是需要增强的方法所在类实现的接口,可以有多个
// 第三个参数就是一个InvocationHandler接口,需要进行实现,在里面创建代理对象
Class[] studentClass = {Student.class};
Student o = (Student) Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), studentClass, new InvocationHandler(){
StudentImpl studenti = new StudentImpl();
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("在增强方法前实现的功能,待增强方法名:" + method.getName());
Object invoke = method.invoke(studenti, args);
System.out.println("在增强方法后实现的功能");
return invoke;
}
});
int i = o.addAchievement(1, 2);
String name = "名字";
o.name(name);
System.out.println(i+name