Spring AOP增强的注意

在这里插入图片描述

在同一个类的内部方法之间调用增强方法增强会无效,比如:

待增强的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" />
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值