分享

Spring的AOP-Java的代理机制

 樱花梦_张艺馨 2018-12-10

AOP的基本思想

AOP的意思是面向方面编程,英文全称:Aspect Oriented ProgrammingAOP能够降低代码的耦合性,使得代码易于维护和重(chong)用,一个应用程序分为核心关注点和横切关注点。核心关注点和具体应用的功能相关,而横切关注点存在于整个系统的范围内。SpringAOP是建立在Java的代理机制之上的。

Java的代理机制

通用的日志输出方法

============TimeBook==============

package com.gc.action.book;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

public class TimeBook {

    private  Logger logger = Logger.getLogger(this.getClass().getName());

    public void doAuditing(String name){

       System.out.println(logger);

       logger.log(Level.INFO,name +"开始。。。");

       System.out.println("=================");

       logger.log(Level.INFO,name +"结束。。。");

    }

}

=============TestTimeBook============

package com.gc.action.book;

 

public class TestTimeBook {

 

    public static void main(String[] args) {

       TimeBook timeBook = new TimeBook();

       timeBook.doAuditing("zx");

    }

}

========log4j.properties 配置文件===================

# Set root category priority to INFO and its only appender to CONSOLE.

log4j.rootCategory=INFO, CONSOLE

#log4j.rootCategory=INFO, CONSOLE, LOGFILE

 

# Set the enterprise logger category to FATAL and its only appender to CONSOLE.

log4j.logger.org.apache.axis.enterprise=FATAL, CONSOLE

 

# CONSOLE is set to be a ConsoleAppender using a PatternLayout.

log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender

log4j.appender.CONSOLE.Threshold=INFO

log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout

log4j.appender.CONSOLE.layout.ConversionPattern=- %m%n

 

# LOGFILE is set to be a File appender using a PatternLayout.

log4j.appender.LOGFILE=org.apache.log4j.FileAppender

log4j.appender.LOGFILE.File=axis.log

log4j.appender.LOGFILE.Append=true

log4j.appender.LOGFILE.Threshold=INFO

log4j.appender.LOGFILE.layout=org.apache.log4j.PatternLayout

log4j.appender.LOGFILE.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

==================结果===============

org.apache.log4j.Logger@1ddc4ec2

- zx开始。。。

=================

- zx结束。。。

通过面向接口编程实现日志输出

============接口TimeBookInterface====================

package com.gc.action.impl;

public interface TimeBookInterface {

    //通过面向接口编程实现日志输出

    public void doAuditing(String name);

}

============接口实现TimeBookImpl=======================

package com.gc.action.impl;

public class TimeBookImpl implements TimeBookInterface {

 

    @Override

    public void doAuditing(String name) {

       System.out.println(name+"实现");

    }

}

===========日志输出类TimeBookProxy =========================

package com.gc.action.impl;

 

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

/**

 * 日志输出

 * @author yltd

 *

 */

public class TimeBookProxy {

    private  Logger logger = Logger.getLogger(this.getClass().getName());

    private TimeBookInterface timeBookInterface;

    public TimeBookProxy(TimeBookInterface timeBookInterface){

       this.timeBookInterface = timeBookInterface;

    }

    /**

     * 实际业务处理

     */

    public void doAuditing(String name){

       logger.log(Level.INFO, name+" 开始审批。");

       timeBookInterface.doAuditing(name);

       logger.log(Level.INFO, name+" 审批结束。");

    }

}

 ==============测试类TestTimeBook ================================

package com.gc.action.impl;

public class TestTimeBook {

    public static void main(String[] args) {

       TimeBookProxy  timeBookProxy = new TimeBookProxy(new TimeBookImpl());

       timeBookProxy.doAuditing("zyx");

    }

}

================结果======================

- zyx 开始审批。

zyx实现

- zyx 审批结束。

使用Java的代理机制实现日志输出

====接口TestLogInterface =========================

package com.gc.action.javaLog;

/**

 * 接口

 * @author yltd

 *

 */

public interface TestLogInterface {

    //操作方法

    public void doSameing(String name);

}

========实现类TestLogImpl ========================

package com.gc.action.javaLog;

/**

 * 实现类

 * @author yltd

 *

 */

public class TestLogImpl implements TestLogInterface {

 

    @Override

    public void doSameing(String name) {

       System.out.println("name = "+name);      

    }

 

}

============日志信息代理类LogProxy ====================

package com.gc.action.javaLog;

 

import java.lang.reflect.InvocationHandler;

import java.lang.reflect.Method;

import java.lang.reflect.Proxy;

import org.apache.log4j.Level;

import org.apache.log4j.Logger;

 

/**

 * 日志信息的代理类

 * @author yltd

 *

 */

public class LogProxy implements InvocationHandler{

    private Logger  logger =Logger.getLogger(this.getClass().getName());

    private Object obj;

   

    public Object dind(Object obj){

       this.obj=obj;

       return Proxy.newProxyInstance(obj.getClass().getClassLoader(), obj.getClass().getInterfaces(),this);

    }

   

    @Override

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

       Object result =null;

       logger.log(Level.INFO, args[0]+" 开始。。。");

       result = method.invoke(obj, args);

       logger.log(Level.INFO, args[0]+" 结束。。。");

       return result;

    }

}

============测试类TestMain ===========================

package com.gc.action.javaLog;

/**

 * 测试类

 * @author yltd

 *

 */

import com.gc.action.javaLog.TestLogInterface;

public class TestMain {

 

    public static void main(String[] args) {

       LogProxy lp =new LogProxy();

       TestLogInterface tli =(TestLogInterface) lp.dind(new TestLogImpl());

       tli.doSameing("zyx");

    }

 

}

==========结果============

- zyx 开始。。。

name = zyx

- zyx 结束。。。

 

总结:第一种方式,需要在每个类里都增加对输出日志信息的代码;第二种方式,虽然实现了业务逻辑与输出日志信息代码的分离,但还是必须依赖于固定的接口;第三种方式,真正实现了对输出日志信息代码的重用,并且不依赖于固定的接口实现。

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多