首页 > 代码库 > Spring 对 AOP 的支持

Spring 对 AOP 的支持

1、AOP概念

  首先,AOP是对OOP的一个补充。它考虑的是“横切性”问题。横切性问题即可以理解为我们同一层类的问题(例如:Service层)。

  它的理念是,把遍历在系统各个角落具有横切性的独立的服务,抽出来放到一个地方,然后等到运行时,再放进去,考虑的是“横向”的东西。将横切性关注的东西给抽出来,会使代码大大减少,更加简洁,更加有复用性。

       下图展示AOP中的基本概念:


  技术分享


       基础概念不多说,从上图可以看出SpringAOP的实现的过程:

  ?  找到横切性性关注点(发现横切性问题,具体实现为Advice)

  ?  编写切入点(Pointcut),即指定Advice的方法的作用域

  ?  将Advice织入(Weave)目标对象(TargetObject)的Joinpoint

  织入(Weave)是动态的,默认采用的方式是JDK的动态代理,当然也可以采用CGLIB代理。

  可简单地表示为下图:


  技术分享


2、Spring 对 AOP 的支持—采用Annotation方式


 依赖包配置:

       *SPRING_HOME/dist/spring.jar

       *SPRING_HOME/lib/log4j/log4j-1.2.14.jar

       *SPRING_HOME/lib/jakarta-commons/commons-logging.jar

       *SPRING_HOME/lib/aspectj/*.jar  --(要使用aspectj提供的相关的注解)

 源码

  interface UserManager

package com.bjpowernode.spring;

public interface UserManager {
	public void addUser(String userName, String password);
}

  class UserManagerImpl  

package com.bjpowernode.spring;

public class UserManagerImpl implements UserManager {

	public void addUser(String username, String password) {
		System.out.println("---------UserManagerImpl.add()--------");
	}
}

  *class  SecurityHandler(将横切性关注点模块化,建立相关的类)

package com.bjpowernode.spring;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

@Aspect
public class SecurityHandler {

	/**
	 * 定义Pointcut,Pointcut的名称为addAddMethod(),此方法没有返回值和参数 该方法就是一个标识,不进行调用
	 */
	@Pointcut("execution(* add*(..))")
	private void addAddMethod() {
	};

	/**
	 * 定义Advice,表示我们的Advice应用到哪些Pointcut订阅的Joinpoint上
	 */
	@Before("addAddMethod()")
	// @After("addAddMethod()")
	private void checkSecurity() {
		System.out.println("");
		System.out.println("-------checkSecurity-------");
	}
}

  为所有的方法名中带add的方法,执行之前都加入checkSecurity()服务。


  Spring配置文件—ApplicationContext.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:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
	<!-- 启用AspectJ对Annotation的支持 -->       
	<aop:aspectj-autoproxy/>  
	
	<bean id="userManager" class="com.bjpowernode.spring.UserManagerImpl"/>
	 
	<bean id="securityHandler" class="com.bjpowernode.spring.SecurityHandler"/>
</beans>

  classClient—客户端

package com.bjpowernode.spring;

import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Client {
	public static void main(String[] args) {

		BeanFactory factory = new ClassPathXmlApplicationContext(
				"applicationContext.xml");
		System.out.print(factory);
		UserManager userManager = (UserManager) factory.getBean("userManager");
		userManager.addUser("张三", "123");
	}

}

  运行结果:

-------checkSecurity-------
---------UserManagerImpl.add()--------


3、Spring 对 AOP 的支持—采用"配置文件"方式


 与上面实现相同的效果。

  * 依赖包配置采用上面的“采用Annotation方式”即可

  * 直接看源码:

  interface  UserManager与上面相同

  class  UserManagerImpl与上面相同

  class  SecurityHandler(将横切性关注点模块化,建立相关的类):

package com.bjpowernode.spring;

public class SecurityHandler {

	private void checkSecurity() {
		System.out.println("");
		System.out.println("-------checkSecurity-------");
	}
}

  *Spring配置文件—ApplicationContext.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:tx="http://www.springframework.org/schema/tx"
	     xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
           http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.0.xsd
           http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
	
	<bean id="userManager" class="com.bjpowernode.spring.UserManagerImpl"/>
	<bean id="securityHandler" class="com.bjpowernode.spring.SecurityHandler"/>
	<aop:config>
		<aop:aspect id = "securityAspect" ref="securityHandler">
			<!-- 以Add为开头的方法
			<aop:pointcut id="addAddMethod" expression="execution(* add*(..))"/>
			 -->
			<!--  com.bjpowernode.spring包下所有类的所有方法
			<aop:pointcut id="addAddMethod" expression="execution(* com.bjpowernode.spring.*.*(..))"/>
			-->
			<!-- com.bjpowernode.spring包下所有类的所有add与del方法 -->
			<aop:pointcut id="addAddMethod" expression="execution(* com.bjpowernode.spring.*.add*(..))||execution(* com.bjpowernode.spring.*.del*(..))"/>
			<!-- Advice,配一个Pointcut -->
			<aop:before method="checkSecurity" pointcut-ref="addAddMethod"/>
		</aop:aspect>
	</aop:config>
</beans>

  主要是在aspect节中,将Advice与Poincut联系起来


  classClient—客户端也与上面相同


  运行结果正确:

-------checkSecurity-------
---------UserManagerImpl.add()--------

4、总结

  做AOP,重点是,发现Aspect(切面),并在“运行时”切入进去。织入过程,默认采用JDK的动态代理。动态灵活,但比较慢;静态比较快(可以预编译),但不灵活。Spring的AOP可以针对pojo对象提供声明式服务,如声明式事务; Ejb里面的SessionBean也可以提供声明式事务。

Spring 对 AOP 的支持