Spring AOP原理浅析及入门实例

来源:互联网 发布:5kplayer mac 编辑:程序博客网 时间:2024/05/04 19:38

上篇问题及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();}

实现:

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

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

@Aspect    //定义一个切面@Componentpublic 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();    }

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

0 0
原创粉丝点击