SpringAOP

SpringAOP

The concept of AOP

AOP - (Aspect Orient Programming): Aspect Oriented Programming is a programming idea that complements OOP (Aspect Orient Programming). AOP extracts the same code scattered in different business logics, rebuilds it into a module, and weaves this module into the business logic that requires the module through a cross-sectional approach.

There is a picture in the book "Spring Actual Combat (4th Edition)" which explains the idea very vividly.

Why do we need the idea of AOP?

In actual development, a log will be added to each business code to monitor and record the operation of the business code. At this time, we need to add every place that needs to use the log. If there are only one, two, three or four places that need to add a log, then there is no problem with manually adding it, but what about thousands? Obviously, manual addition is not appropriate. At this time, some technology is needed to simplify. AOP is to add log functions to these business codes through a horizontal cross-sectional approach.

AOP terminology

  • Advice: Enhanced processing in the AOP framework. The notification describes when the aspect will be executed and how the enhancement will be executed.
  • Join point: A join point represents a point where an aspect can be inserted during application execution. This point can be a method call or an exception thrown. In Spring AOP, the connection point is always a method call.
  • PointCut: A connection point for enhanced processing can be inserted. Use some expressions to indicate the connection points to be enhanced
  • Aspect: Aspect is a combination of notice and point of contact. That is Aspect=Advice+PointCut
  • Introduction: Introduction allows us to add new methods or properties to existing classes.
  • Weaving: Add enhancement processing to the target object and create an enhanced object. This process is weaving

AspectJ and SpringAOP

AOP is a programming idea, it is a goal, and the specific implementation is implemented by SpringAOP or AspectJ

AspectJ is an aspect-oriented framework that extends the Java language. AspectJ defines the AOP syntax, and it has a special compiler used to generate Class files that comply with the Java byte encoding specification. AspectJ uses a static proxy method for weaving. Static proxy refers to the use of commands provided by the AOP framework to compile, so that the AOP proxy class can be generated during the compilation phase, so it is also called compile-time enhancement. There are three weaving opportunities for static agents: compilation period (compiling with ajc), post-compilation period (that is, weaving after generating class files or typing into a jar package), and weaving after class loading (using WeavingURLClassLoader class loader). Because it has been determined during compilation, the performance is good. AspectJ can support weaving in fields, methods, and constructors.

SpringAOP is an AOP framework written by Spring with reference to AspectJ. It is based on dynamic proxy implementation, if you use an interface, use JDK dynamic proxy technology to implement, if it is a common class, it is implemented through CGLIB. It also needs to rely on SpringIOC for management, so it can only perform AOP on SpringBean. SpringAOP can only be woven at runtime, so the dynamic generation of proxy instances at runtime leads to lower performance. SpringAOP can only support the weaving of methods, and its function is weak.

Dynamic Agent Technology

What is dynamic proxy technology? The dynamic proxy technology is to create the proxy object of the target object, and carry out a functional enhancement technology to the method of the target object. The created proxy object is not generated in the class file at the beginning, but dynamically generated during the run, and disappears after the program runs. Therefore, when using dynamic proxy technology, the object you get is not the original object, but the object proxied by the dynamic proxy. This technology can perform some functional enhancements to the methods in the original code without modifying the source code, reducing the coupling of the code.

Ordinary object creation process

The process of creating an object through a dynamic proxy

Two ways to implement dynamic proxy

The first JDK dynamic proxy, which is used to implement the dynamic proxy of the interface. JDK dynamic proxy is a dynamic proxy technology that comes with Java, which mainly involves two classes under the java.lang.reflect package: Proxy and InvocationHandler. The cross-cutting logic can be defined by implementing the InvocationHandler interface, and the code of the target class can be called through the reflection mechanism to dynamically organize the business code logic and the cross-cutting logic together.

The second one is CGLIB (Code Generation Library), which is used to implement dynamic proxies for common classes. It is a bytecode generation library based on ASM, which performs dynamic proxy through inheritance, and uses method interception technology in subclasses to intercept all parent class method calls and weave into crosscutting logic. Since CGLIB is dynamically proxied by inheritance, the proxied class cannot be modified by final

Next, use the code to further understand these two technologies.

JDK dynamic proxy

