黑马程序员-代理和AOP

来源:互联网 发布:a星算法的优缺点 编辑:程序博客网 时间:2024/06/07 07:45

       ------------- android培训java培训、java学习型技术博客、期待与您交流! ------------
 

         纠结了2周的代理, 终于在今晚告一段落了,  废话不多说,开始总结:

        所谓的代理,其实就是通过一个对象去调用其封装好的某一个方法,它在其他类的各个方法中增加了一些系统功能,例如,异常处理、日志、计算方法的运行时间、事物管理、等等。

        通常情况下,我们都是采用动态代理,我们可以自定义一个目标类,借由代理类来实现它。

        编写一个与目标类具有相同接口的代理类,代理类的每个方法调用目标类的相同方法,并在调用方法时加上系统功能的代码。

        如果采用工厂模式和配置文件的方式进行管理,则不需要修改客户端程序,在配置文件中配置是使用目标类、还是代理类,这样以后很容易切换,譬如,想要日志功能时就配置代理类,否则配置目标类,这样,增加系统功能很容易,以后运行一段时间后,又想去掉系统功能也很容易。

        代理分为两种,静态代理以及动态代理
        
        静态代理:
        系统中的各种接口的类增加代理功能,那将需要太多的代理类,全部采用静态代理方式,也就是说,我们需要一个个的将类写死,比如说要实现什么样的接口,接口里所带的参数等等, 要写死,这样很不利于开发。
        
        动态代理:
        于是就产生出了动态代理的概念,由我们自己去配置一个类,交由Java虚拟机去识别。(请看概念)
        JVM可以在运行期动态生成出类的字节码,这种动态生成的类往往被用作代理类,即动态代理类。
        JVM生成的动态类必须实现一个或多个接口,所以,JVM生成的动态类只能用作具有相同接口的目标类的代理。
CGLIB库可以动态生成一个类的子类,一个类的子类也可以用作该类的代理,所以,如果要为一个没有实现接口的类生成动态代理类,那么可以使用CGLIB库。
        代理类的各个方法中通常除了要调用目标的相应方法和对外返回目标返回的结果外,还可以在代理方法中的如下四个位置加上系统功能代码:
        1.在调用目标方法之前
        2.在调用目标方法之后
        3.在调用目标方法前后
        4.在处理目标方法异常的catch块中
  

        获取代理类

//,
Class clazzProxy1 = Proxy.getProxyClass(Collection.class.getClassLoader(), Collection.class);   //打印结果是 $Proxy0
 

       获取代理类的构造方法

        Constructor[] constructors = clazzProxy1.getConstructors(); //
        
        for(Constructor constructor : constructors){
            
            String name = constructor.getName(); //
            
            StringBuilder sBuilder = new StringBuilder(name); //
            
            sBuilder.append('(');
            
            Class[] clazzParams = constructor.getParameterTypes(); //
            
            for(Class clazzParam : clazzParams){
                
                sBuilder.append(clazzParam.getName()).append(',');
                
            }
            
            if(clazzParams!=null && clazzParams.length != 0)  // 
            
                sBuilder.deleteCharAt(sBuilder.length()-1);
                
            sBuilder.append(')');
            
            System.out.println(sBuilder.toString());//  xxx(xx);
            
            //$Proxy0(java.lang.reflect.InvocationHandler)  
            
            //InvocationHandler ,
            
            //,InvocationHandler
            
        }
 

        返回代理类里的各个方法

        for(Method method : methods){
            
            String name = method.getName();
            
            StringBuilder sBuilder = new StringBuilder(name);
            
            sBuilder.append('(');
            
            Class[] clazzParams = method.getParameterTypes();
            
            for(Class clazzParam : clazzParams){
                
                sBuilder.append(clazzParam.getName()).append(',');
                
            }
            if(clazzParams!=null && clazzParams.length != 0)
            
                sBuilder.deleteCharAt(sBuilder.length()-1);
                
            sBuilder.append(')');
            
            System.out.println(sBuilder.toString());    
            
        }  //代码同构造方法  不做解释
         
        创建代理的实例化对象  以Collection 为例
    
 
    class MyInvocationHander1 implements InvocationHandler{
        
            public Object invoke(Object proxyMethod methodObject[] args)
                    throws Throwable {
                        
                // TODO Auto-generated method stub
                return null;
            }
        
        }
        Collection proxy1 = (Collection)constructor.newInstance(new MyInvocationHander1());
        
        //InvocationHandlder,
        
        //InvocationHandlder
        
        System.out.println(proxy1);
        
        proxy1.clear();
        
//      proxy1.size();  //,invokenull
 
 
        Collection proxy2 = (Collection)constructor.newInstance(new InvocationHandler(){ //
            public Object invoke(Object proxyMethod methodObject[] args)
                    throws Throwable {
                        
                return null;
            }
            
        });  //同上 不解释
 
 
 
/*
    ,  
*/
Collection proxy3 = (Collection)Proxy.newProxyInstance(
    
                Collection.class.getClassLoader(),   //目标类的类加载器
                
                new Class[]{Collection.class},  //目标类
                
                new InvocationHandler(){
                    
                    ArrayList target = new ArrayList();   
                    
                    public Object invoke(Object proxyMethod methodObject[] args)
                            throws Throwable {
                        
                        System.out.println("ArrayListHashCode: "+target.hashCode());
                        
                        Object retVal = method.invoke(targetargs); 
                        
                        System.out.println(retVal.getClass().getName());
                        
                        return retVal;                      
                    }
                }
                );
        
        proxy3.add("zxx"); //addinvoke
        
        proxy3.add("lhm");
        
        proxy3.add("bxd");
        
        System.out.println(proxy3.size());
        
        //System.out.println(proxy3.getClass().getName());());
        
        //objecthashCode equals toStringInvocationHandler 
 
        为代理添加一些自定义的功能,那么,这个接口我们可以自定义,比如:计算方法的时间
        首先需要一个接口。
public class ProxyFactoryBean {
    private Advice advice;  //
    
    private Object target//
    
    
    public Advice getAdvice() {
        return advice;
    }
    public void setAdvice(Advice advice) {
        this.advice = advice;
    }
    public Object getTarget() {
        return target;
    }
    public void setTarget(Object target) {
        this.target = target;
    }
    public Object getProxy() {
        
        // TODO Auto-generated method stub
        Object proxy3 = Proxy.newProxyInstance(
            
                target.getClass().getClassLoader(), //
                
                target.getClass().getInterfaces(),//
                
                new InvocationHandler(){
                
                    public Object invoke(Object proxyMethod methodObject[] args)
                            throws Throwable {
                        advice.beforeMethod(method); //,
                        
                        //invoke,,set
                        
                        //set使
                        
                        Object retVal = method.invoke(targetargs);
                        
                        advice.afterMethod(method); //
                        
                        return retVal;                      
                        
                    }
                }
                );
        return proxy3;
    }
}
 
 AOP的定义
Spring框架里有一个AOP的概念, 所以的AOP,是面向切面的编程, 也就是说,在框架的基础上添加事物等一系列的功能。

 
根据配置文件获取到动态代理的例子:
 
public class ProxyFactoryBean {
    private Advice advice//
    
    private Object target//
    
    public Advice getAdvice() {
        
        return advice;
    }
    public void setAdvice(Advice advice) {
        
        this.advice = advice;
    }
    public Object getTarget() {
        
        return target;
    }
    public void setTarget(Object target) {
        
        this.target = target;
    }
    public Object getProxy() {  //同上, 不解释
        Object proxy3 = Proxy.newProxyInstance(
            
                target.getClass().getClassLoader(),
        
                target.getClass().getInterfaces(),
                
                new InvocationHandler(){
                
                    public Object invoke(Object proxyMethod methodObject[] args)
                            throws Throwable {
                        advice.beforeMethod(method);
                        
                        Object retVal = method.invoke(targetargs);
                        
                        advice.afterMethod(method);
                        
                        return retVal;                      
                        
                    }
                }
                );
        return proxy3;
    }
 
 
 
public class BeanFactory {
    
    Properties props = new Properties();
    
    public BeanFactory(InputStream ips){
        
        try {
            
            props.load(ips);  //
            
        } catch (IOException e) {
            
            e.printStackTrace();
        }
    }
    
    public Object getBean(String name){ //
        
        String className = props.getProperty(name); 
        
        Object bean = null;
        
        try {
            
            Class clazz = Class.forName(className); //,
            
            //,BEAN
            
            bean = clazz.newInstance();
            
        } catch (Exception e) {
            
            e.printStackTrace();
        } 
        
        if(bean instanceof ProxyFactoryBean){
            
            Object proxy = null;
            
            ProxyFactoryBean proxyFactoryBean = (ProxyFactoryBean)bean//
            
            try {
                
                //
                
                Advice advice = (Advice)Class.forName(props.getProperty(name + ".advice")).newInstance();
                
                //
                
                Object target = Class.forName(props.getProperty(name + ".target")).newInstance();
                
                //set
                
                proxyFactoryBean.setAdvice(advice);
                
                proxyFactoryBean.setTarget(target);
                
                //,
                
                proxy = proxyFactoryBean.getProxy();
                
            } catch (Exception e) {
                
                e.printStackTrace();
                
            }
            
            return proxy;
            
        }
        
        return bean;
        
    }
    
}
 
 

------------- android培训java培训、java学习型技术博客、期待与您交流! ------------

详情请查看:http://edu.csdn.net/

 

原创粉丝点击