AOP理解与实践分析




AOP:Aspect Oriented Programming 面向切面编程,在Spring框架中被作为核心组成部分之一,最常见的就是事务控制,主要通过利用代理模式来实现。
代理原理说明:
当客户端调用代理对象的业务方法的时候,代理对象将拦截所有业务方法,根据事先给出的权限规则,判断当前请求是否符合权限要求,在符合条件的情况下,再将业务方法委派给目标对象,执行方法体,实现事务控制管理(如图过程趋势大致走向)。



常见的三大代理模式:举例介绍&(附注释说明)

1、静态代理:即设计模式中的Proxy模式,example:
<1>业务接口:

public interface InterfaceProxy {
    public String save(String name);
}
<2>业务实现(省略):
<3>代理对象:
/**
 * 静态代理:要代理的类是自己写的,要实现代理功能,必须实现要代理的那个目标对象的接口
 * 代理模式:为一些对象加入代理,以控制该对象的访问
 * @author zhoujh
 */
public class StaticProxyFactory implements InterfaceProxy{
    
    //要代理的目标对象
    private InterfaceProxy target;
    
    public StaticProxyFactory(InterfaceProxy target){
        this.target = target;
    }

    @Override
    public String save(String name) {
        target.save(name);//组合代理要实现的目标对象接口方法
        return name;
    }

}


2、动态代理:jdk1.5中提供,利用反射,实现InvocationHandler接口。

/**
 * JDK提供Proxy类创建动态代理对象
 * 通过代理对象实现目标对象的所有接口,能将方法的调用委派给目标对象
 * 使用代理类Proxy:应用的条件是目标对象必须是面向接口的,否则是不能应用JDK动态代理的 横切性关注点
 * 应用原理:当客户端调用代理对象的业务方法的时候,代理对象就会执行invoke方法,执行过程中再将该方法委派给目标对象
 * @author zhoujh
 */
public class JDKProxyFactory implements InvocationHandler {
    public Object targetObject;

    public Object createProxyInstance(Object targetObject) {
        this.targetObject = targetObject;

        /**
         * new一个代理实例
         *
         * @param1:目标对象的类加载器
         * @param2:目标对象的所有接口
         * @param3:当前类实例本身:Handler(回调) 该参数表示接口
         *                             同时要求该回调实例必须实现InvocationHandler这个接口
         */
        return Proxy.newProxyInstance(this.targetObject.getClass()
                .getClassLoader(),
                this.targetObject.getClass().getInterfaces(), this);
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        InterfaceProxyIntance bean = (InterfaceProxyIntance)this.targetObject;
        Object result = null;
        if(bean.getUser()!= null){//代表该用户有权限,允许执行业务方法
            result = method.invoke(targetObject, args);
        }
        return result;
    }
}
  
3.利用cglib框架实现动态代理

/**
 * CGlib动态代理
 * @author zhoujh
 *
 */
public class CglicProxyFactory {
    
    //使用CGlib生成动态代理对象
    public  Object createProxyInstance(final Object target){
        
        //加强 Proxy增加者
        Enhancer enhancer = new Enhancer();
        
        //指定目标对象作为代理对象的父类
        enhancer.setSuperclass(target.getClass());
        
        //定义回调方法
        Callback callback = new MethodInterceptor() {
            
            @Override
            public Object intercept(Object arg0, Method arg1, Object[] arg2,
                    MethodProxy method) throws Throwable {
                Object result = null;
                System.out.println("begin....");
                result = method.invoke(target, arg2);
                System.out.println("end....");
                return result;
            }
        };
        //设置回调方法
        enhancer.setCallback(callback);
        
        //创建代理对象并返回
        return enhancer.create();
        
    }
}


4.普通类(非接口实现类):

public class RunnerService {
    public void add(String name){
        System.out.println("前方高能"+name);
    }
}

5.接口实现类:
public class InterfaceProxyIntance implements InterfaceProxy{
    private String user = null;
    
    
    public String getUser() {
        return user;
    }
    public InterfaceProxyIntance(){}
    public InterfaceProxyIntance(String user){
        this.user = user;
    }
    public String read() {
        return "read()";
    }

    public String save(String name) {
        return name;
    }

}

6.测试:

public class ProxyTest {
public static void main(String[] args) {
    
    //静态代理Test
    StaticProxyFactory factory1 = new StaticProxyFactory(new InterfaceProxyIntance("hehe"));
    System.out.println(factory1.save("888"));
    
    //JDK动态代理Test
    JDKProxyFactory factory = new JDKProxyFactory();
    /**
     * 注意:这里要通过接口去引用代理对象,因为该代理对象是实现了接口的
     */
    InterfaceProxy proxy = (InterfaceProxy)factory.createProxyInstance(new InterfaceProxyIntance("xxx"));
    System.out.println(proxy.save("888"));
    
    
    //CGlib框架动态代理Test
    CglicProxyFactory cg = new CglicProxyFactory();
    InterfaceProxy proxy1 = (InterfaceProxy)cg.createProxyInstance("");
    System.out.println(proxy1.save("8888"));
    
    
    //非接口实现下的CGlib代理实现
    RunnerService service = new RunnerService();
    CglicProxyFactory cg1 = new CglicProxyFactory();
    RunnerService service1 = (RunnerService)cg1.createProxyInstance(service);
    service1.add("888");

     }
}


spring对AOP的支持

    *如果目标对象实现了接口,默认情况下会采用JDK的动态代理实现AOP
    *如果目标对象实现了接口,可以强制使用CGLIB实现AOP
    *如果目标对象没有实现了接口,必须采用CGLIB库,spring会自动在JDK动态代理和CGLIB之间转换



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值