众所周知,AspectJ可以通过@Before,@After,@Around等注解对连接点进行增强,今天我们来玩一个新注解@DeclareParents。对目标对象增强一个新方法。
- 场景引入:
现在我们有一个动物鸭子类,它有个游泳的函数,但是突然有一天我们需要给动物鸭子实现一个很好吃的食材属性。我们当然可以去动物鸭子类去新增一个方法,但是违背了单一原则。我们可以通过AOP来实现增强。
- Code show time
有一个Animal的接口
public interface Animal { void swim(); }
再来一个动物鸭子的实现类
@Repository("animal") public class DuckAnimal implements Animal{ @Override public void swim() { System.out.println("鸭子喜欢游泳。。。"); } }
需要一个增强方法,实现鸭子是一种美味的食物
public interface Food { void eat(); } @Repository("food") public class DuckFood implements Food{ @Override public void eat() { System.out.println("鸭子看起来很好吃。。。"); } }
采用自动注入
@ComponentScan("com.zjt.springboot.DeclareParents") @Configuration @EnableAspectJAutoProxy public class AppConfiguration { }
声明一个切面
@Aspect @Component public class MyAspect { /** * com.zjt.springboot.DeclareParents.Animal+ 表示增强Animal的所有子类 * *defaultImpl=DuckFood.class 表示默认需要添加的新类 */ @DeclareParents(value="com.zjt.springboot.DeclareParents.Animal+", defaultImpl=DuckFood.class) public static Food food; }
接下来就是紧张刺激的测试环节了:
public class Test { public static void main(String[] args) { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfiguration.class); Animal animal = (Animal)context.getBean("animal"); animal.swim(); Food food = (Food)animal; food.eat(); } }
测试结果:
鸭子喜欢游泳。。。
鸭子看起来很好吃。。。
结论:从测试结果我们发现,只从容器里获取了一个动物鸭子,却可以得到食材的功能,实现了增强功能!