在同一个类的内部方法之间调用增强方法增强会无效,比如:
待增强的bean:
package com.smart.advisor;
public class Waiter{
public void serveTo(String name){
System.out.println("waiter serving "+name+"...");
//内部调用greetTo方法
greetTo(name);
}
public void greetTo(String name) {
System.out.println("waiter greet to "+name+"...");
}
}
配置xml:
<bean id="waiter" class="com.smart.advisor.Waiter" />
<bean id="greetingAdvice" class="com.smart.advisor.GreetingBeforeAdvice" />
<bean id="regexpAdvisor"
class="org.springframework.aop.support.RegexpMethodPointcutAdvisor"
p:patterns=".*To.*" p:advice-ref="greetingAdvice" />
<bean
class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" p:proxyTargetClass="true" />
调用:
String configPath = "com/smart/autoproxy/beans-aware.xml";
ApplicationContext ctx = new ClassPathXmlApplicationContext(configPath);
Waiter waiter = (Waiter) ctx.getBean("waiter");
waiter.serveTo("John");
会发现serveTo中调的greetTo方法并没有增强,解决方法有两种,比较简单的是使用AspectJ进行代理,这里介绍另外一种方法
本质上就是Waiter bean里面注入自己的bean
ContextRefreshedEvent为上下文刷新事件,通过ApplicationListener注册此事件监听,spring容器加载完毕后,就会自动执行onApplicationEvent方法,具体见后面。
Waiter bean改写
package com.smart.advisor;
import com.smart.aop.BeanSelfProxyAware;
public class Waiter implements BeanSelfProxyAware{
private Waiter waiter;
public void setSelfProxy(Object object) {
waiter = (Waiter)object;
}
public void serveTo(String name){
System.out.println("waiter serving "+name+"...");
waiter.greetTo(name);
}
public void greetTo(String name) {
System.out.println("waiter greet to "+name+"...");
}
}
其中BeanSelfProxyAware接口是自己定义的,需重写setSelfProxy方法,为的是方便将自己的bean注入
package com.smart.aop;
public interface BeanSelfProxyAware {
void setSelfProxy(Object object);
}
定义一个工厂bean,专门将自己的bean注入自己
package com.smart.aop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;
import java.util.Map;
@Component
public class BeanSelfProxyAwareMounter implements SystemBootAddon, ApplicationContextAware {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private ApplicationContext applicationContext;
//重写了ApplicationContextAware接口后,setApplicationContext这个会被自动注入
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public void onReady() {
Map<String, BeanSelfProxyAware> proxyAwareMap =
applicationContext.getBeansOfType(BeanSelfProxyAware.class);
if(proxyAwareMap!=null){
for (BeanSelfProxyAware beanSelfProxyAware : proxyAwareMap.values()) {
beanSelfProxyAware.setSelfProxy(beanSelfProxyAware);
if (logger.isDebugEnabled()) {
logger.debug("{}注册自身被代理的实例.");
}
}
}
}
//最先被加载
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
}
其中实现了ApplicationContextAware接口后重写setApplicationContext方法时,ApplicationContext环境变量会被自动注入,SystemBootAddon为自定义接口,需重写onReady方法,为的是方便spring启动的时候可以很方便的调用onReady方法。
SystemBootAddon接口
package com.smart.aop;
import org.springframework.core.Ordered;
public interface SystemBootAddon extends Ordered {
/**
* 在系统就绪后调用的方法
*/
void onReady();
}
实现ApplicationListener监视器,范型使用ContextRefreshedEvent后,spring容器加载完毕后,就会自动执行onApplicationEvent方法。
监视器定义
package com.smart.aop;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.core.OrderComparator;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import java.util.Collections;
import java.util.List;
@Component
public class SystemBootManager implements ApplicationListener<ContextRefreshedEvent> {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private List<SystemBootAddon> systemBootAddons = Collections.EMPTY_LIST;
private boolean hasRunOnce = false;
//注入上面定义的SystemBootAddon的启动项
@Autowired(required = false)
public void setSystemBootAddons(List<SystemBootAddon> systemBootAddons) {
Assert.notEmpty(systemBootAddons);
OrderComparator.sort(systemBootAddons);
this.systemBootAddons =systemBootAddons;
}
//ApplicationListener<>里边的泛型需要继承ApplicationEvent抽象方法
//ContextRefreshedEvent为上下文刷新事件,实现了这个接口,spring容器加载完毕后,就会执行这个实现类的重写的方法.
public void onApplicationEvent(ContextRefreshedEvent event) {
if (!hasRunOnce) {
for (SystemBootAddon systemBootAddon : systemBootAddons) {
systemBootAddon.onReady();
if (logger.isDebugEnabled()) {
logger.debug("执行插件:{}",systemBootAddon.getClass().getCanonicalName());
}
}
hasRunOnce = true;
}else{
if (logger.isDebugEnabled()) {
logger.debug("已执行过容器启动插件集,本次忽略之.");
}
}
}
}
在xml中需开启上下文扫描,不然@Component定义的pojo不会加载。
<context:component-scan base-package="com.smart.aop" />