Spring Aop基本原理 --- 代理模式(浅谈以及代码实现)

Spring的Aop(Aspect-Oriented Programming)面向方面编程,其基本原理主要是代理模式的机制,“代理模式” 使用代理对象完成用户请求,屏蔽用户对真实对象的访问,对目标类进行功能增强,在某个方法的执行前后增加一些操作。通俗的说就是,比如校长需要向所有学生传达一个信息,校长会通过班主任老师告诉学生,而校长和学生之间没有存在沟通。老师就起到一个代理的作用。

代理方式:静态代理;动态代理 (基于JDK的动态代理;基于Cglib的动态代理),如下所示:

1.静态代理

静态代理,个人理解可以用 “同一接口,代理注入”来概括,一组代理实现,代理类和目标实现类需要实现同一接口,代理类必须注入目标实现类中,具体可查看如下示例:

public interface IAopPory {
    public void testAop();
}

public class A implements IAopPory {
    @Override
    public void testAop() {
        System.out.println("代理实现");
    }
}

public class B implements IAopPory {
    private A a;
    public B(A a) {
        this.a = a;
    }
    
    @Override
    public void testAop() {
        
        System.out.println("调用之前执行。。。可以写自己的方法");
        a.testAop();
        System.out.println("调用之后执行。。。写自己的处理方法");
    }
    
}

/**
 * 静态代理方式
 * A和B实现同一接口,B中注入A的实例,在重写testAop方法时,调用A的testAop方法,同时可在B类的* 
 * testAop方法中扩展自己所需的内容 
 * */
public class Test {
    public static void main(String[] args) {
        A a = new A();
        B bb = new B(a);
        bb.testAop();
    }
}

 静态代理存在的问题:
 (1)通过上面的示例可以看出,代理对象需要与目标对象实现一样的接口,所以会有很多代理类,类太多,不利于管理,且容易造成代码混乱
 (2)实现同一个接口,接口增删方法,目标对象与代理对象都要维护.

2.基于jdk的动态代理

  实现步骤:

(1)目标对象必须实现接口(可以多个)

(2)调用实现 Proxy.newProxyInstance(目标对象的classloader,目标对象的实现接口, new InvocationHandler(){});

(3)invoke()的重写

public interface IPory {
    public void add();
}

public interface InterfaceAop {
    public void delete();
}

public class A implements IPory ,InterfaceAop {
    @Override
    public void add() {
        
        System.out.println("添加成功");
    }
    
    @Override
    public void delete() {
        
        System.out.println("删除成功");
    }
}


public class ProxyFactory {
    private Object target;
    public ProxyFactory(Object target) {
        
        this.target = target;
    }
    
    public Object getProxyInstance(){
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),
                target.getClass().getInterfaces(), new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args)
                            throws Throwable {
                        if(method.getName().equals("add")){
                            System.out.println("判断方法啊等等--"+method.getName());
                        }
                        if(method.getName().equals("delete")){
                            System.out.println("判断方法啊等等--"+method.getName());
                        }
                        System.out.println("动态代理执行方法之前"+method.getName());
                        Object returnValue = method.invoke(target, args);
                        System.out.println("动态代理执行方法之后"+method.getName());
                        return returnValue;
                    }
                });
        
    }
    

   
    public static void main(String[] args) {
        ProxyFactory pf = new ProxyFactory(new A());
	    IPory aa = (IPory) pf.getProxyInstance();
		InterfaceAop aa2 = (InterfaceAop) pf.getProxyInstance();
		aa.add();
        //强转目标对象A,报错类型转换异常
        A a = (A) pf.getProxyInstance();    
    }
    
}

jdk动态代理不足:

JDK 的动态代理机制是单一代理机制的,它只能代理被代理类的接口集合中的方法,如上示例,getProxyInstance() 生成后的代理类的实例是无法强转为A类型的,只能转成接口之一,这说明其代理的方式是单一的,在任何一种情况下,只能使用某一个接口的功能,而无法同时使用多接口功能。

3.基于Cglib的动态代理

Cglib原理是针对目标类生成一个子类,覆盖其中的所有方法,所以目标类和方法不能声明为final类型

public class CglibDAO {
    public void update(){
        System.out.println("cglib -- update");
    }
}

/**
 * cglib 方式创建代理模式 -子类代理
 * 
 * */
public class CglibProxyFactory implements MethodInterceptor{
    private Object cgDao;
    public CglibProxyFactory(Object cgDao) {
        this.cgDao = cgDao;
    }
    
    public Object getProxyInstance(){
        //工具类
        Enhancer en = new Enhancer();
        //设置父类
        en.setSuperclass(cgDao.getClass());
        //设置回调函数
        en.setCallback(this);
        //创建子类
        return en.create();
    }
    
    @Override
    public Object intercept(Object arg0, Method arg1, Object[] arg2,
            MethodProxy arg3) throws Throwable {
        System.out.println("开始。。。。");
        Object returnValue = arg1.invoke(cgDao, arg2);
        System.out.println("结束。。。。");
        return returnValue;
    }
}

/**
 *  1.代理对象,不需要实现接口
    2.代理对象的生成,是利用JDK的API,动态的在内存中构建代理对象(需要我们指定创建代理对象/目标对象实现的接口的类型)
    3.动态代理也叫做:JDK代理,接口代理
 * */
public class Test {
    public static void main(String[] args) {
        CglibDAO c = (CglibDAO) new CglibProxyFactory(new CglibDAO())         
                     .getProxyInstance();
        c.update();
    }
}

 

  • 4
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值