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

白话Spring(基础篇)---AOP(实例篇-1)

2016-03-04 21:33 435 查看
[一知半解,就是给自己挖坑]

上文中,介绍了AOP的基本概念,接下来,我们看看AOP相关概念对应的实例及用法。本节我们先介绍AOP的实现方式的第一种方式:Spring提供的类org.springframework.aop.framework.ProxyFactoryBean。

准备工作:

a.操作系统:win7 x64

b.开发工具:eclipse mars j2ee版本,maven3.3.2,Spring 4,junit4.12

c.引入前面工程中的jar包至外,还需要引入的有:aspectjweaver,aoplliance,spring-aop
-------------------------------------------------------------------------------------------------------------------------------------
使用 ProxyFactoryBean 来创建 AOP 代理的最重要的优点之一是 IoC 可以管理通知和切入点。 这是一个非常的强大的功能,能够实现其他 AOP 框架很难实现的特定的方法。例如,一个通知本身可以引用应用对象(除了目标对象,它在任何AOP 框架中都可以引用应用对象),这完全得益于依赖注入所提供的可插入性。

--------------------------------------------------------------------------------------------------------------------------------------------------------

1.创建Spring091工程,工程结构图如下:



2.创建BaseAfterReturnAdvice.java文件,具体内容如下:

package com.java.ingo.advice;

import java.lang.reflect.Method;

import org.springframework.aop.AfterReturningAdvice;

/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月4日下午2:02:08
*类说明
*/
public class BaseAfterReturnAdvice implements AfterReturningAdvice {

/**
* returnValue :切入点执行完方法的返回值,但不能修改 <br>
* method :切入点方法 <br>
* args :切入点方法的参数数组 <br>
* target :目标对象
*/
public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    System.out.println("====进入after()==========");
        System.out.print(args[0] + "在");
        System.out.print(target + "对象上被");
        System.out.println(method + "方法删除了");
        System.out.println("====退出after()===========");
}
}
3.创建BaseAfterThrowsAdvice.java文件,具体内容如下:

package com.java.ingo.advice;

import java.lang.reflect.Method;

import org.springframework.aop.ThrowsAdvice;

/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月4日下午2:04:52
*类说明
*/
public class BaseAfterThrowsAdvice implements ThrowsAdvice {

/**
* 通知方法,需要按照这种格式书写
*
* @param method
*            可选:切入的方法
* @param args
*            可选:切入的方法的参数
* @param target
*            可选:目标对象
* @param throwable
*            必填 : 异常子类,出现这个异常类的子类,则会进入这个通知。
*/
public void afterThrowing(Method method, Object[] args, Object target, Throwable throwable) {
System.out.println("删除出错");
}
}
4.创建BaseAroundAdvice.java文件,具体内容如下:

package com.java.ingo.advice;

import java.lang.reflect.Method;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.cglib.proxy.MethodProxy;

/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月4日下午2:03:08
*类说明
*/
public class BaseAroundAdvice implements MethodInterceptor {

/**
* invocation :连接点
*/
public Object invoke(MethodInvocation invocation) throws Throwable {
 System.out.println("===========进入around===========");
        // 调用方法的参数
        Object[] args = invocation.getArguments();
        // 调用的方法
        Method method = invocation.getMethod();
        // 获取目标对象
        Object target = invocation.getThis();
        // 执行完方法的返回值:调用proceed()方法,就会触发切入点方法执行
        Object returnValue = invocation.proceed();
        System.out.println("输出:" + args[0] + ";" + method + ";" + target + ";" + returnValue + "\n");
        System.out.println("===========结束进入around===========");
        return returnValue;
}
}
5.创建BaseBeforeAdvice.java文件,具体内容如下:

package com.java.ingo.advice;

import java.lang.reflect.Method;

import org.springframework.aop.MethodBeforeAdvice;

/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月4日上午11:41:39
*类说明
*/
public class BaseBeforeAdvice implements MethodBeforeAdvice {

/**
* method : 切入的方法 <br>
* args :切入方法的参数 <br>
* target :目标对象
*/
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("=进入before()============");
        System.out.print("准备在" + target + "对象上用");
        System.out.print(method + "方法进行对 '");
        System.out.println(args[0] + "'进行删除!");
        System.out.println("=退出before()============");
}
}
6.创建Customer.java文件,具体内容如下:

package com.java.ingo.entity;
public class Customer {
private String name;
private String sex;
private int age;

public Customer() {
super();
System.out.println("------创建人员-------");
}

public Customer(String name, String sex, int age) {
super();
this.name = name;
this.sex = sex;
this.age = age;
}

public String getName() {
return name;
}

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

public String getSex() {
return sex;
}

public void setSex(String sex) {
this.sex = sex;
}

public int getAge() {
return age;
}

public void setAge(int age) {
this.age = age;
}

}
7.创建IBaseBusiness.java文件,具体内容如下:

package com.java.ingo.service;

import com.java.ingo.entity.Customer;

/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月4日上午11:40:25
*类说明
*/
public interface IBaseBusiness {

/**
* 用作代理的切入点方法
*
* @param obj
* @return
*/
public void delete(Customer obj);
}
8。创建BaseBusiness.java文件,具体内容如下:

package com.java.ingo.service.impl;

import com.java.ingo.entity.Customer;
import com.java.ingo.service.IBaseBusiness;

/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月4日上午11:40:55
*类说明
*/
public class BaseBusiness implements IBaseBusiness {

/**
* 切入点
*/
public void delete(Customer obj) {
System.out.println("||=====================||");
System.out.println("删除用户:"+obj.getName());
System.out.println("||=====================||");
}
}


9.创建Main。java,具体内容如下:

package Main;

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

import com.java.ingo.entity.Customer;
import com.java.ingo.service.IBaseBusiness;
import com.java.ingo.service.impl.BaseBusiness;

/**
*@author 作者 E-mail:ingo
*@version 创建时间:2016年3月4日上午11:46:52
*类说明
*/
public class Main {
public static void main(String[] args) {
ApplicationContext context = new ClassPathXmlApplicationContext("classpath:beans.xml");
IBaseBusiness business = (IBaseBusiness ) context.getBean("businessProxy");
business.delete(new Customer("Tom","male",22));
}
}


10.创建beans.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:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd"
default-autowire="byName">

<!-- ==============================利用spring自己的aop配置================================ -->
<!-- 声明一个业务类 -->
<bean id="baseBusiness" class="com.java.ingo.service.impl.BaseBusiness" />
<!-- 声明通知类 -->
<bean id="baseBefore" class="com.java.ingo.advice.BaseBeforeAdvice" />
<bean id="baseAfterReturn" class="com.java.ingo.advice.BaseAfterReturnAdvice" />
<bean id="baseAfterThrows" class="com.java.ingo.advice.BaseAfterThrowsAdvice" />
<bean id="baseAround" class="com.java.ingo.advice.BaseAroundAdvice" />
<!-- 使用ProxyFactoryBean 产生代理对象 -->
<bean id="businessProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<!-- 代理对象所实现的接口 ,如果有接口可以这样设置 -->
<property name="proxyInterfaces">
<value>com.java.ingo.service.IBaseBusiness</value>
</property>

<!-- 设置目标对象 -->
<property name="target">
<ref local="baseBusiness" />
</property>
<!-- 代理对象所使用的advice,即4种通知-->
<property name="interceptorNames">
<list>
<value>baseAfterReturn</value>
<value>baseAround</value>
<value>baseAfterThrows</value>
<value>baseBefore</value>
</list>
</property>
</bean>
</beans>

现在,我们来解释一下这份配置文件:

a.配置文件中的id为baseBefore及其他3个bean就是我们所需要的4中通知,及advice。这些通知需要实现对应的接口。

接口的描述如下:

通知类型接口描述
Beforeorg.springframework.aop.MethodBeforeAdvice在目标方法之前执行
aroundorg.aopalliance.intercept.MethodInterceptor拦截对目标对象方法执行
afterorg.springframework.aop.AfterReturningAdvice在目标方法之后执行
throwsorg.springframework.aop.ThrowsAdvice目标方法发生错误是执行
b.配置文件中的id为baseBusiness的bean是Spring要代理的对象,及当执行此对象中的方法时,触发4个advice

c.配置文件中的id为businessProxy的bean是Spring的ProxyFactoryBean。

d.属性proxyInterfaces指明需要代理的接口。

e.属性target指明需要代理的目标对象。

f.属性interceptorNames指明需要使用到的advice的类型。

注意:

1. ProxyFactoryBean的proxyInterfaces属性只支持使用字符串的方式进行注入,不支持使用Bean的依赖方式进行注入。

2.如果ProxyFactoryBean 的proxyInterfaces 属性没有 被设置,但是目标类实现了一个(或者更多) 接口,那么ProxyFactoryBean 将自动检测到这个目标类已经实现了至少一个接口,
一个基于JDK的代理将被创建 。被实际代理的接口将是目标类所实现的全部 接口;实际上,这和在proxyInterfaces 属性中列出目标类实现的每个接口的情况是一样的。然而,这将显著地减少工作量以及输入错误的可能性。

11.测试方法:运行main方法,观察控制台输出即可。
-------------------------------------------------------------------------------------------------------------------------------------------------------

至此,白话Spring(基础篇)---AOP(实例篇-1)结束

参考资料:

Spring官网:http://spring.io/docs
其他博文:http://outofmemory.cn/code-snippet/3762/Spring-AOP-learn-example
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: