Spring AOP原理浅析及入门实例

上篇问题及Spring AOP实现原理浅析

上篇说了一个AOP编程问题,那是一个错误的AOP案例。它的错误在A类中,再次粘贴A类代码:

    @Component
    public class AImpl implements A {
        public void doing() {
            System.out.println("hello");
        }

        public static void main( String[] args )
        {
            ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml");
            AImpl a=ctx.getBean(AImpl.class);      //(1)出错行
            //A a=ctx.getBean(A.class); //(2)换成这样就正确了
            a.doing();
        }


    }

先说一下正确代码(代码2)的执行过程:

步骤执行过程
1程序启动,生成Bean并加载到缓存池(因为Spring默认是即时加载bean,而不是延时加载),因为配置了切面,所以,不生成AImpl类的bean,而生成一个proxy类对象。这个proxy类实现了A接口,并通过反射机制来调用AIplm类对象来完成操作。(这其实就是动态代理模式
2得到beanFactory。
3根据A的名以单例模式获取bean实例,发现容器中只有proxy对象是A类对象,所以实际返回的是proxy对象
4执行proxy对象的doing()方法.

为什么行(1)错了呢?
因为,容器中并没有AImpl类的bean实例,而只有proxy类的实例。所以,ctx.getBean(AImpl.class) 返回的是null。

Spring AOP是默认是通过动态代理的方式来实现的,动态代理要求代理对象和被代理对象必须要有同一个接口。如果类一个接口都没有实现,那么,Spring将使用CGLIB方式实现,CGLIB方式不要求类实现接口。
上面的示例中,Aimpl实现了A接口,所以使用的是动态代理方式,如果Aimpl不实现A接口,则将会使用GCLIB方式,那么行(1)也是正确的。

入门实例

1.加入依赖包,建议使用maven的方式。修改pom..xml文件,加入下面的依赖。

<!-- spring framework -->    
    <dependency>
       <groupId>org.springframework</groupId>
       <artifactId>spring-context</artifactId>
       <version>4.2.1.RELEASE</version>
    </dependency>

    <!-- AspectJ依賴包 -->
    <dependency>
       <groupId>org.aspectj</groupId>
       <artifactId>aspectjweaver</artifactId>
       <version>1.8.6</version>
    </dependency>
    <dependency>
       <groupId>aspectj</groupId>
       <artifactId>aspectjrt</artifactId>
       <version>1.5.3</version>
    </dependency>

2.bean.xml文件,就加入

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd">
      <!--自动扫描包中的bean,使用注解来配置bean就需要这一行,需要修改包名-->
      <context:component-scan base-package="com.lcl.springlearning"></context:component-scan>

      <!-- 添加对 aspectj支持 -->
      <aop:aspectj-autoproxy></aop:aspectj-autoproxy>  
</beans>

3.编写正常的逻辑代码。一个接口A,和一个实现类AImpl。Spring AOP的动态代理机制要求被切面拦截的类必须实现一个接口。
接口:

public interface A {
    public void doing();
}

实现:

@Component
public class AImpl implements A {
    public void doing() {
        System.out.println("hello");
    }
}

4.定义切面。注意这个切面必须定义成一个bean,也就是要加。上@Component 注解

@Aspect    //定义一个切面
@Component
public class B {

    @Pointcut("execution(* doing(..))")   //定义一个切点,拦截所有的doing方法
    public void pointCutMethod(){
    }

    @Before("pointCutMethod()")       //定义前置事件
    public void doBefore(){
        System.out.println("前置通知!");
    }

    @After("pointCutMethod()")        //定义最终事件
    public void doAfter(){
        System.out.println("后置通知!");
    }
}

5、测试代码

public static void main( String[] args )
    {
        ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml");
        A a=ctx.getBean(A.class);//注意要使用接口A
        a.doing();
    }

刚开始学的时候,看了很多实例都讲了太多现实逻辑,非常难懂,强烈要求讲例子的时候不要加入太多现实逻辑。

    原文作者:AOP
    原文地址: https://blog.csdn.net/ruangong1203/article/details/48245071
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