//Define the interface public interface UserService { public void getone () ; public void gettwo () ; } //Implement the interface public class UserServiceImpl implements UserService { @Override public void getone () { System.out.println( "I am the first" ); } @Override public void gettwo () { System.out.println( "I am the second one" ); } } //Implement the InvocationHandler interface. //The InvocationHandler interface is the method of loading the interface implementation class through the reflection mechanism, so as to weave the method of the proxy object cross-cutting logic public class ServiceProxy implements InvocationHandler { public Object target; public ServiceProxy (Object target) { this .target = target; } @Override public Object invoke (Object proxy, Method method, Object[] args) throws Throwable { System.out.println( "????" ); Object invoke = method.invoke(target, args); System.out.println( "!!!!" ); return invoke; } } //Test class public class ProxyTest { public static void main (String[] args) { UserService userService = new UserServiceImpl(); ServiceProxy serviceProxy = new ServiceProxy(userService); UserService userService1= (UserService)Proxy.newProxyInstance(UserService.class.getClassLoader(), new Class[]{UserService.class}, serviceProxy); userService1.getone(); userService1.gettwo(); } } /* result: ??? I am the first !!!! ??? I am the second !!!! */ Copy code

Through the above code, it is found that the realization of JDK dynamic proxy mainly depends on the newProxyInstance() method under the Proxy class. This method has three parameters: ClassLoader loader, Class<?>[] interfaces, and InvocationHandler h.

loader: class loader, used to load the interface

interfaces: an array of interface classes to be dynamically proxied

InvocationHandler: Invocation handler. The invoke method in the parameter will be executed when the method of the proxy object is called. All methods in the proxy object will be intercepted.

CGLIB dynamic agent

To achieve this function, you first need to import two jar packages, asm and cglib

//The common class that needs to implement proxy public class OtherClass { public void say () { System.out.println( "I am dealing with business" ); } } //Test class public class CGLibTest { public static void main (String[] args) { OtherClass otherClass = new OtherClass(); OtherClass o = (OtherClass)Enhancer.create(otherClass.getClass(), new MethodInterceptor() { @Override public Object intercept (Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { System.out.println( "Realize CGLIB dynamic proxy" ); Object invoke = method.invoke(otherClass, objects); return invoke; } }); o.say(); } } /* result Realize CGLIB dynamic proxy I'm dealing with business */ Copy code

According to the above code, dynamic proxy is performed through the create method under the Enhancer class. There are two parameters in this method, Class type and Callback callback.

type: The class that needs to implement dynamic proxy

Callback: An interface that can be understood as the logic that will be executed when the method of the generated proxy class is called.

Its implementation classes are as follows

  1. MethodInterceptor
  2. NoOp
  3. LazyLoader
  4. Dispatcher
  5. InvocationHandler
  6. FixedValue

If you want to learn more, you can do it yourself.

SpringAOP code implementation

SpringAOP has two ways to implement code, one is XML file, which has always been based on annotations. Because as long as you learn how to write in XML, the way of annotation is very simple, so the next step will be to write code through XML files.

Need to be introduced before the code is written

< Dependency > < the groupId > org.aspectj </the groupId > < the artifactId > aspectjweaver </the artifactId > < Version > 1.9.6 </Version > </dependency > copy the code

First enable AOP support. There are also two ways. One is to enable it through the aop:aspectj-autoproxy/ tag, and the other is to enable it through the annotation @EnableAspectJAutoProxy.

Next, perform a simple test

//Define the interface public interface UserService { public void info () ; } //Define the implementation class of the interface public class UserServiceImpl implements UserService { @Override public void info () { System.out.println( "Info" ); } } //Define the aspect public class AJOne { public void say () { System.out.println( "I am in the first place" ); } } Copy code
<!--Write xml code--> <!--Enable AOP support--> <aop:aspectj-autoproxy/> <!--Define the aspect class--> <bean id="Ajone" class="com.itheima.aop.AJOne"/> <!--IOC for the implementation class of the interface. As mentioned earlier, the object of the SpringAOP proxy must be SpringBean, so you must first register the Bean--> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <!--Configure AOP--> <aop:config> <!--Configure the pointcut writing of AOP to find the method that needs to be proxied--> <aop:pointcut id="pointcutOne" expression="execution(* com.itheima.service.UserServiceImpl.info(..))"/> <!--Declare the aspect class--> <aop:aspect ref="Ajone"> <!--Configure the Advice notification, here is the pre-notification --> <aop:before method="say" pointcut-ref="pointcutOne"></aop:before> </aop:aspect> </aop:config> Copy code
//Write test class public class Test01 { public static void main (String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext( "/ApplicationContext.xml" ); UserService userService = cp.getBean( "userService" , UserService.class); userService.info(); } } /* result: I'm in the first place Info */ Copy code

Since SpringAOP is implemented through JDK proxy or CGLIB proxy, what is the default?

Answer through DEBUG

It is found that JDK proxy technology is used by default, so how to modify it to CGLIB? It can be modified through the proxy-target-class attribute in the aop:config tag and set it to true to become a CGLIB implementation.

The above is one of the simplest implementations of SpringAOP, and some functions in it will be explained in detail next.

Advice-Notice

As mentioned earlier, the notification describes when the aspect is executed and how to perform the enhancement processing. There are five types of notifications in SpringAOP, namely, before notification (Before), after notification (AfterReturning), surrounding notification (Around), exception notification (AfterThrowing), and final notification (After).

A piece of code is used to describe the location of these five notifications and the execution order of these five notifications

try { AroundBefore(); //Around the notification header Before(); //Front notification method(); //Business code AroundAfter(); //Around the notification tail After(); //After notification ) catch (Throwable t) { AfterThrowing(); //Exception notification } finally { AfterReturning(); //Final notice } Copy code

Before implementing the code, first accept two classes, one is JoinPoint, and the other is ProceedingJoinPoint, a subclass of JoinPoint.

JoinPoint encapsulates the aspect information in SpringAop. Add this parameter to the aspect method to obtain the JoinPoint object that encapsulates the information of the method.

The method in JoinPoint is as follows

Method nameFeatures
Signature getSignature();Get the object that encapsulates the signature information, in which you can get the target method name, the Class of the class and other information
Object[] getArgs();Get the parameter object passed into the target method
Object getTarget();Get the object being proxied
Object getThis();Get proxy object

Because ProceedingJoinPoint is a subclass of JoinPoint, it can use all the methods of JoinPoint. It also adds two methods:

Object the proceed () throws Throwable //execution of the target method Object the proceed (Object [] var1) throws Throwable //new parameter passed to the target method executed copy the code

ProceedingJoinPoint can only be used when surrounding notifications

Next, implement the code for these five notifications respectively

Prior notice (Before)

Weaving before the method is implemented

//Define the interface public interface UserService { public void info () ; } //Define the implementation class of the interface public class UserServiceImpl implements UserService { @Override public void info () { System.out.println( "Info" ); } } //Define the aspect public class AJOne { public void before (JoinPoint joinPoint) { System.out.println( "Method name to obtain proxy object" +joinPoint.getSignature().getName()); System.out.println( "Get the parameters of the method in the proxy object" + Arrays.toString(joinPoint.getArgs())); System.out.println( "Get the delegated object" +joinPoint.getTarget().toString()); System.out.println( "Get the proxy object" +joinPoint.getThis().toString()); System.out.println( "Pre-notification" ); } } Copy code
< bean id = "Ajone" class = "com.itheima.aop.AJOne"/> < bean id = "userService" class = "com.itheima.service.UserServiceImpl"/> < aop:config > < aop:pointcut id = "pointcutOne" expression = "execution(* com.itheima.service.UserServiceImpl.info(..))"/> < aop:aspect ref = "Ajone" > < aop:before method = "before" pointcut-ref = "pointcutOne" > </aop:before > </aop:aspect > </aop:config > Copy code
//Test class public class Test02 { public static void main (String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext( "/ApplicationContext.xml" ); UserService userService = cp.getBean( "userService" , UserService.class); userService.info(); } } /* result: Get the method name info of the proxy object Get the parameters of the method in the proxy object[] Get the proxy object com.itheima.service.UserServiceImpl@20d28811 Get the proxy object com.itheima.service.UserServiceImpl@20d28811 Advance notice Info */ Copy code

AfterReturning

Weaving after the method is implemented, the notification can get the return value of the method

//Define the interface public interface UserService { public int add ( int a, int b) ; } //Define the implementation class of the interface public class UserServiceImpl implements UserService { @Override public int add ( int a, int b) { return a+b; } } //Define the aspect public class AJOne { public void afterreturning (Object val) { System.out.println( "The return value of the method obtained by the post notification" +val); } } Copy code
< bean id = "Ajone" class = "com.itheima.aop.AJOne"/> < bean id = "userService" class = "com.itheima.service.UserServiceImpl"/> < aop:config > < aop:pointcut id = "pointcutTwo" expression = "execution(* com.itheima.service.UserServiceImpl.add(..))"/> < aop:aspect ref = "Ajone" > <!--returning attribute is to assign the return value to the method In the parameter --> < aop:after-returning method ="afterReturning" the pointcut-REF = "pointcutTwo" returning = "Val"/> </AOP: Aspect > </AOP: config > copy the code
//Test class public class Test03 { public static void main (String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext( "/ApplicationContext.xml" ); UserService userService = cp.getBean( "userService" , UserService.class); int i = userService.add( 5 , 2 ); System.out.println(i); } } /* result: The return value of the method obtained by the post-notification is 7 7 */ Copy code

Around

Weaving before and after the implementation of the method, the implementation of the method depends on the proceeding() method in proceedingJoinPoint

//Define the interface public interface UserService { public int add ( int a, int b) ; } //Define the implementation class of the interface public class UserServiceImpl implements UserService { @Override public int add ( int a, int b) { return a+b; } } //Define the aspect public class AJOne { public int around (ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println( "surround forward notification" ); Integer proceed = (Integer)proceedingJoinPoint.proceed(); //The proceed method must be used for the surround notification, the method of the target object can be used, we can get the return value of the method of the target object and modify it System.out.println(proceed); System.out.println( "Surround rear notification" ); return 10 ; } } Copy code
< bean id = "Ajone" class = "com.itheima.aop.AJOne"/> < bean id = "userService" class = "com.itheima.service.UserServiceImpl"/> < aop:config > < aop:pointcut id = "pointcutThree" expression = "execution(* com.itheima.service.UserServiceImpl.add(..))"/> < aop:aspect ref = "Ajone" > < aop:around method = "around" pointcut-ref ="pointcutThree"/> </aop:aspect > </aop:config > Copy code
//Test class public class Test04 { public static void main (String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext( "/ApplicationContext.xml" ); UserService userService = cp.getBean( "userService" , UserService.class); int i = userService.add( 5 , 2 ); System.out.println(i); } } /* result: Surround front notification 7 Surround back notification 10 */ Copy code

Through the results, we found that we did modify the return value of the proxy object's method.

Exception notification (AfterThrowing)

Execute when the method of the proxy object throws an exception

//Define the interface public interface UserService { public int division ( int a, int b) ; } public class UserServiceImpl implements UserService { @Override public int division ( int a, int b) { return a/b; } } //Define the aspect public class AJOne { public void throwing (Throwable t) { System.out.println( "Exception Notification" ); System.out.println(t.getMessage()); } } Copy code
< bean id = "Ajone" class = "com.itheima.aop.AJOne"/> < bean id = "userService" class = "com.itheima.service.UserServiceImpl"/> < aop:config > < aop:pointcut id = "pointcutFour" expression = "execution(*com.itheima.service.UserServiceImpl.division(..))"/> < aop:aspect ref = "Ajone" > <!--throwing attribute is the exception class in the method Parameter name --> < aop:after-throwing method ="the throwing" the pointcut-REF = "pointcutFour" the throwing = "T"/> </AOP: Aspect > </AOP: config > copy the code
//Test class public class Test05 { public static void main (String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext( "/ApplicationContext.xml" ); UserService userService = cp.getBean( "userService" , UserService.class); int i = userService.division( 5 , 0 ); System.out.println(i); } } /* result: Exception notification /by zero */ Copy code

Final notice (After)

It will be executed regardless of whether the code has an exception

//Define the interface public interface UserService { public int division ( int a, int b) ; } public class UserServiceImpl implements UserService { @Override public int division ( int a, int b) { return a/b; } } //Define the aspect public class AJOne { public void after () { System.out.println( "Final Notice" ); } } Copy code
< bean id = "Ajone" class = "com.itheima.aop.AJOne"/> < bean id = "userService" class = "com.itheima.service.UserServiceImpl" < aop:config > < aop:pointcut id = " pointcutFive" expression = "execution(* com.itheima.service.UserServiceImpl.division(..))"/> < aop:aspect ref = "Ajone" > < aop:after method = "after" pointcut-ref ="pointcutFive"/> </aop:aspect > </aop:config > Copy code
//Test class public class Test06 { public static void main (String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext( "/ApplicationContext.xml" ); UserService userService = cp.getBean( "userService" , UserService.class); int i = userService.division( 5 , 0 ); System.out.println(i); } } /* result: Final notice Exception in thread "main" java.lang.ArithmeticException:/by zero at com.itheima.service.UserServiceImpl.division(UserServiceImpl.java:22) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:49) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:215) at com.sun.proxy.$Proxy4.division(Unknown Source) at com.itheima.test.Test06.main(Test06.java:14) Process finished with exit code 1 */

.

Pointcut-

execution()

arg()

@args()

target()

@target()

within()

@within()

this AOP Bean

@annotation

xml && || xml and or not

execution() execution()

arg()

// public interface UserService { public void info(String s1,String s2); public void info(int num); } // public class UserServiceImpl implements UserService{ @Override public void info(String s1, String s2) { System.out.println(s1+"=="+s2); } @Override public void info(int num) { System.out.println(num); } } // public class BeforeAdvice { public void problem(){ System.out.println(" "); } }
<bean id="beforeAdvice" class="com.itheima.AJ.BeforeAdvice"/> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <aop:config> <!-- arg String --> <aop:pointcut id="argTest" expression="args(java.lang.String,java.lang.String)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="problem" pointcut-ref="argTest"/> </aop:aspect> </aop:config>
// public class Test07 { public static void main(String[] args) { ClassPathXmlApplicationContext cc = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); UserService userService = cc.getBean("userService", UserService.class); userService.info("One","Two"); userService.info(50); } } /* One==Two 50 */

arg

@args()

@args @args

// @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Args { } // @Args public class Car { @Override public String toString() { return "car!!!"; } } // public interface UserService { public void info(String s1, String s2); public void info(int num); public void info(Car car); } // public class UserServiceImpl implements UserService{ @Override public void info(String s1, String s2) { System.out.println(s1+"=="+s2); } @Override public void info(int num) { System.out.println(num); } @Override public void info(Car car) { System.out.println(car); } } // public class BeforeAdvice { public void problem(){ System.out.println(" "); } }
<bean id="beforeAdvice" class="com.itheima.AJ.BeforeAdvice"/> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <aop:config> <!-- Args --> <aop:pointcut id="Args" expression="@args(com.itheima.annotated.Args)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="problem" pointcut-ref="Args"/> </aop:aspect> </aop:config>
// public class Test08 { public static void main(String[] args) { ClassPathXmlApplicationContext cc = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); UserService userService = cc.getBean("userService", UserService.class); userService.info("One","Two"); userService.info(50); userService.info(new Car()); } } /* One==Two 50 car!!! */

target()

// public interface PeopleService { public void say(int num); } public interface UserService { public void info(String s1, String s2); public void info(int num); public void info(Car car); } // public class PeopleServiceImpl implements PeopleService{ @Override public void say(int num) { System.out.println(num); } } public class UserServiceImpl implements UserService{ @Override public void info(String s1, String s2) { System.out.println(s1+"=="+s2); } @Override public void info(int num) { System.out.println(num); } @Override public void info(Car car) { System.out.println(car); } } // public class BeforeAdvice { public void problem(){ System.out.println(" "); } }
<bean id="beforeAdvice" class="com.itheima.AJ.BeforeAdvice"/> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <bean id="peopleService" class="com.itheima.service.PeopleServiceImpl"/> <aop:config> <!--target --> <aop:pointcut id="target" expression="target(com.itheima.service.UserService)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="problem" pointcut-ref="target"/> </aop:aspect> </aop:config>
// public class Tets09 { public static void main(String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); UserService userService = cp.getBean("userService", UserService.class); PeopleService peopleService = cp.getBean("peopleService", PeopleService.class); peopleService.say(20); System.out.println("==============="); userService.info(20); userService.info(new Car()); userService.info("first","second"); } } /* 20 =============== 20 car!!! first==second */

target

@target

// @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Targets { } // public interface PeopleService { public void say(int num); } public interface UserService { public void info(String s1, String s2); public void info(int num); public void info(Car car); } // @Targets public class PeopleServiceImpl implements PeopleService{ @Override public void say(int num) { System.out.println(num); } } public class UserServiceImpl implements UserService{ @Override public void info(String s1, String s2) { System.out.println(s1+"=="+s2); } @Override public void info(int num) { System.out.println(num); } @Override public void info(Car car) { System.out.println(car); } } // public class BeforeAdvice { public void problem(){ System.out.println(" "); } }
<bean id="beforeAdvice" class="com.itheima.AJ.BeforeAdvice"/> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <bean id="peopleService" class="com.itheima.service.PeopleServiceImpl"/> <aop:config> <!--@taget --> <aop:pointcut id="targets" expression="@target(com.itheima.annotated.Targets)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="problem" pointcut-ref="targets"/> </aop:aspect> </aop:config>
// public class Tets10 { public static void main(String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); UserService userService = cp.getBean("userService", UserService.class); PeopleService peopleService = cp.getBean("peopleService", PeopleService.class); peopleService.say(20); System.out.println("==============="); userService.info(20); userService.info(new Car()); userService.info("first","second"); } } /* 20 =============== 20 car!!! first==second */

within()

target within target

// public interface PeopleService { public void say(int num); } public interface UserService { public void info(String s1, String s2); public void info(int num); public void info(Car car); } // public class PeopleServiceImpl implements PeopleService{ @Override public void say(int num) { System.out.println(num); } } public class UserServiceImpl implements UserService{ @Override public void info(String s1, String s2) { System.out.println(s1+"=="+s2); } @Override public void info(int num) { System.out.println(num); } @Override public void info(Car car) { System.out.println(car); } } // public class BeforeAdvice { public void problem(){ System.out.println(" "); } }
<bean id="beforeAdvice" class="com.itheima.AJ.BeforeAdvice"/> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <bean id="peopleService" class="com.itheima.service.PeopleServiceImpl"/> <aop:config> <!-- com.itheima.service com.itheima.service..*--> <aop:pointcut id="within" expression="within(com.itheima.service.*)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="problem" pointcut-ref="within"/> </aop:aspect> </aop:config>
// public class Test11 { public static void main(String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); UserService userService = cp.getBean("userService", UserService.class); PeopleService peopleService = cp.getBean("peopleService", PeopleService.class); peopleService.say(20); System.out.println("==============="); userService.info(20); userService.info(new Car()); userService.info("first","second"); } } /* 20 =============== 20 car!!! first==second */

@within()

// @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Within { } // public interface PeopleService { public void say(int num); } public interface UserService { public void info(String s1, String s2); public void info(int num); public void info(Car car); } // public class PeopleServiceImpl implements PeopleService{ @Override public void say(int num) { System.out.println(num); } } public class UserServiceImpl implements UserService{ @Override public void info(String s1, String s2) { System.out.println(s1+"=="+s2); } @Override public void info(int num) { System.out.println(num); } @Override public void info(Car car) { System.out.println(car); } } // public class BeforeAdvice { public void problem(){ System.out.println(" "); } }
<bean id="beforeAdvice" class="com.itheima.AJ.BeforeAdvice"/> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <bean id="peopleService" class="com.itheima.service.PeopleServiceImpl"/> <aop:config> <aop:pointcut id="within" expression="@within(com.itheima.annotated.Within)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="problem" pointcut-ref="within"/> </aop:aspect> </aop:config>
// public class Test12{ public static void main(String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); UserService userService = cp.getBean("userService", UserService.class); PeopleService peopleService = cp.getBean("peopleService", PeopleService.class); peopleService.say(20); System.out.println("==============="); userService.info(20); userService.info(new Car()); userService.info("first","second"); } } /* 20 =============== 20 car!!! first==second */

@target @within

@target @within

// @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Targets { } @Target(ElementType.TYPE) @Retention(RetentionPolicy.RUNTIME) public @interface Within { } // @Within @Targets public class Man { public void speak(){ System.out.println("Manspeak!!!"); } public void say(){ System.out.println("say!!!"); } } public class NoMan extends Man{ @Override public void say() { System.out.println("NoManSay"); } } public class Human extends Man{ @Override public void speak() { System.out.println("Humanspeak"); } } // public class BeforeAdvice { public void target(){ System.out.println(" @target"); } public void within(){ System.out.println(" @with"); } }
<bean id="huMan" class="com.itheima.service.Human"/> <bean id="man" class="com.itheima.service.Man"/> <bean id="noMan" class="com.itheima.service.NoMan"/> <aop:config> <aop:pointcut id="targets" expression="@target(com.itheima.annotated.Targets)"/> <aop:pointcut id="within" expression="@within(com.itheima.annotated.Within)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="target" pointcut-ref="targets"/> <aop:before method="within" pointcut-ref="within"/> </aop:aspect> </aop:config>
// public class Test13 { public static void main(String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); Man man = cp.getBean("man", Man.class); NoMan noMan = cp.getBean("noMan", NoMan.class); HuMan huMan = cp.getBean("huMan", Human.class); man.say(); man.speak(); System.out.println("==================="); huMan.say(); huMan.speak(); System.out.println("=============="); noMan.say(); noMan.speak(); } } /* @target @with say!!! @target @with Manspeak!!! =================== @with say!!! Humanspeak ============== NoManSay @with Manspeak!!! */

@targe @within

this()

// public interface PeopleService { public void say(int num); } public interface UserService { public void info(String s1, String s2); public void info(int num); public void info(Car car); } // public class PeopleServiceImpl implements PeopleService{ @Override public void say(int num) { System.out.println(num); } } public class UserServiceImpl implements UserService{ @Override public void info(String s1, String s2) { System.out.println(s1+"=="+s2); } @Override public void info(int num) { System.out.println(num); } @Override public void info(Car car) { System.out.println(car); } } // public class BeforeAdvice { public void problem(){ System.out.println(" "); } }
<bean id="beforeAdvice" class="com.itheima.AJ.BeforeAdvice"/> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <bean id="peopleService" class="com.itheima.service.PeopleServiceImpl"/> <aop:config> <!-- CGLIB--> <aop:pointcut id="this" expression="this(com.itheima.service.UserService)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="problem" pointcut-ref="this"/> </aop:aspect> </aop:config>

@annotation()

// @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Method { } // public interface UserService { public void info(String s1, String s2); public void info( int num); public void info(Car car); } // public class UserServiceImpl implements UserService{ @Override public void info(String s1, String s2) { System.out.println(s1+"=="+s2); } @Override @Method public void info(int num) { System.out.println(num); } @Override public void info(Car car) { System.out.println(car); } } // public class BeforeAdvice { public void problem(){ System.out.println(" "); } }
<bean id="beforeAdvice" class="com.itheima.AJ.BeforeAdvice"/> <bean id="userService" class="com.itheima.service.UserServiceImpl"/> <aop:config> <!-- --> <aop:pointcut id="annotation" expression="@annotation(com.itheima.annotated.Method)"/> <aop:aspect ref="beforeAdvice"> <aop:before method="problem" pointcut-ref="annotation"/> </aop:aspect> </aop:config>
// public class Test16 { public static void main(String[] args) { ClassPathXmlApplicationContext cp = new ClassPathXmlApplicationContext("/ApplicationContext.xml"); UserService userService = cp.getBean("userService", UserService.class); userService.info(20); userService.info(new Car()); userService.info("first","second"); } } /* 20 car!!! first==second */

execution()

execution(modifiers-pattern? ret-type-pattern declaring-type-pattern?name-pattern(param-pattern) throws-pattern?) execution

modifiers-pattern? *** **

ret-type-pattern *****

declaring-type-pattern

name-pattern *

param-pattern .. *****

throws-pattern

execution()

execution(* *(..))

execution(public * *(..))

public

execution(public int *(..))

public int

execution(* com.itheima.service.UserService.*(..))

com.itheima.service.UserService

execution(* com.itheima.service.*.*(..))

com.itheima.service

execution(* *.service.*.*(..))

com.service/cn.service

execution(* *..service.*.*(..))

service

execution(* *..service..*(..))

service

execution(* com.itheima.service.*.say(..))

com.itheima.service say

execution(* com.itheima.service.*.*(String))

com.itheima.service String

execution(* com.itheima.service.*.*(String,*))

com.itheima.service String

execution(* com.itheima.service.*.*(String,..))

com.itheima.service String .

execution within target within target execution

executio()

1 AOP OOP .

2 AOP AspectJ SpringAOP AspectJ SpringAOP

3 SpringAOP

4 SpringAOP

5 SpringAOP pointcut advice