java架构解密——AOP之动态代理实现

62 篇文章 0 订阅
7 篇文章 11 订阅

         在上篇博客中,我们在宏观上介绍了AOP的底层实现,具体见博客java架构解密——Spring框架的AOP,在博客中,我们讲述了Aop的一些设计上的思路,今天,咱们就具体的实现,和大家一起探讨,看看AOP是怎么一步一步走到今天,而且有些图,也要做些纠正!


一,代码演变

前提:最初要实现的功能(打招呼)


代码:

接口:

<span style="font-size:18px;">public interface Greeting {
	 void sayHello(String name);  
}</span>


实现:

<span style="font-size:18px;">public class GreetingImpl  implements Greeting {

	@Override 
    public void sayHello(String name) {  
          
        System.out.println("Hello! " + name);  
         
    }  
 
}</span>

1,要增加一个功能在打招呼前加入打印“befor”,在打招呼后打印“after”

修改后实现:

<span style="font-size:18px;">public class GreetingImpl  implements Greeting {

	@Override 
    public void sayHello(String name) {  
        before();  
        System.out.println("Hello! " + name);  
        after();  
    }  
 
    private void before() {  
        System.out.println("Before");  
    }  
 
    private void after() {  
        System.out.println("After");  
    }  
	
}</span>

2,我想统一管理这些

    如果有一天,图 1 中的深色代码段需要修改,那是不是要打开 3 个地方的代码进行修改?如果不是 3 个地方包含这段代码,而是 100 个地方,甚至是 1000 个地方包含这段代码段,那会是什么后果?
    为了解决这个问题,我们通常会采用将如图 1 所示的深色代码部分定义成一个方法,然后在 3 个代码段中分别调用该方法即可。

代理的实现:

<span style="font-size:18px;">public class GreetingProxy implements Greeting {
	private GreetingImpl greetingImpl;  
	 
    public GreetingProxy(GreetingImpl greetingImpl) {  
        this.greetingImpl = greetingImpl;  
    }  
 
    @Override 
    public void sayHello(String name) {  
        before();  
        greetingImpl.sayHello(name);  
        after();  
    }  
 
    private void before() {  
        System.out.println("Before");  
    }  
 
    private void after() {  
        System.out.println("After");  
    }  
}</span>

注意:这时候,GreetingImpl里没有befor和after方法!


3,动态更换代理

    因为软件系统需求变更是很频繁的事情,系统前期设计方法 1、方法 2、方法 3 时只实现了核心业务功能,过了一段时间,我们需要为方法 1、方法 2、方法 3 都增加事务控制;又过了一段时间,客户提出方法 1、方法 2、方法 3 需要进行用户合法性验证,只有合法的用户才能执行这些方法;又过了一段时间,客户又提出方法 1、方法 2、方法 3 应该增加日志记录;又过了一段时间,客户又提出……面对这样的情况,我们怎么办?

类设计:


JDK代理实现:

<span style="font-size:18px;">public class JDKDynamicProxy 
	implements InvocationHandler {  
		 
	    private Object target;  
	 
	    public JDKDynamicProxy(Object target) {  
	        this.target = target;  
	    }  
	 
	    @SuppressWarnings("unchecked")  
	    public <T> T getProxy() {  
	        return (T) Proxy.newProxyInstance(  
	            target.getClass().getClassLoader(),  
	            target.getClass().getInterfaces(),  
	            this 
	        );  
	    }  
	 
	    @Override 
	    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {  
	        before();  
	        Object result = method.invoke(target, args);  
	        after();  
	        return result;  
	    }  
	 
	    private void before() {  
	        System.out.println("Before");  
	    }  
	 
	    private void after() {  
	        System.out.println("After");  
	    }  
}</span>

客户端:

<span style="font-size:18px;">public class Client {
	public static void main(String[] args) {  
        Greeting greeting = new JDKDynamicProxy(new GreetingImpl()).getProxy();  
        greeting.sayHello("Jack");     
    }  
}</span>

运行时对象的关系:




4.1改进

缺点:必须有接口
CGLib代理:

CGLIB实现:

<span style="font-size:18px;">public class CGLibDynamicProxy implements MethodInterceptor {  
 
    private static CGLibDynamicProxy instance = new CGLibDynamicProxy();  
 
    
    private CGLibDynamicProxy() {  
    }  
 
    public static CGLibDynamicProxy getInstance() {  
        return instance;  
    }  
 
    @SuppressWarnings("unchecked")  
    public <T> T getProxy(Class<T> cls) {  
        return (T) Enhancer.create(cls, this);  
    }  
 
    @Override 
    public Object intercept(Object target, Method method, Object[] args, MethodProxy proxy) throws Throwable {  
        before();  
        Object result = proxy.invokeSuper(target, args);  
        after();  
        return result;  
    }  
 
    private void before() {  
        System.out.println("Before");  
    }  
 
    private void after() {  
        System.out.println("After");  
    }  
	
	
}</span>

客户端:

<span style="font-size:18px;">public class Client {
	public static void main(String[] args) {  
        Greeting greeting = CGLibDynamicProxy.getInstance().getProxy(GreetingImpl.class);  
        greeting.sayHello("Jack");  
    } 
}</span>

运行时对象的关系:


总结:

        进行到这里,一般的博客也许就会结束了,因为核心内容已经结束了,但是,咱们的征途是星辰和大海,咱们的征途才刚开始,这个AOP还很草率,还没有实现动态的组装,而且咱们的aop切面(公共服务)和代理类写在了一起,等等这些问题,解决这些问题,需要我们站在整个设计思路上下功夫,核心原理懂了,剩下的抽象和封装的工作,是考验一个人另一个能力的时候了,咱们,下节继续!


  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 15
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值