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

【Spring AOP】学习记录(一)

2016-09-11 15:43 309 查看
概述
什么是AOP

作用

实现框架

例子
配置1application-contextxml

配置2servicesxml

切面对象DebugInterceptorjava

代理接口ISampleCreateUserjava

接口实现SampleCreateUserImpljava

测试基础类BaseTestjava

测试实例ISampleCreateUserTestjava

测试结果

总结
缺点

参考

由于公司有自己的框架,整个架构跟
Spring
几乎沾不上边,在业余时间对
Spring
框架的学习,最近开始学习切面编程
“Spring AOP”
,并且在博文中记录一下,以便日后快速上手

概述

这一章先了解一下什么是AOP,以及写一个简单的例子

什么是AOP?

aop叫aspect oriented program,面向切面的编程。那什么是面向切面编程,切面就是可插可拔,俗一点说就是想要就要,想不要就不要。直接看看下图理解一下



作用?

我们在编程的时候很多重复的代码如:

日志记录

事务控制

异常处理

函数执行时间/监控

权限校验

等等

当项目开发到一定程度的时候,我们如果突然要说加上这么多东西,那多要命啊。那么这个时候我们可以考虑加入AOP了

实现框架?

有人问,如果不用spring,那还有其他框架吗?那是必须的

笔者了解到的可以做到的有下面几个

JBOSS ASM 字节码修改

CGLIB spring可以用它来做代理

ASPECTJ eclipse实现

例子

该例子是从spring官网下拿下来进行测试的,笔者尝试了可以成功运行

配置1(application-context.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"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!--支持扫描包-->
<context:component-scan base-package="com.carl.spring"/>
<!--支持注解-->
<context:annotation-config/>

<!--其他配置文件-->
<import resource="services.xml"></import>
</beans>


spring 入口配置文件

配置2(services.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:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--aop start-->
<bean id="createUserProxy" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces" value="com.carl.spring.hello.aop.ISampleCreateUser"/>
<!-- Use inner bean, not local reference to target -->
<property name="target" ref="sampleCreateUser">
</property>
<property name="interceptorNames">
<list>
<value>debugInterceptor</value>
</list>
</property>
</bean>
<!--aop end-->
</beans>


该配置是AOP的一个代理配置,获取对象的时候,直接获取
createUserProxy
就可以获取
target
执行的代理对象,(因为ProxyFactoryBean实现了FactoryBean,可以直接获取对应的对象);
interceptorNames
就是切面的对象了
Advice/Advisor/Interceptor


切面对象(DebugInterceptor.java)

package com.carl.spring.hello.aop;

import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.springframework.stereotype.Component;

/**
* @author Carl
* @date 2016/9/11
*/
@Component("debugInterceptor")
public class DebugInterceptor implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("Before: invocation=[" + methodInvocation + "]");
Object rval = methodInvocation.proceed();
System.out.println("Invocation returned");
return rval;
}
}


methodInvocation.proceed();
为执行代理方法,在执行代理方法前和执行方法后,执行了一些系统输出

代理接口(ISampleCreateUser.java)

package com.carl.spring.hello.aop;

/**
* @author Carl
* @date 2016/9/11
*/
public interface ISampleCreateUser {

String create();
}


这里只做一个接口的定义

接口实现(SampleCreateUserImpl.java)

package com.carl.spring.hello.aop;

import org.springframework.stereotype.Service;

/**
* @author Carl
* @date 2016/9/11
*/
@Service("sampleCreateUser")
public class SampleCreateUserImpl implements ISampleCreateUser {
@Override
public String create() {
System.out.println("invoking SampleCreateUserImpl.create()");
return "return res for SampleCreateUserImpl.create()";
}
}


注意,这里有一个注解
@Service("sampleCreateUser")
,否则在service.xml获取不了代理对象

测试基础类(BaseTest.java)

package com.carl.spring.hello.bean;

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

/**
* @author Carl
* @date 2016/8/28
*/
public abstract class BaseTest {
protected ApplicationContext context;

@Before
public void setUp() throws Exception {
context =
new ClassPathXmlApplicationContext(new String[] {"application-context.xml"});

}
}


测试实例(ISampleCreateUserTest.java)

package com.carl.spring.hello.aop;

import com.carl.spring.hello.bean.BaseTest;
import org.junit.Test;

import static org.junit.Assert.*;

/**
* Created by Administrator on 2016/9/11.
*/
public class ISampleCreateUserTest extends BaseTest {
@Test
public void create() throws Exception {
ISampleCreateUser createUser = context.getBean("createUserProxy", ISampleCreateUser.class);
assertNotNull(createUser);
String res = createUser.create();
assertEquals("return res for SampleCreateUserImpl.create()", res);
System.out.println(res);
}
}


Junit的真实测试类

测试结果

该结果是从控制台中直接输出

Before: invocation=[ReflectiveMethodInvocation: public abstract java.lang.String com.carl.spring.hello.aop.ISampleCreateUser.create(); target is of class [com.carl.spring.hello.aop.SampleCreateUserImpl]]
invoking SampleCreateUserImpl.create()
Invocation returned
return res for SampleCreateUserImpl.create()


总结

最终还是实现了切面,可插拔的东西,但是对象必须交给spring进行代理

缺点

每个对象都需要配置一遍代理

每个代理都要主动调用一次
methodInvocation.proceed()


需求可能只需要
前置执行/后置执行/异常时执行/前后都执行


需要配置xml,注解行不行

这上面的内容spring都可以很好的解决,在后面的博文中会记下来

参考

http://blog.csdn.net/Intlgj/article/details/5671248
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: