spring aop支持
来源:百度文库 编辑:神马文学网 时间:2024/04/28 14:34:12
Spring只支持方法的JoinPoints,也就是Adivices将在方法执行的前后被引用,Spring不支持Field成员的Joinpoints,这是因为Spring的设计哲学中认为,支持Field成员的Joinpoints会破坏对象的封装性。
Advices
Advices实现了Aspectj的真正逻辑,根据蒋这些通知织入Targets的时机不同,Spring提供了几种不同的通知,比如,Before、After、Around、Throw。
1.Before
/**
* 前置通知,在目标方法调用之前执行
* @author Administrator
*
*/
public class BeforeAdvicesTest implements MethodBeforeAdvice{
public void before(Method method, Object[] args, Object target)
throws Throwable {
System.out.println("before execute");
}
}
class="com.bhsc.AOP.target.TargetImple">
class="org.springframework.aop.framework.ProxyFactoryBean">
value="com.bhsc.AOP.target.TargetInterface"/>
通知实现了MethodBeforeAdvice,在配置中建立了Advice,Target,还使用了ProxyFactoryBean,这个类会被BeanFactory,ApplicationContext,用来建立代理对象,并配置了实现的接口,在不指定目标方法时,Before Advice会被织入到接口上的所有方法。
Advice的Target并不是动态代理中的代理对象,而是真实的对象,也就是动态代理中传入的真正的类。
拿动态代理来对比下:
Object proxy = Proxy.newProxyInstance(Monkey.class.getClassLoader(),
Monkey.class.getInterfaces(),
new MyInvocationHandler( new Monkey()));
可以看到动态代理中,真正的类是new时候传入的,而Spring则配置在文件中注入了。
2.After 和Before类似
3.Around
/**
* Around通知,在真正执行某个方法前,会先插入Interceptor,如果有多个,则会一个个执行,然后执行method的方法,将执行流程转给下一个Interceptor,最后一层层返回堆栈,最后离开堆栈返回应用程序本身的流程。
* @author Administrator
*
*/
public class MethodInterceptorTest implements MethodInterceptor{
public Object invoke(MethodInvocation methodInvocation) throws Throwable {
System.out.println("execute method:"+methodInvocation.getMethod());
Object result=null;
result=methodInvocation.proceed();
return result;
}
}
class="com.bhsc.AOP.MethodInterceptorTest">
class="org.springframework.aop.framework.ProxyFactoryBean">
value="com.bhsc.AOP.target.TargetInterface"/>
1.Throw 如果抛出的异常类型和发生的类型相同,那么就会执行通知方法。
前面的Advice,一定程度上也包括切入点,也就是一个类的所有方法,不过这些都是粗粒度的,事实上,我们可以定义更细粒度的,定义需要的方法,那就是PointCut。
PointCutAdvisor
PointCut定义了Joinpoint的集合,表示Advice应用的时机(方法)。在Spring中,用PointcutAdvisor表示PointCut和Advisor的结合,就是aspect。PointcutAdvisor是Advisor的子接口:
public interface Advisor {
Advice getAdvice();
/**
* @return whether this advice is associated with a particular target instance
*/
boolean isPerInstance();
public interface PointcutAdvisor extends Advisor {
/**
* Get the Pointcut that drives this advisor.
*/
Pointcut getPointcut();
}
分别有NameMatchMethodPointcutAdvisor、RegexpMethodPointcutAdvisor、ControlFlowPointcut
1.NameMatchMethodPointcutAdvisor ,最基本的PointcutAdvisor,可以使用表达式指定Advice应用目标上的方法名称。
support.NameMatchMethodPointcutAdvisor">
class="org.springframework.aop.framework.ProxyFactoryBean">
value="com.bhsc.AOP.target.TargetInterface"/>
在target中加入nihao方法:
public void nihao(String name){
System.out.println("你好 :"+name);
}
TargetInterface ti=(TargetInterface)ctx.getBean("helloProxy");
ti=(TargetInterface)ctx.getBean("helloAdvisorProxy");
ti.hello("lisi");
ti.nihao("lisi");
结果:
before execute
hello :lisi
你好 :lisi
2.RegexpMethodPointcutAdvisor,使用正则来编写pointcut表达式。
3.ControlFlowPointcut
用来判断某个方法中,是否要求目标对象执行某个方法,在执行时期动态决定是否介入Advice来提供服务,所以这是动态的PointCut功能。
public class Some implements ApplicationContextAware{
private TargetInterface target;
public void setApplicationContext(ApplicationContext
applicationContext)throws BeansException {
target=(TargetInterface)applicationContext.getBean("");
}
public void helloEverybody(){
target.hello("wangwu");
target.nihao("qw");
}
public void hello(){
System.out.println("hello!");
}
boolean flag=true;
if(flag){
some.helloEverybody();
}else{
some.hello();
}
PointCut
public interface Pointcut {
ClassFilter getClassFilter();
MethodMatcher getMethodMatcher();
Pointcut TRUE = TruePointcut.INSTANCE;
}
TruePointcut是PointCut的简单实现,传回的ClassFilter是ClassFilter.TRUE,传回的MethodMatcher是MethodMatcher.TRUE;
ClassFilter决定一个类是否要应用Advice,matches决定传入的类是否符合PointCur的定义。
public interface ClassFilter {
boolean matches(Class clazz);
ClassFilter TRUE = TrueClassFilter.INSTANCE;
}
MethodMatcher决定某个方法是否要应用Advice:
public interface MethodMatcher {
boolean matches(Method method, Class targetClass);
boolean isRuntime();
boolean matches(Method method, Class targetClass, Object[] args);
MethodMatcher TRUE = TrueMethodMatcher.INSTANCE;
如果是静态的PointCut,比如前面的NameMatchMethodPointcutAdvisor ,
RegexpMethodPointcutAdvisor,则执行第一个方法,isRuntime返回FALSE,否则执行第二个方法,isRuntime返回true。
Introduction
是一种特殊的Advice,从行为上来看,它不像前面的Before,After等,在方法前后介入服务,而是直接介入整个对象的行为,就好像凭空多了一些可操作的行为,为对象动态加入(Mixin)原先所没有的职责。
class="onlyfun.caterpillar.OtherIntroduction" />
"org.springframework.aop.support.DefaultIntroductionAdvisor">
class="org.springframework.aop.framework.ProxyFactoryBean">
value="onlyfun.caterpillar.ISome" />
ApplicationContext ctx = new
ClassPathXmlApplicationContext("Aop.xml");
ISome some=(ISome)ctx.getBean("proxyFactoryBean");
some.doSome();
//看起来像是增加了职责
原来对象的职责。。。
Autoproxing
自动代理可以不用为每一个目标对象手动代理对象,使用自动代理,可以通过Bean名称或是Pointcut对比,自动为符合对比条件的目标对象建立代理对象。
1.BeanNameAutoProxyCreator
看一下前面的配置:
class="com.bhsc.AOP.target.TargetImple">
class="org.springframework.aop.framework.ProxyFactoryBean">
value="com.bhsc.AOP.target.TargetInterface"/>
不仅要定于Advice,target,还要定义一个代理对象,配置接口,target等,如果应用比较大,那么一个个配置是很麻烦的,PointcutAdvisor的定义只是对切入点更准确的定义,并不能解决配置繁琐的问题(NameMatchMethodPointcutAdvisor),不过Spring提供了自动代理,可以更加简单的配置。
比如,我们为Bean取好名称,xxxService,这样,就可以使用BeanNameAutoProxyCreator配置:
class="org.springframework.
aop.framework.autoproxy.BeanNameAutoProxyCreator">
ISome someService=(ISome)ctx.getBean("someService");
someService.doSome();
((IOther)someService).doOther();
2.DefaultAdvisorAutoProxyCreator:自动搜寻