Spring学习-----AOP(1)

前面已经学过了bean的相关知识,对bean的配置方法也有了一定的了解。下面来学习Spring中一个重要的知识点AOP编程,这些知识点都是根据韩顺平老师的视频总结而来,虽然简单,但是作为入门了解还是不错的。不过想要真正的应用到项目中,还需要进行深一步的学习。


  1. AOP的概念

        AOP(aspect oriented programming)面向切面编程,是对所有对象或是一类对象编程,核心是在不增加代码的基础上,还能增加功能。他所应用到的场景一般是将交叉功能(事务、日志)提取出来。

         2、AOP术语

1、切面:要实现的交叉功能,是系统模块化的一个切面或者领域(如日志记录等)

2、连接点:应用程序执行过程中插入切面的地点,可以是方法调用,异常抛出,或者要修改的字段。

3、通知:切面的实际实现,他通知系统新的行为。如在日志通知包含了实现日志功能的代码,向日志文件写日志。通知在连接点插入到应用系统中。

4、切入点:定义了通知应该应用在哪些连接点,通知可以应用到AOP框架支持的任何连接点。

5、引入:为类添加新的方法和属性

6、目标对象:被通知的对象,既可以是你编写的类,也可以是第三方的类

7、代理:将通知应用到目标对象后创建的对象,应用系统的其他部分不用为了支持代理对象而改变

8、织入:将切面应用到目标对象从而创建一个新的代理对象的过程。织入发生在目标对象生命周期的多个点上

编译器:切面在目标对象编译时织入,这需要一个特殊的编译器

类装载器:切面在目标对象那个被载入JVM是织入,这需要一个特殊的类载入器

运行期:切面在应用系统运行时织入

        3、配置步骤

步骤:

1、定义接口

2、编写对象(被代理对象=目标对象)

3、编写通知

4、bean.xml文件配置

1、配置被代理对象

2、配置通知

3、配置代理对象(是proxyFactoryBean实例)

a、配置被代理对象

b、配置代理接口集

c、把通知织入代理对象

下面我们来举个例子,需求就是在调用UserBean 的sayHello()前利用前置通知完成日志的书写,利用环绕通知将sayHello方法包裹起来(然而现在并不能了解环绕通知的具体应用场景是什么),调用完sayHello方法后,最后用后置通知释放资源。


首先来看一下框架图:




  1. 定义接口:
              package rogue.aop;

                  public interface TestSeverInter {

                  public void sayHello(); 

                 }


             package rogue.aop;

                 public interface TestSeverInter2 {

                 public void sayBye();

                }

                        

                      2.编写目标对象

package rogue.aop;

public class SeverTest1 implements TestSeverInter,TestSeverInter2 {
	private String name;
	
	
	public String getName() {
		return name;
	}


	public void setName(String name) {
		this.name = name;
	}


	public void sayHello() {
		System.out.println("Hello"+name);
	}


	@Override
	public void sayBye() {
		System.out.println("Bye"+name);
		
	}

}

3、编写通知

.package rogue.aop;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

public class MyMethodBeforeAdvice implements MethodBeforeAdvice {

	@Override
	/**
	 * method:被调用的方法的名字
	 * args:传递的参数
	 * target:目标对象(就是被调用的对象)
	 * 
	 */
	public void before(Method method, Object[] args, Object target)
			throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("前置通知-通知日志..."+method.getName());
	}

}

package rogue.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;

public class MyMethodSurroundAdvice implements MethodInterceptor {

	@Override
	public Object invoke(MethodInvocation arg0) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("调用环绕通知前。。");
		arg0.proceed();
		System.out.println("调用环绕通知后。。");
		return null;
	}

}

package rogue.aop;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

public class MyMethodAfterAdvice implements AfterReturningAdvice {

	@Override
	public void afterReturning(Object returnValue, Method method,
			Object[] args, Object target) throws Throwable {
		// TODO Auto-generated method stub
		System.out.println("关闭资源。。。");
	}

}

4、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:context="http://www.springframework.org/schema/context"
		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.5.xsd
	http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

<!-- 配置被代理对象 -->
<bean id="SeverTest1" class="rogue.aop.SeverTest1">
  <property name="name" value="大帽子" />
</bean>

<!--配置通知-->
     <!-- 配置前置通知 -->
<bean id="MyMethodBeforeAdvice" class="rogue.aop.MyMethodBeforeAdvice" />
     <!-- 配置后置通知 -->
<bean id="MyMethodAfterAdvice" class="rogue.aop.MyMethodAfterAdvice" />
     <!-- 配置环绕通知 -->
<bean id="MyMethodSurroundAdvice" class="rogue.aop.MyMethodSurroundAdvice" />



<!-- 配置代理对象(也就是将被代理对象,接口和通知整合起来,配置在一起) -->
<bean id="proxyFactoryBean" class="org.springframework.aop.framework.ProxyFactoryBean">
       <!-- 第一步:将被代理对象织入到代理对象中 (name一定要是target)-->
<property name="target" ref="SeverTest1"></property>
       <!-- 第二步:将代理接口集织入到代理对象中 (name一定要是proxyInterfaces)-->
<property name="proxyInterfaces">
	<list>
		<value>rogue.aop.TestSeverInter</value><!-- 这里应该是全限定名 -->
		<value>rogue.aop.TestSeverInter2</value>
	</list>
</property>

       <!-- 第三步:把通知织入到代理对象(name一定要是interceptorNames) -->
<property name="interceptorNames">
	<list>
	<!-- 相当于把MyMethodBeforeAdvice前置通知和代理对象关联,也可以把通知看作拦截器  -->
		<value>MyMethodBeforeAdvice</value>
		<value>MyMethodAfterAdvice</value>
		<value>MyMethodSurroundAdvice</value>
	</list>
</property>


</bean>
</beans>

测试程序

package rogue.aop;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class app {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		ApplicationContext aContext = new ClassPathXmlApplicationContext("rogue/aop/aop.xml");
		
                //在这里我们应该取proxyFactoryBean,因为在这里面有我们织入的通知,执行完通知后再执行正常的代码
		TestSeverInter tS = (TestSeverInter) aContext.getBean("proxyFactoryBean");
		tS.sayHello();
		System.out.println("**********************************");
		
		((TestSeverInter2)tS).sayBye();
	}

}

结果截图:





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章