spring的aop实现

前言:
spring的aop是spring框架中很重要的功能,提供了一个面向切面的实现方式,从而实现了诸如日志,事务,拦截等切面的实.由于spring已经整合了一个aop框架AspectJ,因此我们既可以用spring的代理工厂方式,也可直接使用AspectJ框架的方式来实现切面功能,并且AspectJ框架的实现也有两种,因此总的来说由三种实现方式。

一.基于spring的ProxyFactoryBean实现aop
由于面向切面的实现方式是基于动态代理的方式,因此spring提供了一个代理工厂的bean,利用这个bean我们可以实现一些切面功能.同时spring为我们提供大量的通知的接口,只要我们实现这些接口就可以实现一个切面功能.
这里写图片描述
这里先实现一个前置的通知接口(注意通知也是bean):

@Component
public class Advice implements MethodBeforeAdvice{
    /**
     * arg0:被调用的方法
     * arg1:这个方法的参数
     * arg2:被代理的对象
     */
    @Override
    public void before(Method arg0, Object[] arg1, Object arg2) throws Throwable {
        System.out.println("拦截方法:"+arg0.getName());

    }

}

实现了通知那么之后就是要设计代理的过程。这里就用这个类来模拟一个service

public interface Service {
    public void show();
}
@Component("serviceImp")
public class ServiceImp implements Service{
    @Override
    public void show() {
        System.out.println("执行方法");
    }

}

现在的关键就是在于设计ProxyFactoryBean

<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
    <!-- 代理的接口,如果目标对象没有接口的话就会用cglib来实现 -->
        <property name="ProxyInterfaces">   
            <list>
                <value>service.Service</value>
            </list>
        </property>
        <!-- 目标对象 -->
        <property name="target" ref="serviceImp"></property>
        <!-- 通知的bean -->
        <property name="interceptorNames">
            <list>
                <value>advice</value>
            </list>
        </property>
    </bean> 

当这些设计好后便可以实现对方法的增强,来看看实现:

public void aopByFactory() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/spring.xml");
        //由于上面是有接口的因此不会用cglib实现,固需要用接口
        Service service = (Service) applicationContext.getBean("proxyFactoryBean");
        System.out.println(service.getClass());
        service.show();
    }

结果:
这里写图片描述
可以看到确实实现了.
2基于aspectj框架实现
第一种方式比较简单,直接利用注解便可以实现,不过要注意Apsect的注解需要导Aspect的jar包.导入了包后我们便可以自己设置通知类,这里设计了一个简单的通知类

@Component
@Aspect
public class AdviceByAnnotation {

    @Before("execution(* service.*.*())")
    public void before(){
        System.out.println("基于注解实现aspect");
    }
}

关于execution表达式可以去看看其他的博客,这里是拦截service包下任意类的任意方法。
同时再spring的配置文件种需要开启对apsect注解的识别功能

    <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

现在来看看测试代码

    public void aopByannotionAspectj() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/spring.xml");
        Service service = applicationContext.getBean(Service.class);
        System.out.println(service.getClass());
        service.show();
        //这里额外写了一个没有接口的类,可以看到是用cglib实现
        ServiceBycglib  imp = applicationContext.getBean(ServiceBycglib.class);
        System.out.println("spring aop 利用cglib代理未实现接口的类:" +imp.getClass());

    }

结果:
这里写图片描述
这种实现方式相对普遍
利用spring配置文件整合实现aspectj
这种方式不需要导入aspectj的jar包既可以实现,实现上来说也不复杂.首先还是要有一个通知类:

@Component
public class AdivceByXml {
    public void before() {
        System.out.println("基于xml配置aspectj实现aop");
    }
}

然后便是xml的配置

        <!-- 基于xml实现 -->
      <aop:config>
      <!-- 设置切入点 -->
        <aop:pointcut expression="execution(* service.*.*(..))" id="pointcut"/>
        <!-- 设置切面 -->
        <aop:aspect id="myAspect" ref="adivceByXml" >
                 <aop:before method="before" pointcut-ref="pointcut"/>      
        </aop:aspect>
    </aop:config>

这里spring提供了专门的标签用于设置aop,注意要设置pointcut(切入点),和切面。当然还有很多的通知类型这里只用了before。测试代码:

    public void aopByXml() {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("spring/spring.xml");
        Service service = applicationContext.getBean(Service.class);
        System.out.println(service.getClass());
        service.show();
    }

结果:
这里写图片描述
可以看到aspectj的两种实现方式都可以,不过第二种再设计事务的时候会方便许多

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值