Spring AOP

AOP

面向切面编程

AspectJ

intro to aspectJ

Spring AOP Design

AOP面向切面编程是通过代理对象来实现的,和拦截器是不是有点像,最主要的区别就是PointCut,来看看接口设计:

public interface Pointcut {

	/**
	 * Return the ClassFilter for this pointcut.
	 * @return the ClassFilter (never {@code null})
	 */
	ClassFilter getClassFilter();

	/**
	 * Return the MethodMatcher for this pointcut.
	 * @return the MethodMatcher (never {@code null})
	 */
	MethodMatcher getMethodMatcher();
}

Spring 整合AspectJ,使用了AspectJ对切面的定义,同时支持自己的xml space定义切面等信息,AspectJ还是支持weaving(compiling,loading)阶段。

Spring的整合方式是提供spring自己的weaving方式,动态代理,运行时刻,并协同spring ioc进行工作,满足绝大多数企业应用场景。 当然spring也支持独立使用AspectJ,使用原生的weaving方式。

spring的设计哲学,包容并可扩展。 spring aop

Spring AOP Proxy

Spring AOP 的实现方式是为目标对象生成代理对象。 Spring AOP 框架对 AOP 代理类的处理原则是:如果目标对象的实现类实现了接口,Spring AOP 将会采用 JDK 动态代理来生成 AOP 代理类;如果目标对象的实现类没有实现接口,Spring AOP 将会采用 CGLIB 来生成 AOP 代理类——不过这个选择过程对开发者完全透明、开发者也无需关心,CGLIB 底层使用ASM。

Proxy CGLIB
// 拦截器类
public class AroundAdvice implements MethodInterceptor 
{ 
    public Object intercept(Object target, Method method , Object[] args, MethodProxy proxy) 
throws java.lang.Throwable 
{ 
    System.out.println("执行目标方法之前,模拟开始事务 ..."); 
    // 执行目标方法,并保存目标方法执行后的返回值
    Object rvt = proxy.invokeSuper(target, new String[]{"被改变的参数"}); 
    System.out.println("执行目标方法之后,模拟结束事务 ..."); 
    return rvt + " 新增的内容"; 
} 
}


//接下来程序提供一个 ChineseProxyFactory 类,这个 ChineseProxyFactory 类会通过 CGLIB 来为 Chinese 生成代理类
public class ChineseProxyFactory 
{ 
    public static Chinese getAuthInstance() 
        { 
            Enhancer en = new Enhancer(); 
            // 设置要代理的目标类
            en.setSuperclass(Chinese.class);
            // 设置要代理的拦截器
            en.setCallback(new AroundAdvice());
            // 生成代理类的实例 
            return (Chinese)en.create();
        } 
}

Proxy Jdk

Spring AOP 会动态选择使用 JDK 动态代理、CGLIB 来生成 AOP 代理,如果目标类实现了接口,Spring AOP 则无需 CGLIB 的支持,直接使用 JDK 提供的 Proxy 和 InvocationHandler 来生成 AOP 代理即可

//Proxy 编程是面向接口的。下面我们会看到,Proxy 并不负责实例化对象,和 Decorator 模式一样,要把 Account定义成一个接口,然后在 AccountImpl里实现 Account接口,接着实现一个 InvocationHandlerAccount方法被调用的时候,虚拟机都会实际调用这个 InvocationHandler的 invoke方法

class SecurityProxyInvocationHandler implements InvocationHandler { 
    private Object proxyedObject; 
    public SecurityProxyInvocationHandler(Object o) { 
        proxyedObject = o; 
    } 
        
    public Object invoke(Object object, Method method, Object[] arguments) 
        throws Throwable {             
        if (object instanceof Account && method.getName().equals("opertaion")) { 
            SecurityChecker.checkSecurity(); 
        } 
        return method.invoke(proxyedObject, arguments); 
    } 
}

//在应用程序中指定 InvocationHandler生成代理对象
public static void main(String[] args) { 
    Account account = (Account) Proxy.newProxyInstance( 
        Account.class.getClassLoader(), 
        new Class[] { Account.class }, 
        new SecurityProxyInvocationHandler(new AccountImpl()) 
    ); 
    account.function(); 
}

关于Spring Aop 的具体实现,这里有源码解析spring aop 源码解析

面试的时候常会被问及的一个问题,如果一个类里面的两个方法都被增强了,method1 调用 method2 的时候,method2 会被增强吗? 其实这个问题很简单,AOP只是在使用proxy类对method1做了增强,然后会调用target的method1方法,然后target.method1 invoke target.method2. 所以method2是没有被增强的。

为什么private方法不能使用AOP?
因为两种实现方式都不能代理private方法,cglib通过继承父类的方式,不能访问父类private方法。

Spring Transaction

我们知道Spring 的@Transaction 是通过切面实现的,然后在事务嵌套过程中会有上面我们提到的类似的问题,那事务里面是怎么解决的呢。
通过属性propagation 来控制事务的传播,所以需要理解这个才不会迷惑.

参考

https://vimeo.com/52990474

https://www.ibm.com/developerworks/cn/java/j-lo-asm30/

https://www.ibm.com/developerworks/cn/java/j-lo-springaopcglib/index.html

转载于:https://my.oschina.net/tigerlene/blog/1512078

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值