Shang Silicon Valley AOP
AOP (concept)
1. What is AOP
(1) Aspect oriented programming (aspect oriented programming), AOP can isolate all parts of business logic, so as to reduce the coupling between all parts of business logic, improve the reusability of programs, and improve the efficiency of development.
(2) Popular Description: add new functions to the main functions without modifying the source code
(3) Use the login example to illustrate AOP
AOP (underlying principle)
-
The underlying AOP uses dynamic agents
(1) There are two cases of dynamic agents
In the first case, JDK dynamic proxy is used
- Create the proxy object of the interface implementation class and enhance the method of the class
In the second case, CGLIB dynamic proxy is used
- Create the proxy object of the subclass of the current class and enhance the method of the class
-
AOP(JDK dynamic agent)
The first step is to use JDK dynamic Proxy and create objects using Proxy class methods
(1) Call the newProxyInstance method
-
class Proxy() (check api)
static Object
newProxyInstance(ClassLoader loader, class <? > [] interfaces, invocationhandler h) returns an instance of the proxy class of the specified interface, which dispatches the method call to the specified call handler.
-
The first parameter is the class loader
-
The first parameter is the class where the enhancement method is located. The interface implemented by this class supports multiple interfaces
-
The first parameter is to implement this interface InvocationHandler, create proxy objects and write enhanced methods;
Step 2: write JDK dynamic code
(1) Create interfaces and define methods
package com.atguigu.spring5.Dao; public interface UserDao { public int add(int a, int b); public String update(String id); }
(2) Create interface implementation classes and implement methods
package com.atguigu.spring5.Dao.impl; import com.atguigu.spring5.Dao.UserDao; public class UserDaoImpl implements UserDao { @Override public int add(int a, int b) { return a+b; } @Override public String update(String id) { return id; } }
(3) Use the Proxy class to create a Proxy object for the interface
-
There are two ways to create proxy objects
//Anonymous Inner Class Class[] interfaces={UserDao.class}; Proxy.newProxyInstance(JDKProxy.class.getClassLoader() , interfaces, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } });
//Create object implementation interface package com.atguigu.spring5.test; import com.atguigu.spring5.Dao.UserDao; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; public class JDKProxy { public static void main(String[] args) { //Create a proxy object that implements the class Class[] interfaces={UserDao.class}; Proxy.newProxyInstance(JDKProxy.class.getClassLoader() , interfaces, new UserDaoProxy() ); } } //Create proxy object code class UserDaoProxy implements InvocationHandler{ //Write enhanced logic @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { return null; } }
-
code
package com.atguigu.spring5.test; import com.atguigu.spring5.Dao.UserDao; import com.atguigu.spring5.Dao.impl.UserDaoImpl; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.Arrays; public class JDKProxy { public static void main(String[] args) { //Create a proxy object that implements the class Class[] interfaces={UserDao.class}; UserDaoImpl userDao=new UserDaoImpl(); UserDao dao =(UserDao) Proxy.newProxyInstance(JDKProxy.class.getClassLoader() , interfaces, new UserDaoProxy(userDao)); int result=dao.add(1,2); System.out.println("result:"+result); } } //Create proxy object code class UserDaoProxy implements InvocationHandler{ //1. Who is the proxy object created and who is passed over private Object obj; //Parameter construction transfer public UserDaoProxy(Object obj){ this.obj=obj; } //Write enhanced logic @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //Method System.out.println("Method..."+method.getName()+":Parameters passed.."+ Arrays.toString(args)); //Enhanced method execution Object res=method.invoke(obj,args); //Do a process after the method System.out.println("Line after method..."+obj); return res; } }
-
-
AOP terminology
(1) Connection point
- Class can be enhanced. These methods are connection points
(2) Entry point
- The method that is actually really enhanced is called the entry point
(3) Notification (enhanced):
-
The logical part of the actual enhancement is called notification (enhancement)
-
There are many types of notifications
(1) Advance notice
(2) Post notification
(3) Surround notification
(4) Exception notification
(5) Final notice
(4) Section
- Apply notifications to pointcut processes
AOP operation (preparation)
-
spring frameworks generally implement AOP operations based on AspectJ
(1) What is AspectJ
*AspectJ is not a part of Spring. It is an independent AOP framework. Generally, AspectJ and Spring framework are used together for AOP operation
-
AOP operation based on AspectJ
(1) Implementation of configuration file based on xml
(2) Annotation based implementation (use)
-
Introduce AOP related dependencies into the project
-
Pointcut expression
(1) The function of pointcut expression: know which method in which class to enhance
(2) Syntax structure:
-
execution([permission modifier] [return type] [full path of class] [method name] ([parameter list]))
-
Example 1: com atguigu. dao. add in bookdao class is enhanced
execution(*com.atguigu.dao.BookDao.add(...) )
-
Example 2: com atguigu. dao. All methods in the bookdao class are enhanced
execution(com.atguigu.dao.BookDao.(...) )
-
Example 3: com atguigu. All classes and methods in Dao package are enhanced
execution(* com.atguigu.dao.* .* (...))
-
AOP operation (AspectJ annotation)
-
Create a class and define methods in the class
package com.atguigu.spring5.aopanno; //Enhanced class public class User { public void add(){ System.out.println("add........."); } }
-
Create enhanced classes (write your enhanced logic)
(1) In the enhanced class, create methods so that different methods represent different notification types
//Enhancement class public class UserProxy { //Before advice public void before(){ System.out.println("before......."); } }
-
Configure notifications
-
(1) In the spring configuration file, turn on annotation scanning
<?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:p="http://www.springframework.org/schema/p" 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/aop http://www.springframework.org/schema/aop/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-aop.xsd"> <!--Enable scanning of annotations--> <context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan> </beans>
(2) Creating User and UserProxy objects using annotations
package com.atguigu.spring5.aopanno; import org.springframework.stereotype.Component; //Enhanced class @Component public class User { public void add(){ System.out.println("add........."); } }
package com.atguigu.spring5.aopanno; import org.springframework.stereotype.Component; //Enhancement class @Component public class UserProxy { //Before advice public void before(){ System.out.println("before......."); } }
(3) Add the annotation @ Aspect on the enhanced class
package com.atguigu.spring5.aopanno; import org.aspectj.lang.annotation.Aspect; import org.springframework.stereotype.Component; //Enhancement class @Component @Aspect //Generate proxy object public class UserProxy { //Before advice public void before(){ System.out.println("before......."); } }
(4) Turn on the generation proxy object in the spring configuration file
<?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:p="http://www.springframework.org/schema/p" 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/aop http://www.springframework.org/schema/aop/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-aop.xsd"> <!--Enable scanning of annotations--> <context:component-scan base-package="com.atguigu.spring5.aopanno"></context:component-scan> <!--open Aspectj Proxy object--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
-
-
Configure different types of notifications
(1) In the enhanced class, add the notification type annotation on the notification method and use the pointcut expression
package com.atguigu.spring5.aopanno; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //Enhancement class @Component @Aspect //Generate proxy object public class UserProxy { //Before advice //The before annotation is represented as a pre notification @Before(value="execution(* com.atguigu.spring5.aopanno.User.add(..))") public void before(){ System.out.println("before......."); } @After(value="execution(* com.atguigu.spring5.aopanno.User.add(..))") public void after(){ System.out.println("after......."); } @AfterReturning(value="execution(* com.atguigu.spring5.aopanno.User.add(..))") public void afterReturning(){ System.out.println("afterReturning......."); } //Exception notification @AfterThrowing(value="execution(* com.atguigu.spring5.aopanno.User.add(..))") public void afterThrowing(){ System.out.println("AfterThrowing......."); } //Surround notification @Around(value="execution(* com.atguigu.spring5.aopanno.User.add(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ System.out.println("Before surround......."); //Enhanced method execution proceedingJoinPoint.proceed(); System.out.println("After surround......."); } }
-
Same pointcut extraction
package com.atguigu.spring5.aopanno; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; //Enhancement class @Component @Aspect //Generate proxy object public class UserProxy { //Extract from the same pointcut @Pointcut(value="execution(* com.atguigu.spring5.aopanno.User.add(..))" ) public void pointdemo(){ } //Before advice //The before annotation is represented as a pre notification @Before(value="pointdemo()") public void before(){ System.out.println("before......."); } @After(value="pointdemo()") public void after(){ System.out.println("after......."); } @AfterReturning(value="pointdemo()") public void afterReturning(){ System.out.println("afterReturning......."); } //Exception notification @AfterThrowing(value="pointdemo()") public void afterThrowing(){ System.out.println("AfterThrowing......."); } //Surround notification @Around(value="pointdemo()") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable{ System.out.println("Before surround......."); //Enhanced method execution proceedingJoinPoint.proceed(); System.out.println("After surround......."); } }
-
There are multiple enhancement classes to enhance the same method. You can set the priority of the enhancement class
(1) Add the annotation @ order (numeric type value) on the enhanced class. The smaller the numeric type, the higher the priority
@Component @Aspect @Order(1) public class PersonProxy {
-
Full development annotation
(1) To create a configuration class, you do not need to create an xml configuration file
@Configuration @ComponentScan(basePackages = {"com.atguigu"}) @EnableAspectJAutoProxy(proxyTargetClass = true) public class configAop {
AOP operation (AspectJ configuration file)
-
Create two classes, enhanced class and enhanced class, and create methods
-
Create two class objects in the spring configuration file
<!--Create objects of two classes--> <bean id="book" class="com.atguigu.spring5.aopxml.Book"></bean> <bean id="bookProxy" class="com.atguigu.spring5.aopxml.BookProxy"></bean>
-
Configuring pointcuts in the spring configuration file
<!--to configure aop enhance--> <aop:config> <!--breakthrough point--> <aop:pointcut id="p" expression="execution(* com.atguigu.spring5.aopxml.Book.buy(..))"/> <!--Configuration section--> <aop:aspect ref="bookProxy"> <!--Enhance the role in specific methods--> <aop:before method="before" pointcut-ref="p"/> </aop:aspect>