在看此文章之前,你可能已经知道了,spring是通过Before、After、AfterRunning、AfterThrowing以及Around 共5中通知方式为目标方法增加切面功能,比如一个需要在目标类执行一个目标方法之前和之后分别打印一份日志,就可以建立一个切面在这个方法前后打印日志。但是如果我想在此目标类中再增加一个目标方法是,该怎么办呢?
最简单的办法就是在建立此目标类的时候,增加此方法。但是如果原目标类非常复杂,动一发而牵全身。我们可以为需要添加的方法建立一个类,然后建一个代理类,同时代理该类和目标类。用一个图来表示
图中,A就是原目标类,B就是新添加的方法所在的类,通过建立一个代理类同时代理A和B,调用者调用该代理时,就可以同时A和B中的方法了。
正好spring已经为我们做好这些事情,我们只需要在spring 下乘凉就可以了,通过@DeclareParents注解就可以实现该功能。下面通过代码来演示
代码演示
原有的代码功能
public interface IndexDao {
public void saveUser(String user);
}
@Service
public class IndexDaoImpl implements IndexDao {
@Override
public void saveUser(String user) {
System.out.println("save user" + user);
}
}
这里就假设我们的业务代码很复杂了不想再修改了但是又需要增加功能如何处理
public interface IndexPlusDao {
public void Query();
}
@Service
public class IndexPlusDaoImpl implements IndexPlusDao{
@Override
public void Query() {
System.out.println("IndexPlusDaoImpl query");
}
}
这里增加一个增强版的代码进行补充
Aspect类中增加配置
//"+"表示所有子类;defaultImpl 表示默认需要添加的新的类
@DeclareParents(value = "com.wfg.aop2.dao.*+",defaultImpl = IndexPlusDaoImpl.class)
private static IndexDao indexDao;
测试类
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
IndexDao bean = context.getBean(IndexDao.class);
System.out.println("类名称:"+bean.getClass().getName());
System.out.println("bean instanceof IndexDao :"+(bean instanceof IndexDao));
System.out.println("bean instanceof IndexDaoImpl :"+(bean instanceof IndexDaoImpl));
System.out.println("bean instanceof Proxy :"+(bean instanceof Proxy));
bean.saveUser("zhangsan");
IndexPlusDao dao = (IndexPlusDao) context.getBean(IndexPlusDaoImpl.class);
dao.Query();
}