spring使用aop
增强通知的种类:
a.前置通知:在执行目标方法前实施某种逻辑.
b.后置通知:在执行目标方法后实施某种逻辑.
c.环绕通知在执行目标方法前后实施某种逻辑.
d.异常抛出通知:在执行目标方法抛出异常实施某种逻辑.
e.引入通知:在执行目标类添加新方法和属性.
一.先从一个前置通知例子入手:
1.ForumService.java和ForumServiceImpl.java参考spring aop(一)--基于JDK
二.以上配置都是编程式来生成代理,可以将此代理实例注册成为spring的bean.以下是基于xml的applicationContext.xml声明式配置例子(基于java-config就简单得多了).
增强通知的种类:
a.前置通知:在执行目标方法前实施某种逻辑.
b.后置通知:在执行目标方法后实施某种逻辑.
c.环绕通知在执行目标方法前后实施某种逻辑.
d.异常抛出通知:在执行目标方法抛出异常实施某种逻辑.
e.引入通知:在执行目标类添加新方法和属性.
一.先从一个前置通知例子入手:
1.ForumService.java和ForumServiceImpl.java参考spring aop(一)--基于JDK
2.实现MethodBeforeAdvice接口的ForumBeforeAdvice来实现前置通知的业务逻辑,下面只是简单输出一句话,按下面使用,那么每次调用ForumServiceImpl的每个方法前都么输出这句话.
import org.springframework.aop.MethodBeforeAdvice;
import java.lang.reflect.Method;
public class ForumBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("before advice:"+method);
}
}
3.测试使用
import org.springframework.aop.BeforeAdvice;
import org.springframework.aop.framework.ProxyFactory;
public class TestForumService {
public static void main(String[] args) {
ForumService target=new ForumServiceImpl();
BeforeAdvice advice=new ForumBeforeAdvice();
ProxyFactory proxyFactory=new ProxyFactory();
//proxyFactory.setInterfaces(target.getClass().getInterfaces());
//proxyFactory.setOptimize(true);
proxyFactory.setTarget(target);
proxyFactory.addAdvice(advice);
ForumService proxy= (ForumService) proxyFactory.getProxy();
proxy.removeForum(10);
proxy.removeTopic(1012);
}
}
小结:spring到底使用基于jdk还是基于CGLib创建动态代理,取决于你的配置,按上面的配置是使用了ObjenesisCglibAopProxy来创建代理.至于详细,可进入org.springframework.aop.framework.DefaultAopProxyFactory.createAopProxy方法调试.
二.以上配置都是编程式来生成代理,可以将此代理实例注册成为spring的bean.以下是基于xml的applicationContext.xml声明式配置例子(基于java-config就简单得多了).
<?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">
<bean id="forumServiceImpl" class="org.exam.aop.ForumServiceImpl" />
<bean id="forumBeforeAdvice" class="org.exam.aop.ForumBeforeAdvice" />
<bean id="forumService" class="org.springframework.aop.framework.ProxyFactoryBean">
<property name="interfaces" value="org.exam.aop.ForumService" />
<property name="interceptorNames">
<list>
<value>forumBeforeAdvice</value>
</list>
</property>
<property name="target" ref="forumServiceImpl" />
</bean>
</beans>
基于java config的一个配置例子:
import org.aopalliance.aop.Advice;
import org.exam.aop.DebugInterceptor;
import org.exam.service.UserService;
import org.exam.service.UserServiceImpl;
import org.springframework.aop.framework.ProxyFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class AppConfig{
@Bean
public UserService userServiceImpl(){
return new UserServiceImpl();
}
@Bean
public Advice debugInterceptor(){
return new DebugInterceptor();
}
@Bean
public ProxyFactoryBean userService(){
ProxyFactoryBean userService=new ProxyFactoryBean();
userService.setInterceptorNames("debugInterceptor");
userService.setTarget(userServiceImpl());
return userService;
}
}
注册ProxyFactoryBean,要做两步:
1.定义使用的Advisor链(一系列Advisor Bean),并注入该Bean的interceptorNames属性.
2.定义要创建代理的Bean,并注入该Bean的target属性(可选:还有要创建代理Bean的接口名称注入该Bean的interfaces).
测试使用:
public class Main {
public static void main(String[] args) throws InterruptedException {
ApplicationContext applicationContext=new ClassPathXmlApplicationContext("applicationContext.xml");
ForumService proxy= (ForumService) applicationContext.getBean("forumService");
proxy.removeForum(10);
proxy.removeTopic(1012);
}
}
直到目前为止,前面介绍的使用,横切逻辑都被织入了目标类的所有方法.下篇文章会介绍使用基于@AspectJ来定义一个切面.