一直都是我从csdn里面涉取,现在也共享一下我的Spring Aop入门:
1.首选定义一个接口
public interface IStudent {
public void addStudent(String name);
public void addA();
}
2.定义接口的实现
public class StudentImpl implements IStudent {
public void addStudent(String name) {
// TODO Auto-generated method stub
System.out.println( " 欢迎 " + name + " 你加入Spring家庭! " );
}public void addA() {
// TODO Auto-generated method stub
System.out.println( " 我是A " );
}}
3.定义一个Advice[通知]
import java.lang.reflect.Method;
import org.springframework.aop.MethodBeforeAdvice;/**
* @author ycl
*/
public interface SimpleBeforeAdvice extends MethodBeforeAdvice {void before() throws Throwable;//不需要传递参数的调用
void before(Method method, Object[] args, Object target) throws Throwable;
}
4. 定义一个AdivceImpl[通知的实现]
import java.lang.reflect.Method;
/**
* @author Dmitriy Kopylenko
* this is the set invoke times.
*/
public class SimpleBeforeAdviceImpl implements SimpleBeforeAdvice {
private int invocationCounter;private String methods[];
public void setMethods(String[] methods) {
this.methods = methods;
}public void before() throws Throwable {
++invocationCounter;
System.out.println("调之前:"+invocationCounter);
}public int getInvocationCounter() {
return invocationCounter;
}public void before(Method method, Object[] args, Object target)
throws Throwable {
if(AdviceUtils.isContain(methods, method.getName())){
System.out.println("执行before Invoke");
before();
System.out.println("这是BeforeAdvice中的Before方法");
System.out.println("调用的方法是"+method.getName());
System.out.println("参数为"+args.toString());
System.out.println("目标对象为:"+target);
}else{
System.out.println("Before不拦截此方法"+method.getName());
}
}}
5.定义一个MethodInterceptor
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;/**
* @author ycl
* 方法调用之前的配置
*/
final class SimpleAdviceInterceptor implements MethodInterceptor {
private boolean flag;
public void setFlag(boolean flag) {
this.flag = flag;
}public SimpleAdviceInterceptor(){
super();
}
public Object invoke(MethodInvocation mi) throws Throwable {
Object result=null;
if(flag){
result=mi.proceed();
}
return result;
}
}
6.定义配置文件beans.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!-- 打开spring的注释代理引擎 -->
<bean id="simpleAspect" class="test.org.springframework.aop.SimpleAspect" />
<bean id="beforeAdvice" class="test.org.springframework.aop.SimpleBeforeAdviceImpl">
<!-- 拦截哪些方法 -->
<property name="methods" >
<list>
<value>addStudent</value>
</list>
</property>
</bean>
<bean id="afterAdvice" class="test.org.springframework.aop.SimpleAfterAdviceImpl">
<!-- 拦截哪些方法 -->
<property name="methods" >
<list>
<value>add*</value>
</list>
</property>
</bean>
<bean id="compareInterceptor" class="test.org.springframework.aop.SimpleAdviceInterceptor">
<!-- 是否执行主程序方法 -->
<property name="flag" value="true" ></property>
</bean>
<bean id="studenttarget" class="test.org.springframework.aop.StudentImpl"></bean>
<!-- 目标对象 -->
<bean id="student" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>test.org.springframework.aop.IStudent</value>
<!-- 可以有多个接口 -->
</property>
<property name="interceptorNames">
<list>
<value>beforeAdvice</value>
<value>afterAdvice</value>
<value>compareInterceptor</value>
<!-- 最后一个为interceptor,其他的为通知 -->
</list>
</property>
<property name="target">
<ref bean="studenttarget"/>
<!-- 只能有一个实例 -->
</property>
</bean>
<!-- 这种是使用纯手工配置的方式进行的 -->
</beans>
7.测试Aop应用
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Test {public static void main(String args[]){
Test test=new Test();
test.doAbsoluteClassPathXmlApplicationContext();
}
public void doAbsoluteClassPathXmlApplicationContext(){
ApplicationContext ctx = new ClassPathXmlApplicationContext("beans.xml",this.getClass());
IStudent ms=(IStudent)ctx.getBean("student");
ms.addA();
/**
* 此AOP特点
* 1. 可以定义是否进行方法前进行拦截
* 2. 可以定义是否进行方法后进行拦截
* 3. 可以定义拦截方法后是否执行主方法
* 4. 可以定义方法前[方法后]拦截哪些方法
* 5. 可以用配置文件动态添加,不会对原有的程序代码有任何影响.
*/
}
}
Aop概念说明:
面向切面编程:Aspect Oriented Programming, 可以通过预编译方式和运行期动态代理实现在不修改源代码的情况下给程序动态统一添加功能的一种技术,解决了调用者和被调用者之间的解耦,采用注入的方式动态的控制方法之间的调用,实例,事务和日志的动态添加.
Aop有以下几种实现方法:
· AspectJ (TM): 创建于Xerox PARC. 有近十年历史,成熟
缺点:过于复杂;破坏封装;需要专门的Java编译器。
· 动态AOP:使用JDK的动态代理API或字节码Bytecode处理技术。
Aop的专业术语解析:
1. 切面(Aspect): 一个关注点的模块化,这个关注点可能会横切多个对象。事务管理是J2EE应用中一个关于横切关注点的很好的例子。 在Spring AOP中,切面可以使用通用类(基于模式的风格) 或者在普通类中以 @Aspect 注解(@AspectJ风格)来实现。[目标编程]
织入(Weaving): 把切面(aspect)连接到其它的应用程序类型或者对象上,并创建一个被通知(advised)的对象,我这里没有分离,应该把那些System.out.println()换成业务处理并分离出一个类,也就是被通知的对象.
2. 连接点(Joinpoint): 在程序执行过程中某个特定的点,比如某方法调用的时候或者处理异常的时候。 在Spring AOP中,一个连接点 总是 代表一个方法的执行。 通过声明一个org.aspectj.lang.JoinPoint类型的参数可以使通知(Advice)的主体部分获得连接点信息。[拦截器]
3. 通知(Advice): 在切面的某个特定的连接点(Joinpoint)上执行的动作。通知有各种类型,其中包括“around”、“before”和“after”等通知。 通知的类型将在后面部分进行讨论。许多AOP框架,包括Spring,都是以拦截器做通知模型, 并维护一个以连接点为中心的拦截器链。
4. 切入点(Pointcut): 匹配连接点(Joinpoint)的断言。通知和一个切入点表达式关联,并在满足这个切入点的连接点上运行(例如,当执行某个特定名称的方法时)。 切入点表达式如何和连接点匹配是AOP的核心:Spring缺省使用AspectJ切入点语法。
5. 引入(Introduction): (也被称为内部类型声明(inter-type declaration))。声明额外的方法或者某个类型的字段。 Spring允许引入新的接口(以及一个对应的实现)到任何被代理的对象。 例如,你可以使用一个引入来使bean实现 IsModified 接口,以便简化缓存机制。
6. 目标对象(Target Object): 被一个或者多个切面(aspect)所通知(advise)的对象。也有人把它叫做 被通知(advised) 对象。 既然Spring AOP是通过运行时代理实现的,这个对象永远是一个 被代理(proxied) 对象。
AOP代理(AOP Proxy): AOP框架创建的对象,用来实现切面契约(aspect contract)(包括通知方法执行等功能)。 在Spring中,AOP代理可以是JDK动态代理或者CGLIB代理。 注意:Spring 2.0最新引入的基于模式(schema-based)风格和@AspectJ注解风格的切面声明,对于使用这些风格的用户来说,代理的创建是透明的。
根据原则对应于我以上的Aop实现: