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!

代理类的大致实现:

清醒时做事,糊涂时读书,大怒时睡觉,独处时思考; 做一个幸福的人,读书,旅行,努力工作,关心身体和心情,成为最好的自己 -- 共勉
原文地址:https://www.cnblogs.com/hello-yz/p/4752073.html