Spring AOP
关键字: spring aop advice pointcut advisor理解advice,pointcut和advisor.
advice是想向别的程序内部不同的地方注入的代码.
pointcut定义了需要注入advice的位置.
advisor是pointcut和advice的装配器,是将advice注入主程序中预定义位置的代码.
spring提供的几个种同的advices,比如before advice,after advice,around advice,throw advice等等.
业务接口IHello.java
public interface IHello {
public void toHello(String name);
}
实现HelloImp.java
public class HelloImp implements IHello {
public void toHello(String name) {
System.out.println("hello:" + name);
}
}
以下是几种advices的实现:
1. 1. before advice 会在目标对象被调用之前执行的.before advice的实现代码:
LogBeforeAdvice.java
public class LogBeforeAdvice implements MethodBeforeAdvice {
public void before(Method method, Object[] param, Object target)
throws Throwable {
System.out.println("method start..." + method.getName());
}
}接口MethodBeforeAdvice只有一个方法before需要实现,它定义了advice的实现.
before方法有三个参数,参数Method是advice开始后执行的方法.Object[]是传给被调用的参数数组,Object是执行方法m对象的引用.
2. after advice 会在目标对象被调用之后执行的.after advice的实现代码:
public class LogAfterAdvice implements AfterReturningAdvice {
public void afterReturning(Object arg0, Method method, Object[] arg2,
Object arg3) throws Throwable {
System.out.println("method end..." + method.getName() + arg2[0]);
}
}
spring的配置:
<bean id="logBeforeAdvice" class="com.spring.advices.LogBeforeAdvice"></bean> <bean id="hello" class="com.dynamic.proxy.HelloImp"></bean> <bean id="logAfterAdvice" class="com.spring.advices.LogAfterAdvice"></bean> <bean id="helloProxy" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>com.dynamic.proxy.IHello</value> </property> <property name="target"> <ref bean="hello"/> </property> <property name="interceptorNames"> <list> <value>logBeforeAdvice</value> <value>logAfterAdvice</value> </list> </property> </bean>
属性proxyInterface定义了接口类。
属性target指向本地配置的一个bean
属性interceptorNames是唯一允许定义一个值列表的属性.这个列表包含所有需要在beanTarget上执行的advice.
编写主方法的Java代码:
public class SpringDemo {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
IHello hello = (IHello)context.getBean("helloProxy");
hello.toHello("callan");
}
}每次toHell方法调用时,都会执行advice.也就是说调用toHello会先执行LogAfterAdvice,调用完后会执行LogAfterAdvice
以上是before advice和after advice的实现,也可以单独用MethodInterceptor来代替它们的功能.不同的是,在MethodInterceptor的invoke()方法中你要决定是否使用 proceed()方法来调用目标方法.
3. around advice的实现:
public class LogInterceptor implements MethodInterceptor {
public Object invoke(MethodInvocation method) throws Throwable {
// TODO Auto-generated method stub
System.out.println("start...");
Object obj = null;
// method.proceed()会调用目示方法,在调用目录方法之前打印了start,之后打印了end,实现与before,after的组合功能
obj = method.proceed();
System.out.println("end...");
return obj;
}
}
配置与before,after相似
<bean id="helloProxy2" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="proxyInterfaces"> <value>com.dynamic.proxy.IHello</value> </property> <property name="target"> <ref bean="hello"/> </property> <property name="interceptorNames"> <list> <value>logInterceptore</value> </list> </property> </bean>
before advice,after advice,around advice三种只定义了切入在代理接口执行前后执行,其实可以还可以更细的切入日志等
4. 有一个方便的类叫做NameMatchMethodPointcutAdvisor,它允许通过名称选择方法,只有匹配的方法才会加入日志.要想使用NameMatchMethodPointcutAdvisor,只需要修改配置.
<bean id="helloAdvice" class="org.springframework.aop.support.NameMatchMethodPointcutAdvisor">
<property name="mappedName">
<value>toHello</value> <!-- 方法名 -->
</property>
<property name="advice">
<ref bean="logBeforeAdvice"/>
</property>
</bean>
<bean id="helloProxy3" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="proxyInterfaces">
<value>com.dynamic.proxy.IHello</value>
</property>
<property name="target">
<ref bean="hello"/>
</property>
<property name="interceptorNames">
<list>
<value>helloAdvice</value>
</list>
</property>
</bean>
IHello接口中,只有toHello方法才能切入日志.
mappedName是定义匹配的方法名,还可以使用mappedNames定义方法列表
<property name="mappedNames">
<value>toHello</value> <!-- 方法名 -->
<value>toHello2</value> <!-- 方法名 -->
<value>toHello3</value> <!-- 方法名 -->
</property>
5. RegExpMethodPointcutAdvisor与NameMatchMethodPointcutAdvisor类例,只需要修改配置.
<bean id="reg" class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"> <property name="pattern"> <value>.*hello</value> </property> <property name="advice"> <list> <value>logInterceptore</value> </list> </property> </bean>
pattern属性符合完整类名加方法名称.比如IHello下的toHello方法,就要编写com.dynamic.proxy.IHello.toHello.
. 符合任何单一字符
+ 符合前一个字符一次或多次
* 符合前一个字符零次或多次
6.如果要为目标对象提供advice,必须要为其建立代理对象,如果程序规模很大时,一个个代理会很麻烦,spring提供了自动代理BeanNameAutoProxyCreator与 DefaultAdvisorAutoProxyCreator
BeanNameAutoProxyCreator:根据beanName进行自动代理.
spring配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd"> <bean id="logBeforeAdvice" class="com.spring.advices.LogBeforeAdvice"></bean> <bean id="helloService" class="com.dynamic.proxy.HelloImp"> </bean> <bean id="beanNameAutoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="beanNames"> <list> <value>*Service</value> </list> </property> <property name="interceptorNames"> <value>logBeforeAdvice</value> </property> </bean> </beans>
为每个beanName为Service结属的bean提供自动的代理.
public class SpringDemo {
public static void main(String[] args) {
ApplicationContext context = new FileSystemXmlApplicationContext("classpath:applicationContext.xml");
IHello hello = (IHello)context.getBean("helloService");
hello.toHello("callan");
}
}这样在toHello方法调用前也会执行logBeforeAdvice,以后只要想要为目标对象使用log advice时,只要取名为***Service就可以了
评论
这个bean后处理器,根据事务拦截器为目标bean自动创建事务代理
比如配置:
<!-- Spring声明式事务 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> <property name="dataSource" ref="dataSource" /> </bean> <bean id="autoProxyCreator" class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator"> <property name="interceptorNames" value="transactionInterceptor" /> <property name="beanNames" value="*Dao,*Po,*Tao,*BatchDeal" /> </bean> <bean id="transactionInterceptor" class="org.springframework.transaction.interceptor.TransactionInterceptor"> <property name="transactionManager" ref="transactionManager" /> <property name="transactionAttributeSource" ref="transactionAttributeSource" /> </bean> <bean id="transactionAttributeSource" class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource"> <property name="properties"> <props> <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> </props> </property> </bean>
发表评论
- 浏览: 35220 次
- 性别:

- 来自: 上海

- 详细资料
搜索本博客
最近加入圈子
最新评论
-
struts2 的国际化支持
...
-- by w3cw3c -
C# 加密 java解密 (DES)
对中文加密解密不行啊
-- by fxdfxd -
Hibernate Annotation(三 ...
博主,我看到你导入的注解类是javax.persistence.*; 怎么 ...
-- by flyinglife -
Hibernate Annotation(三 ...
谢谢博主,写的非常之好
-- by flyinglife -
struts2 文件上传
byte[] buffer = new byte[1024*10]; ...
-- by shoru






评论排行榜