zoukankan      html  css  js  c++  java
  • JDK动态代理

    在开始学习Spring AOP(面向切面编程)的时候,就碰到了jdk动态代理,据说这是实现AOP的底层技术。

    于是乎搜罗了以下blog加深学习:

    1. http://www.cnblogs.com/luotaoyeah/p/3778183.html

    2. http://m.blog.csdn.net/blog/weitry/38460385

    3. http://wwyu8901.iteye.com/blog/846919

    目前还仅限于会用的程度。。。

    比如应用场景: 准备在调用某个方法的前后加上一些log。

    方法有3种:

    1. 在有源码的前提下,直接在方法前后加上代码;

    2. 若无源码,则可以使用继承的方式,重写方法;

    3. (推荐)如果该类实现了接口,则采用组合的方式,也实现这个接口,重写方法。

    而AOP的实现方式就类似于第3种方法,也是JDK动态代理的实现方式。

    所谓的JDK动态代理主要涉及到java.lang.reflect包中的Proxy类和InvocationHandler接口。

    1. 通过实现InvocationHandler接口,可以定义实现横切逻辑的方法(比如打log);重写invoke(),从而利用反射机制调用目标类的代码,将横切逻辑和业务逻辑动态编织在一起;

    2. Proxy则为InvocationHandler实现类动态创建一个符合某一接口的代理实例。

    注意:JDK动态代理依靠接口实现,若某个类没有实现接口,则JDK无法为该类生成代理实例。

    具体实例的Code:

    User类:

    public class User {
        private String name;
        private String id;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getId() {
            return id;
        }
    
        public void setId(String id) {
            this.id = id;
        }
    }

    1. 接口和实现类

    public interface UserDAO {
        public void save(User user);
    }
    public class UserDAOImpl implements UserDAO {
        @Override
        public void save(User user) {
            System.out.println("user is saved");
        }
    }

    2. 在执行save()前后加上log,所以使用JDK动态代理。实现InvocationHandler接口 + 利用Proxy生成代理实例:

    public class LogIntercepter implements InvocationHandler{
    
        private Object target;
    
        public Object getTarget() {
            return target;
        }
    
        //只需一个LogIntercepter实例即可
        public void setTarget(Object target) {
            this.target = target;
        }
    
        //横切逻辑方法
        public void before(){
            System.out.println("before method...");
        }
        public void end(){
            System.out.println("end method...");
        }
    
        //生成代理实例
        public Object newProxyInstance(){
            return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),this);
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            //横切逻辑+业务逻辑
            before();
            method.invoke(target, args);
            end();
            return proxy;
        }
    }

    3. Test

    public class Main {
    
        public static void main(String[] args) {
    
            User user = new User();
            user.setId("12");
            user.setName("proxy");
    
            //无proxy
            UserDAOImpl dao = new UserDAOImpl();
            dao.save(user);
            //使用proxy
            LogIntercepter log = new LogIntercepter();
            log.setTarget(dao);
            UserDAO dao1 = (UserDAO)log.newProxyInstance();
            dao1.save(user);
        }
    }

    4. 测试结果:

    user is saved
    before method...
    user is saved
    end method...

    5. done!

    代理类的大致实现:

    清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己 -- 共勉
  • 相关阅读:
    js处理select操作总结
    IntelliJ IDEA 下载 安装
    PropertiesConfiguration处理properties
    CentOS操作系统,安装完毕后只能在“命令行模式”下登陆,无法进入“图形化界面”
    java客户端Ip获取
    加载依赖的jar包在命令行编译和运行java文件
    request.getSession(true)和request.getSession(false)的区别
    Spring在web请求中定义编码(org.springframework.web.filter.CharacterEncodingFilter)
    java操作redis
    【http】生命周期和http管道技术 整理中
  • 原文地址:https://www.cnblogs.com/hello-yz/p/4752073.html
Copyright © 2011-2022 走看看