Spring AOP 实现

Spring AOP 实现

@(spring)[AOP]

spring aop的发展过程


增强类型


spring 的aop底层是通过jdk动态代理和cglib动态代理技术为bean织入横切逻辑的。spring通过使用增强类定义横切逻辑。
Spring 提供了五种增强类型:
- 前置增强 : org.springframework.aop.MethodBeforeAdvice 是Spring目前可用的前置增强
- 后置增强 : org.springframework.aop.AfterReturningAdvice 目标方法后执行
- 环绕增强 : org.aopalliance.intercept.MethodInterceptor 目标方法前后执行
- 异常抛出增强 : org.springframework.aop.AfterReturningAdvice 抛出异常后执行
- 引介增强 : org.springframework.aop.support.DelegatingIntroductionInterceptor 为目标类增加新的方法和属性

前置增强


  1. 定义增强类
  2. 使用spring 的 ProxyFactory 将增强类目标类放入工厂,然后工厂实现代理

前置增强类:

public class BeforeAop implements MethodBeforeAdvice {
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
        System.out.println("this is before advice...");
    }
}

ProxyFactory完成代理:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mvc.xml"})
public class AopTest {

    @Test
    public void beforeAdvice(){
        Waiter target = new NaviWaiter();
        // 前置增强
        BeforeAdvice beforeAdvice = new BeforeAop();
        // spring代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        // JDK代理
        proxyFactory.setInterfaces(target.getClass().getInterfaces());
        proxyFactory.setTarget(target);
        proxyFactory.addAdvice(beforeAdvice);
        // 增强,设为true强制使用cglib代理(要引cglib库)
//        proxyFactory.setOptimize(true);

        Waiter waiter = (Waiter) proxyFactory.getProxy();
        waiter.greetTo("miss");
    }
}
schema方式实现

spring的xml中配置bean

<bean class="com.lemontree.spring.aoptalk.BeforeAop" id="beforeAop"/>
<bean class="com.lemontree.spring.service.NaviWaiter" id="target"/>
<bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
    p:proxyInterfaces="com.lemontree.spring.service.Waiter"
    p:interceptorNames="beforeAop"
    p:target-ref="target"/>

测试:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:spring.xml","classpath:spring-mvc.xml"})
public class AopTest {

    @Autowired
    private Waiter waiter;

    @Test
    public void schema(){
        waiter.greetTo("tt");
    }
}

环绕增强

顾名思义
代码和和前置增强直接看代码
环绕增强

public class ArroundAop implements MethodInterceptor {
    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Object[] o = invocation.getArguments();
        String s = (String) o[0];
        System.out.println("this is around..."+s);
        Object result = invocation.proceed();
        System.out.println("this is  ....");
        return result;
    }
}

异常抛出增强

ThrowsAdvice 并没有定义方法,他只是一个标识接口,spring会通过反射机制进行判断,但是必须以下面的方法签名进行定义:

    void afterThrowing(Method method,Object[] args,Object target,Throwable);

方法名必须为afterThrowing,前三个参数可以选,要么都要要么都不要,最后一个是Throwable或它的子类

具体实现:

public class ThrowAop implements ThrowsAdvice {

    //定义增强逻辑
    public void afterThrowing(Method method,Object[] args,Object target,Exception ex)throws Throwable{
        System.out.println("方法名"+method.getName());
        System.out.println("异常名称"+ex.getMessage());
        System.out.println("回滚一波~~~~~");
    }

}

引介增强

引介增强比较特殊,他不是在目标方法中织入增强,而是为目标类创建新的方法和属性,所以增强的链接点是类级别的(上面的 增强是方法级别的)。

具体实现:
1. 定义一个接口:

public interface MoniterService {
    void wathchYou(boolean isWatch);
}
  1. 定义引介增强
public class IntroductionAop extends DelegatingIntroductionInterceptor implements MoniterService{
    private ThreadLocal<Boolean> moniMap = new ThreadLocal<>();

    @Override
    public void wathchYou(boolean isWatch) {
        moniMap.set(isWatch);
    }

    @Override
    public Object invoke(MethodInvocation mi) throws Throwable {
        if (moniMap.get()!=null && moniMap.get()){
            System.out.println("do it!");
        }
        return super.invoke(mi);
    }
}
  1. 测试
    @Test
    public void introAop(){
        Waiter target = new NaviWaiter();
        // 引介增强
        IntroductionInterceptor introductionAop = new IntroductionAop();
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setInterfaces(target.getClass().getInterfaces());
        proxyFactory.setTarget(target);
        proxyFactory.addAdvice(introductionAop);

        Waiter waiter = (Waiter) proxyFactory.getProxy();
        waiter.greetTo("mss");
        System.out.println("-----------------------");
        MoniterService moniterService = (MoniterService) waiter;
        moniterService.wathchYou(true);
        waiter.greetTo("mss");
    }

创建切面

增强类存在一个问题:增强被织入目标类的所有方法中。所以就需要Spring AOP去定位连接点。
所以创建切面的目的:找到连接点 ,为对应的方法织入横切逻辑


静态方法匹配切面

StaticMethodMatcherPointcutAdvisor 代表一个静态方法匹配切面,通过StaticMethodMatcherPointcut 定义切点
切面的创建:
1. 创建切面
2. 将增强类放入到切面中
3. 工厂生成代理类

具体实现:
切面:

public class StaticMethod extends StaticMethodMatcherPointcutAdvisor {
    @Override
    public boolean matches(Method method, Class<?> targetClass) {
        return "greetTo".equals(method.getName());
    }
}

测试:

    @Test
    public void staticAdvisor()  {
        Waiter target = new NaviWaiter();
        // 前置增强
        BeforeAop beforeAop = new BeforeAop();
        // 静态普通方法名称匹配
        StaticMethod staticMethod = new StaticMethod();
        staticMethod.setAdvice(beforeAop);
        // 代理工厂
        ProxyFactory proxyFactory = new ProxyFactory();
        proxyFactory.setInterfaces(target.getClass().getInterfaces());
        proxyFactory.setTarget(target);
        proxyFactory.addAdvisor(staticMethod);

        //生成代理类
        Waiter waiter = (Waiter) proxyFactory.getProxy();
        waiter.greetTo("可以");
        System.out.println("----------------");
        waiter.serveTo("不可以?");
    }

自动代理

先看看前面的schame

   <bean class="com.lemontree.spring.aoptalk.BeforeAop" id="beforeAop"/>
    <bean class="com.lemontree.spring.service.NaviWaiter" id="target"/>
    <bean id="waiter" class="org.springframework.aop.framework.ProxyFactoryBean"
        p:proxyInterfaces="com.lemontree.spring.service.Waiter"
        p:interceptorNames="beforeAop"
        p:target-ref="target"/>

可以看出,每次生成一个代理类都需要用ProxyFactoryBean配置一遍,十分麻烦。
所以spring提供了新的创建类:
- BeanNameAutoProxyCreator
- DefaultAdvisorAutoProxyCreator
还有很多中,这里只讲两个
有了Creator方法就可以嘿嘿嘿了
新的schame配置:

    <bean class="com.lemontree.spring.aoptalk.BeforeAop" id="beforeAop"/>
    <bean class="com.lemontree.spring.service.NaviWaiter" id="waiter"/>
   <bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"
        p:interceptorNames="beforeAop"
        p:beanNames="*er"
        p:optimize="true"/>

迎来新时代

注解实现AOP

SpringInAction.4th.面向切面的Spring

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值