AOP
AOP (concept)
(1) Face to face programming (aspect), AOP can isolate all parts of business logic, so that
The coupling degree between each part of business logic is reduced, the reusability of program is improved, and the efficiency of development is improved.
(2) Popular Description: add new functions to the trunk function without modifying the source code
(3) Use examples to illustrate AOP
Using dynamic agent in AOP bottom layer
1. What is AOP
(1) There are two kinds of dynamic agents
- The first case has an interface, using JDK dynamic agent
1. Create interfaces to implement class proxy objects and enhance class methods
- In the second case, CGLIB dynamic agent is used
1. Create proxy objects of subclasses and enhance methods of classes
AOP (JDK dynamic agent)
1. Use JDK dynamic Proxy to create Proxy objects using methods in Proxy class
(1) Call the newProxyInstance method
Method has three parameters:
First parameter, classloader
The second parameter is the class where the enhancement method is located. The interface implemented by this class supports multiple interfaces
The third parameter is to implement the InvocationHandler interface, create the proxy object, and write the enhanced part
2. Write JDK dynamic agent code
(1) Create interface, define method
package com.company.jdkaop; public interface UserDao { public void insert(); public Boolean update(); }
(2) Create interface implementation class and implementation method
package com.company.jdkaop; public class UserDaoImpl implements UserDao { @Override public void insert() { System.out.println("Executed insert method"); } @Override public Boolean update() { return null; } }
(3) Using Proxy class to create interface Proxy object
package com.company.jdkaop; 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 interface implementation class proxy object Class[] interfaces = {UserDao.class}; UserDaoImpl userDao = new UserDaoImpl(); UserDao o = (UserDao) Proxy.newProxyInstance(JdkProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao)); o.insert(); } } //Create proxy object code class UserDaoProxy implements InvocationHandler { //1. Pass the created proxy object to //Parametric construction transfer private Object obj; public UserDaoProxy(Object obj){ this.obj = obj; } //Enhanced logic @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println("Before method"); // Method is executed Object res = method.invoke(obj, args); System.out.println("After method"); //Return results return res; } }
AOP (terminology)
1. Connection point
Which methods in the class can be enhanced and become join points
2. Entry point
The approach that is actually enhanced is called the pointcut
3. Notification (enhanced)
Actually enhanced logical part
4. Notification type
- Pre notification (before method)
- Post notification (after method)
- Orbit notification (before and after method)
- Exception notification (method exception)
- Final notification (after method execution, before return)
5. Section
The process of applying notifications to pointcuts
AOP operation
1. Spring framework is generally based on AspectJ to implement AOP operations
(1) AspectJ is not a part of Spring. It is an independent AOP framework. AspectJ is generally used together with spinning framework for AOP operation
2. AOP operation based on AspectJ
(1) Implementation of configuration file based on xml
(2) Implementation based on annotation
3. Introduce AOP related dependency into project engineering
4. Pointcut expression
(1) Pointcut expression function: know which method in which class to enhance
(2) Grammatical structure:
execution([permission modifier] [return type] [class full path] Method name )
Example 1: Yes com.company.dao add in the. Bookdao class to enhance
execution(* com.company.dao.BookDao.add(...))
Example 2: Yes com.company.dao All methods in the. Bookdao class are enhanced
execution(* com.company.dao.BookDao.* (...))
Example 3: Yes com.company.dao All classes and methods in the package are enhanced
execution(* com.company.dao.. (...))
AOP operation (AspectJ annotation)
1. Create a class and define methods in the class
package com.company.Aspectj; public class User { public void add(){ System.out.println("add to"); } }
2. Create enhancement class (write enhancement logic)
(1) In the enhanced class, create methods to represent different notification types
package com.company.Aspectj; public class UserProxy { public void before(){ System.out.println("Before method"); } }
3. Configure for notifications
<!-- Enable annotation scanning--> <context:component-scan base-package="com.company"></context:component-scan>
(2) Using annotations to create User and UserProxy objects
@Component
(3) Add annotation @ Aspect to the enhanced class
@Component @Aspect //Build proxy object public class UserProxy { public void before(){ System.out.println("Before method"); } }
(4) Turn on the build agent object in the spring configuration file
<! -- turn on Aspect generation proxy object -- > <aop:aspectj-autoproxy></aop:aspectj-autoproxy
4. Configure different types of notifications
(1) In the enhanced class, notice type annotation is added as the notice method, and pointcut expression configuration is used
package com.company.Aspectj; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component @Aspect //Build proxy object public class UserProxy { //Before advice @Before(value = "execution(* com.company.Aspectj.User.add(..))") public void before(){ System.out.println("Before advice "); } //Post notice @AfterReturning(value = "execution(* com.company.Aspectj.User.add(..))") public void afterReturning(){ System.out.println("Post notice"); } ////Final notice @After(value = "execution(* com.company.Aspectj.User.add(..))") public void after(){ System.out.println("Final notice"); } //Exception notification @AfterThrowing(value = "execution(* com.company.Aspectj.User.add(..))") public void AfterThrowing(){ System.out.println("Exception notification"); } //Around Advice @Around(value = "execution(* com.company.Aspectj.User.add(..))") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("Before wrapping"); //Enhanced method execution proceedingJoinPoint.proceed(); System.out.println("After orbit"); } }
5. Same pointcut extraction
package com.company.Aspectj; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Component @Aspect //Build proxy object public class UserProxy { //Extraction entry point @Pointcut(value = "execution(* com.company.Aspectj.User.add(..))") public void point(){ } //Before advice @Before(value = "point()") public void before(){ System.out.println("Before advice "); } //Post notice @AfterReturning(value = "point()") public void afterReturning(){ System.out.println("Post notice"); } ////Final notice @After(value = "point()") public void after(){ System.out.println("Final notice"); } //Exception notification @AfterThrowing(value = "point()") public void AfterThrowing(){ System.out.println("Exception notification"); } //Around Advice @Around(value = "point()") public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { System.out.println("Before wrapping"); //Enhanced method execution proceedingJoinPoint.proceed(); System.out.println("After orbit"); } }
6. There are multiple enhancement classes and the same method for enhancement. Set the priority of enhancement classes
@Order(1)
7. Full use of annotation development
(1) To create a configuration class, you do not need to create an xml configuration file
7,Full use of annotation development (1) to create configuration classes, no need to create xml configuration file @Configuration @ComponentScan(basePackages = {"com.atguigu"}) @EnableAspectJAutoProxy(proxyTargetClass = true) <!-- open Aspect Build proxy object--> public class ConfigAop { }
AOP operation (AspectJ configuration file)
1. Create two classes, enhanced class and enhanced class, and create methods
2. Create two class objects in the spring configuration file
3. Configuring pointcuts in the spring configuration file
<!-- to configure aop enhance--> <aop:config> <!-- Configuration entry point--> <aop:pointcut id="userpointcut" expression="execution(* com.company.Aspectj.User.add(..))"/> <!-- Configure facets--> <aop:aspect ref="userProxy"> <!-- Enhance in specific ways--> <aop:after method="beforeByXml" pointcut-ref="userpointcut"></aop:after> </aop:aspect> </aop:config>
Using aop to dynamically set data source in project
1. Data source switching interceptor
<bean id="dataSourceInterceptor" class="com.liang.commons.db.DataSourceInterceptor"></bean>
2. AOP configuration
<aop:config expose-proxy="true" proxy-target-class="true"> <aop:aspect ref="dataSourceInterceptor"> <!-- Data source 1 tangent point (basic module) --> <aop:pointcut expression="(execution(* com.sage.system.controller.supervision..*.*(..)))" id="pointcut1"/> <aop:around method="dataSource1Interceptor" pointcut-ref="pointcut1"/> </aop:aspect> <aop:aspect ref="dataSourceInterceptor"> <!-- Data source 2 tangent point (basic module) --> <aop:pointcut expression="(execution(* com.sage.system.controller.zlreport..*.*(..)))" id="pointcut2"/> <aop:around method="dataSource2Interceptor" pointcut-ref="pointcut2"/> </aop:aspect> </aop:config>
3,Data source switching interceptor code public class DataSourceInterceptor { protected Logger logger = LogManager.getLogger(getClass()); public Object dataSource1Interceptor(ProceedingJoinPoint point) throws Throwable { //Get database content from ShiroUser (username + URL + password + driverclass) List<Programsys> collect = UserInfo.getShiroUserInfo().getProgramsys().stream().filter(item -> { return item.getServername().equals(DbConstant.DATABASES_SUPERVISION_NAME); }).collect(Collectors.toList()); try { //Create DataSourceBean DataSourceBean dataSourceBean = new DataSourceBean(new DataSourceBean.DataSourceBeanBuilder(collect.get(0).getBeanname(), collect.get(0).getServerip(), collect.get(0).getPort(),collect.get(0).getServername(), collect.get(0).getUsername(), collect.get(0).getPassword())); //set up DataSourceContext.setDataSource(dataSourceBean); logger.info("*****************Switch to 1 system data source"); //Execute enhanced method Object result = point.proceed(); //Set data source as default DataSourceContext.toDefault(); //Return results return result; } finally { //Set data source as default DataSourceContext.toDefault(); } } public Object dataSource2Interceptor(ProceedingJoinPoint point) throws Throwable { List<Programsys> collect = UserInfo.getShiroUserInfo().getProgramsys().stream().filter(item -> { return item.getServername().equals(DbConstant.DATABASES_ZLREPORT_NAME); }).collect(Collectors.toList()); try { DataSourceBean dataSourceBean = new DataSourceBean(new DataSourceBean.DataSourceBeanBuilder(collect.get(0).getBeanname(), collect.get(0).getServerip(), collect.get(0).getPort(),collect.get(0).getServername(), collect.get(0).getUsername(), collect.get(0).getPassword())); DataSourceContext.setDataSource(dataSourceBean); logger.info("*****************Switch to 2 system data source"); Object result = point.proceed(); DataSourceContext.toDefault(); return result; } finally { DataSourceContext.toDefault(); } } }
I don't think it's right to switch.................................................................