AOP面向切片编程,实现原理就是动态代理,动态代理又分为JDK动态代理和CGLIB动态代理。
1,JDK动态代理智能实现对接口的代理
- public class UserManagerImpl implements UserManager {
- @Override
- public void addString userId, String userName) {
- System.out.println("UserManagerImpl.addUser");
- }
- @Override
- public void dellet(String userId) {
- System.out.println("UserManagerImpl.delUser");
- } }
//动态代理类只能代理接口(不支持抽象类),代理类都需要实现InvocationHandler类,实现invoke方法。该invoke方法就是调用被代理接口的所有方法时需要调用的,该invoke方法返回的值是被代理接口的一个实现类
- public class LogHandler implements InvocationHandler {
- private Object targetObject;
- //绑定关系,也就是关联到哪个接口(与具体的实现类绑定)的哪些方法将被调用时,执行invoke方法。
- public Object newProxyInstance(Object targetObject){
- this.targetObject=targetObject;
- //该方法用于为指定类装载器、一组接口及调用处理器生成动态代理类实例
- //第一个参数指定产生代理对象的类加载器,需要将其指定为和目标对象同一个类加载器
- //第二个参数要实现和目标对象一样的接口,所以只需要拿到目标对象的实现接口
- //第三个参数表明这些被拦截的方法在被拦截时需要执行哪个InvocationHandler的invoke方法
- //根据传入的目标返回一个代理对象
- return Proxy.newProxyInstance(targetObject.getClass().getClassLoader(),
- targetObject.getClass().getInterfaces(),this);
- }
- @Override
- //关联的这个实现类的方法被调用时将被执行
- /*InvocationHandler接口的方法,proxy表示代理,method表示原对象被调用的方法,args表示方法的参数*/
- public Object invoke(Object proxy, Method method, Object[] args)
- throws Throwable {
- System.out.println("start-->>");
- for(int i=0;i<args.length;i++){
- System.out.println(args[i]);
- }
- Object ret=null;
- try{
- /*原对象方法调用前处理日志信息*/
- System.out.println("satrt-->>");
- //调用目标方法
- ret=method.invoke(targetObject, args);
- /*原对象方法调用后处理日志信息*/
- System.out.println("success-->>");
- }catch(Exception e){
- e.printStackTrace();
- System.out.println("error-->>");
- throw e;
- }
- return ret;
- }
- }
被代理对象targetObject通过参数传递进来,我们通过targetObject.getClass().getClassLoader()获取ClassLoader对象,然后通过targetObject.getClass().getInterfaces()获取它实现的所有接口,然后将targetObject包装到实现了InvocationHandler接口的LogHandler对象中。通过newProxyInstance函数我们就获得了一个动态代理对象。
- public class Client {
- public static void main(String[] args){
- LogHandler logHandler=new LogHandler();
- UserManager userManager=(UserManager)logHandler.newProxyInstance(new UserManagerImpl());
- //UserManager userManager=new UserManagerImpl();
- userManager.addUser("1111", "张三");
- }
- }
-
CGLIB可以接口可以类
cglib的代理方式不需要传入被代理对象实例即可完成动态代理。cglib和jdk代理有什么区别呢?jdk的代理对象与被代理对象实现了同一接口,底层通过clone()方法,将实现类的方法复制过来在按照invoke中的配置对方法进行增强。而cglib代理则是代理对象继承了被代理对象的方法,然后自身进行增强。这两种代理思想在外来的自动生成代码方向会经常被使用,实现完全体代码的复用性。