您的位置:首页 > 编程语言 > Java开发

关于Spring的AOP面向切面编程

2015-06-18 19:31 771 查看
AOP,对业务的横向编程,这个思想确实不错。一个简单的实际应用:

在做项目的过程中,做了一个登陆的功能,项目做完这后,需要在用户登录完成后,进行日志管理,也就是将登录成功的用户信息存在数据库中。

这个时候就不要回过头来去源码中,在登录的那个功能里面进行写东西了,利用AOP的原理进行横向拦截大大扩展的程序的可伸缩性!

项目架构SpringMVC + Spring

这种架构项目熟悉的人都知道,Controller是由*-servlet.xml(SpringMVC)文件进行管理的,Service层则是由application.xml(Spring)文件进行管理的.

AOP有四种方式进行配置,常见的是2种,1.注解方式 2.配置文件的方式

我喜欢用配置文件的方式!

先说说对Service曾进行AOP编程吧!

Service层中:

接口:

package com.lgy.service;

public interface Sleepable {
	void sleep();
	int eat();
	int play();
}


实现:

package com.lgy.service;

import org.springframework.stereotype.Service;

@Service
public class Human implements Sleepable {
	@Override
	public void sleep() {
		System.out.println("人在睡觉");
	}

	@Override
	public int eat() {
		System.out.println("dog 在 eat");
		return 1;
	}

	@Override
	public int play() {
		System.out.println("play baskball");
		return 1;
	}

}


说明:三个方法,其中有2个方法有返回值!

被插入的对象如下:

package com.lgy.aop;

import org.aspectj.lang.ProceedingJoinPoint;

public class SleepHelper {
	 public void afterSleep(){
	     System.out.println("睡醒了要穿衣服!");
	 }
	 
	 //ProceedingJoinPoint only in around
	 public Object aroundEat(ProceedingJoinPoint joinpoint) throws Throwable {
		 System.out.println("执行之前");
		 Object result = joinpoint.proceed();   //目标对象执行
		 System.out.println("执行之后");
		 return result;
	 }
	 
	 public void afterReturn() {
		 System.out.println("执行之后");
	 }
}


三个方法,对应切面的三个方法。

beans.xml(spring-aop核心配置文件):
<!-- 配置需要被切面操作的对象 -->
<bean id="sleepHelper" class="com.lgy.aop.SleepHelper"></bean>

<aop:config>
    <aop:aspect ref="sleepHelper">
	<!-- 之后进行插入 -->
	    <aop:after method="afterSleep" pointcut="execution(* com.lgy.service.*.sleep(..))"/>
	    <!-- around获取返回值 -->
	    <aop:around method="aroundEat" pointcut="execution(* com.lgy.service.*.eat(..))" />
	    <!-- 返回之后执行 -->
	    <aop:after-returning method="afterReturn" pointcut="execution(* com.lgy.service.*.play(..))" />
    </aop:aspect>
</aop:config>


对于方法的插入顺序有如下:

<aop:after method=""/> 切面方法完成以后在进行插入

<aop:after-returning method=""/> 切面方法完成返回值以后在进行插入

<aop:after-throwing method=""/> 切面方法在抛出异常的时候进行插入

<aop:around method=""/> 切面方法在开始前后进行插入(实际是自定义)

<aop:before method=""/> 切面方式在开始之前进行插入

若用到环绕,则可以在方法参数添加 ProceedingJoinPoint joinpoint

通过该对象joinpoint.process()可以执行切面方法,进而得到返回值。

测试代码如下:

/**

* 建议:

* 若目标对象有无return:

* 根据需求

* 1.若方法有return

* 则用AOP的after-return或者around

* 2.若方法没有return

* 则用AOP的after或者before

*/

package aop;

import javax.annotation.Resource;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.lgy.service.Sleepable;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:/beans.xml"})
public class AopTest {
	@Resource(name="human")
	private Sleepable sleepable;
	@Test
	public void humAfter() {
		sleepable.sleep();
	}
	
	@Test
	public void humAround() {
		int eat = sleepable.eat();
		System.out.println(eat);  //根据around的切面方法最终返回值
	}
	
	@Test
	public void humafterReturn() {
		int i = sleepable.play();
		System.out.println(i);  //根据around的切面方法最终返回值
	}

}


以上就是对Service层代码进行切面编程-------------------------------------------------------------------------------------------------------------------

在Controller层中有一点不一样,那就是对Aop的配置位置。由于Contorller层是SpringMVC进行管理,Service层是Spring进行管理,进而生产的代理类不同,AOP生产的代理类有2种方式1.jdk的动态代理 2.cglib代理方式有 区别是前者只能对接口进行代理,后者可以对类进行代理,如果目标对象没有实现接口,则默认会采用CGLIB代理。

所以在bean.xml中配置AOP是不行的,需要在*-servlet.xml中进行配置AOP。

Controller层进行切面编程:

Controller层的代码:

同时也是切面对象

package com.lgy.controller;

import javax.annotation.Resource;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.lgy.service.Sleepable;

@Controller
@RequestMapping("/aop")
public class AopController {
	@Resource(name="human")
	private Sleepable sleepable;
	
	@RequestMapping("/hello")
	public String hello() {
		System.out.println("hello world");
		return "hello";
	}
}


被插入的对象如下:

package com.lgy.aop;

public class HelloHelp {
	public void helloBefore() {
		System.out.println("AOP  hellp  before...");
	}
}


*.servlet.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"
       xmlns:mvc="http://www.springframework.org/schema/mvc"
       xsi:schemaLocation="http://www.springframework.org/schema/beans 
      					   http://www.springframework.org/schema/beans/spring-beans.xsd 						   http://www.springframework.org/schema/aop 
						   http://www.springframework.org/schema/aop/spring-aop.xsd 						   http://www.springframework.org/schema/context 						   http://www.springframework.org/schema/context/spring-context.xsd 						   http://www.springframework.org/schema/mvc 
					       http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd"> 	<!-- 使用cglib代理 
	<aop:aspectj-autoproxy proxy-target-class="true" />-->
					   
	<!-- 自动扫描且只扫描@Controller -->
	<context:component-scan base-package="com.lgy" use-default-filters="false">
		<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
	</context:component-scan>
	
	<!-- 注解生效 json转换-->
	<mvc:annotation-driven>
		<mvc:message-converters>  
            <bean class="org.springframework.http.converter.StringHttpMessageConverter" >  
	            <property name = "supportedMediaTypes">
					<list>
	 					 <value>text/plain;charset=UTF-8</value>
	 				</list>
				</property>
            </bean>  
        </mvc:message-converters> 
	</mvc:annotation-driven>
	
	<!-- 文件上传的视图解析器,springmvc中对这个id名称写死  multipartResolver -->
	<bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver" />
	<!-- 配置静态资源 -->
    <!-- 配置视图解析器 -->
    <bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
    	<property name="prefix" value="/WEB-INF/"></property>  
    	<property name="suffix" value=".jsp"></property>
    </bean>
    
    <!-- controller -->
	<aop:config>
	    <aop:aspect ref="helloHelp">
	    	<!-- 之后进行插入 -->
		    <aop:before method="helloBefore" pointcut="execution(* com.lgy.controller.*.hello(..))"/>
	    </aop:aspect>
	</aop:config>
</beans>


ref中的helloHelp在bean.xml文件中进行配置即可。

执行localhost::8080/项目名/aop/hello

测试都通过了!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: