代理:
代理模式最主要的就是在不改变原来代码(就是目标对象)的情况下实现功能的增强
在学习AOP之前先了解代理,代理有两种:一种是动态代理,一类是静态代理。
静态代理
相当于是自己写了一个代理类,在调用的时候调用的是代理类,代理类中的处理还是原生的处理逻辑,不过在前后添加上需要增强功能的代码。(类似继承实现的)
缺点:需要为每一个被代理的对象都创建一个代理类。
静态代理实现:
1.创建接口
public interface Target {public abstract String getExe();
}
2.实现目标对象
public class MyTarget implements Target {@Overridepublic String getExe() {System.out.println("执行ing.....");return "ok";}
}
3.实现代理对象
package 反射;public class Proxy implements Target{MyTarget myTarget;public Proxy(MyTarget myTarget) {this.myTarget = myTarget;}@Overridepublic String getExe() {System.out.println("权限检查");String res= myTarget.getExe();System.out.println("日志打印");return res;}
}
4.测试代码
package 反射;public class demo1 {public static void main(String[] args) {MyTarget myTarget=new MyTarget();Proxy proxy = new Proxy(myTarget);proxy.getExe();}}
动态代理
动态代理模式最大的优势就是不用自己去写一个代理对象,它的代理对象会在java文件编译的时候,通过Java反射去创建的。所以减少了程序员的工作。动态代理的实现有两种方式,现在来介绍一下(基于接口实现)
jdk代理
1.创建接口
package com.aqiuo.jdk;public interface UserDao {public void addUser();public void deleteUser();
}
2.创建实现类
package 代理;public class UserServiceImpl implements UserService{public void addUser(){System.out.println("添加用户");}public void delUser(){System.out.println("删除用户");}}
3.编写切面类
package 代理;public class Aspect {public void admission(){System.out.println("权限检查");}public void log(){System.out.println("日志打印");}
}
4.编写代理类
package 代理;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class JdkProxy implements InvocationHandler {//用Object型才能动态代理Object object;public Object createInstance(Object object){this.object=object;Class[] clazz = object.getClass().getInterfaces();ClassLoader classLoader=JdkProxy.class.getClassLoader();return Proxy.newProxyInstance(classLoader,clazz,this);}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Aspect aspect=new Aspect();aspect.admission();Object res= method.invoke(object,args);aspect.log();return res;}
}
5.测试:
public class Test {public static void main(String[] args) {JdkProxy jdkProxy =new JdkProxy();UserService userService=new UserServiceImpl();UserService proxy= (UserService) jdkProxy.createInstance(userService);proxy.addUser();;proxy.delUser();}
}
/**JDK代理有一定局限性,使用动态代理的对象必须实现一个或多个接口,如果要对没有实现接口的类进行代理,可以用CGLIB代理
CGLIB代理
CGLIB是一个高性能的开源代码生成包,采用非常底层的字节码技术,对指定的目标类生成一个子类,并对子类增强,已经在Spring中集成
导包
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>2.2.2</version>
</dependency>
MethodInterceptor拦截器
cglib的实现最重要的就是去实现这个MethodInterceptor接口来完成,就像jdk时候的InvocationHandler一样
package com.aqiuo.cglib;
//被代理的类
public class UserDao {public void addUser() {// TODO Auto-generated method stubSystem.out.println("添加用户");}public void deleteUser() {// TODO Auto-generated method stubSystem.out.println("删除用户");}}
实现代理类
//代理类
package com.aqiuo.cglib;import java.lang.reflect.Method;import org.springframework.cglib.proxy.Enhancer;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;import com.aqiuo.Aspect.MyAspect;public class CglibProxy implements MethodInterceptor {//代理方法public Object createProxy(Object target) {//创建一个动态类对象Enhancer enhancer=new Enhancer();//确定要增强的类,设置为她的父类enhancer.setSuperclass(target.getClass());//添加回调函数enhancer.setCallback(this);//返回创建的代理类return enhancer.create();}/*** ProxyCGlib根据指定的父类,生成代理对象* method拦截的方法* args拦截方法的参数数组* methodProxy方法的代理对象,用来执行父类方法*/@Overridepublic Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {//创建切面类对象MyAspect myAspect=new MyAspect();//前增强myAspect.check_permissions();//目标方法执行Object object=methodProxy.invokeSuper( proxy, args);//后增强myAspect.log();return object;}}
cglib的原理就是在运行的时候,cglib会自动去生成一个子类,在子类里面去完成增强操作(就是拦截器里面),这里我们来验证cglib就用保存它的子类来查验,也就是将它自动生成的类放在一个指定路径下去看。
//测试类
package com.aqiuo.cglib;public class CglibTest {public static void main(String[] args) {UserDao userDao=new UserDao();CglibProxy proxy=new CglibProxy();UserDao userDao2=(UserDao) proxy.createProxy(userDao);userDao2.addUser();userDao2.deleteUser();}}
cglib动态代理原理:
①创建拦截器:继承MethodInterceptor的 intercepter的类,在拦截器中重写intercerpt( )方法,就是增强+目标对象的方法调用,返回拦截器②在测试这边创建一个类似proxy的子类对象enhancer,然后设置这个代理对象的类型(setSuperclass(目标对象的类型.class完成))
③创建一个拦截器,enhancer通过去设置回调函数(setCallback(拦截器))
④创建代理对象enhancer.create(),代理对象的类型要和目标对象一致哈,然后通过代理对象去完成方法的调用