1 Target object
package com.musi.bean; import org.springframework.stereotype.Component; @Component public class Animal { public void run(){ System.out.println("animal is running ....."); } public void run(String name){ System.out.println(name+" is running ........"); } public void run(int times){ System.out.println("animal running times:"+times); } }
2 Sections
package com.musi.aop.annotationaspect; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.springframework.stereotype.Component; @Aspect @Component public class AnimalAspect { @Before("execution(* com.musi.bean.Animal.run(..))") public void beforeRunning(){ System.out.println("annotation before running ......."); } @After("execution(* com.musi.bean.Animal.run(..))") public void afterRunning(){ System.out.println("annotation after running ......."); } @AfterReturning("execution(* com.musi.bean.Animal.run(..))") public void afterReturning(){ System.out.println("annotation afterReturning running ......."); } @AfterThrowing("execution(* com.musi.bean.Animal.run(..))") public void afterThrowing(){ System.out.println("annotation afterThrowing running ......."); } }
Simplified Writing:
package com.musi.aop.annotationaspect; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class AnimalAspectSimple { @Pointcut("execution(* com.musi.bean.Animal.run())") public void run(){} @Before("run()") public void beforeRunning(){ System.out.println("before running ......."); } @After("run()") public void afterRunning(){ System.out.println("after running ......."); } @AfterReturning("run()") public void afterReturning(){ System.out.println("afterReturning running ......."); } @AfterThrowing("run()") public void afterThrowing(){ System.out.println("afterThrowing running ......."); } }
Note: The @Pointcut annotation is used in the above code, in which the name and actual content of the performance() method are not important. In this case, it should be empty. It is only an identifier itself for the @Pointcut annotation to attach. It is important to note that at this time, except for the annotation and the performance() method without actual operation, the Audience class depends on However, it's a pojo, which is no different from ordinary Java classes. It's just that annotation table names are the most widely used.
3 If you stop at this point, Audience will only be a common bean in the spring container. Even if AspectJ is used, it will not be regarded as an aspect and needs to be configured separately. With Javaconfig, you can enable the automatic proxy function at the class level of the configuration class by using the EnableAspectJ-AutoProxy annotation, as follows:
package com.musi.config; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.EnableAspectJAutoProxy; @Configuration @EnableAspectJAutoProxy @ComponentScan("com.musi") public class SystemConfig { }
The corresponding xml configuration is as follows:
<?xml version="1.0" encoding="UTF-8" ?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <context:component-scan base-package="com.musi"/> <aop:aspectj-autoproxy /> </beans>
4 test classes
package com.musi.test.bean; import com.musi.aop.annotationaspect.Encoreable; import com.musi.bean.Animal; import com.musi.config.SystemConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SystemConfig.class) public class SpringBeanTest { @Autowired private Animal animal; @Test public void test(){ animal.run(); } }
Test classes using xml configuration
package com.musi.test.bean; import com.musi.bean.Animal; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"classpath:application.xml"}) public class SpringXmlTest { @Autowired private Animal animal; @Test public void test(){ animal.run(); } }
5 Create surround notifications
package com.musi.aop.annotationaspect; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class AnimalRoundAspect { @Pointcut("execution(* com.musi.bean.Animal.run(..))") public void run(){} @Around("run()") public void aroundRunning(ProceedingJoinPoint pjp){ try { System.out.println("around before ...."); pjp.proceed(); System.out.println("around after ...."); }catch (Throwable throwable) { System.out.println("around trowing ...."); throwable.printStackTrace(); } } }
Test Class Ibid.
6 Processing parameters in notifications
package com.musi.aop.annotationaspect; import org.aspectj.lang.annotation.After; import org.aspectj.lang.annotation.AfterReturning; import org.aspectj.lang.annotation.AfterThrowing; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; import org.aspectj.lang.annotation.Pointcut; import org.springframework.stereotype.Component; @Aspect @Component public class AnimalArgsAspect { @Pointcut("execution(* com.musi.bean.Animal.run(int))&&args(times)") public void run(int times){} @Before("run(times)") public void beforeRunning(int times){ System.out.println("before running times:"+times); } @After("run(times)") public void afterRunning(int times){ System.out.println("after running times:"+times); } @AfterReturning("run(times)") public void afterReturning(int times){ System.out.println("afterReturning running times:"+times); } @AfterThrowing("run(times)") public void afterThrowing(int times){ System.out.println("afterThrowing running times:"+times); } }
Test class
package com.musi.test.bean; import com.musi.bean.Animal; import com.musi.config.SystemConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SystemConfig.class) public class SpringBeanArgsTest { @Autowired private Animal animal; @Test public void test(){ animal.run(11); } }
7 Introducing new functions through annotations
- Creating Introduced Agents
package com.musi.aop.annotationaspect; public interface Encoreable { void jump(); }
- Proxy default implementation class
package com.musi.aop.annotationaspect; public class EncoreableImpl implements Encoreable { public void jump() { System.out.println("this is EncoreableImpl....."); } }
3) Setting up agents through DeclareParents
package com.musi.aop.annotationaspect; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.DeclareParents; import org.springframework.stereotype.Component; @Aspect @Component public class EncoreableIntroducer { @DeclareParents(value="com.musi.bean.Animal",defaultImpl=EncoreableImpl.class) public static Encoreable encoreable; }
Note: @DeclareParents annotation consists of three parts:
The value attribute specifies which type of bean is to be introduced into the interface. In this case, Animal. (If Animal is an interface, add a plus sign after Animal, that is, "com.musi.bean.Animal+", which means all subtypes of Animal, not Animal itself.)
The defaultImpl attribute specifies the class that provides the implementation for the introduction of functionality. Here we specify the DefaultEncoreable implementation.
@ The static properties annotated in the DeclareParents annotation indicate the interface to be introduced. Here we introduce the Encoreable interface.
In addition, we need to declare Encoreable Introducer as a bean:
4) Test class
package com.musi.test.bean; import com.musi.aop.annotationaspect.Encoreable; import com.musi.bean.Animal; import com.musi.config.SystemConfig; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = SystemConfig.class) public class SpringBeanTest { @Autowired private Animal animal; @Test public void test(){ animal.run(); Encoreable encoreable = (Encoreable)animal; encoreable.jump(); } }