1. Aspect programming
Concept: In the original vertical execution process of the program, adding notifications for a certain method or methods to form a cross-section is called section-oriented programming.
Commonly used section concepts:
- Original function: pointcut, pointcut
- Before advice: A function executed before the point of cut. Before advice
- After advice: a function executed after the point of cut, after advice
- If an exception occurs during the execution of the pointcut, an exception notification will be triggered.
- All the functions are collectively called the aspect.
- Weaving: The process of embedding the aspect into the original function is called weaving
Two, AOP
1. AOP: Aspect Oriented Programming is also known as aspect-oriented programming.
2. Function: The normal program execution flow is a vertical execution flow, while AOP adds a cross-section to the original vertical execution flow without modifying the original program code.
3. Advantages: high scalability, the original function is equivalent to releasing part of the logic. Make the function responsibilities more clear.
4. Spring provides 2 AOP implementation methods
4.1, Schema-based
- Every notification needs to implement an interface or class
- When configuring the spring configuration file, configure
4.2, AspectJ in aop:config - Every notification does not need to implement an interface or class
- The spring configuration file is configured in the subtag aop:aspect of aop:config
Three, Schema-based implementation steps
1. Import Jar
(other jar packages of Spring need to be imported)
2. New notification class
2.1, new pre-notification class
- arg0: Method object of pointcut method object
- arg1: tangent method parameter
- arg2: Which object is the tangent point in
public class MyBeforeAdvice implements MethodBeforeAdvice {
@Override
public void before(Method arg0, Object[] arg1, Objectarg2) throws Throwable {
System.out.println("执行前置通知");
}
}
2.2. New post notification class
- arg0: return value of tangent method
- arg1: Point-cut method object
- arg2: tangent method parameter
- arg3: The object of the class where the pointcut method is located
public class MyAfterAdvice implements AfterReturningAdvice {
@Override
public void afterReturning(Object arg0, Method arg1, Object[] arg2, Object arg3) throws Throwable {
System.out.println("执行后置通知");
}
}
3. Configure the spring configuration file
- Introduce the aop namespace
- Configure the notification class
- Configuration aspect
- *Wildcard, match any method name, any class name, any first-level package name
- If you want to match any method parameters (...)
<?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: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-aop.xsd">
<!-- 配置通知类对象,在切面中引入 -->
<bean id="mybefore" class="com.jax.advice.MyBeforeAdvice"></bean>
<bean id="myafter" class="com.jax.advice.MyAfterAdvice"></bean>
<!-- 配置切面 -->
<aop:config>
<!-- 配置切点 -->
<aop:pointcut expression="execution(*com.jax.test.Demo.demo2())" id="mypoint"/>
<!-- 通知 -->
<aop:advisor advice-ref="mybefore" pointcut-ref="mypoint"/>
<aop:advisor advice-ref="myafter" pointcut-ref="mypoint"/>
</aop:config>
<!-- 配置 Demo 类,测试使用 -->
<bean id="demo" class="com.jax.test.Demo"></bean>
</beans>
4. Write test code
public class Test {
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
Demo demo = ac.getBean("demo",Demo.class);
demo.demo1();
demo.demo2();
demo.demo3();
}
}
5. Execution results
Fourth, the steps to configure exception notification (AspectJ method)
- Only when the cut point reports an exception can the exception notification be triggered
- There is an AspectJ method in spring that provides an exception notification method.
If you want to implement it through schema-base, you need to write your own method according to specific requirements. - Implementation steps:
3.1. Create a new class and write a method with any name in the class
public class MyThrowAdvice{
public void myexception(Exception e1){
System.out.println("执行异常通知"+e1.getMessage());
}
}
3.2 Configure in the spring configuration file
- The ref attribute of aop:aspect indicates: which class the method is in.
- What does <aop: xxxx/> mean?
- method: which method to call when this notification is triggered
- throwing: The name of the exception object must be the same as the method parameter name in the notification (the exception object may not be declared in the notification)
<bean id="mythrow"class="com.jax.advice.MyThrowAdvice"></bean>
<aop:config>
<aop:aspect ref="mythrow">
<aop:pointcut expression="execution(*com.jax.test.Demo.demo1())" id="mypoint"/>
<aop:after-throwing method="myexception" pointcut-ref="mypoint" throwing="e1"/></aop:aspect>
</aop:config>
<bean id="demo" class="com.jax.test.Demo"></bean>
5. Exception notification (Schema-based method)
1. Create a new class to implement the throwsAdvice interface
- You must write the method yourself, and it must be called afterThrowing
- There are two parameter modes, which must be 1 or 4
- The exception type should be consistent with the exception type reported by the cutpoint
public class MyThrow implements ThrowsAdvice{
// public void afterThrowing(Method m, Object[] args,
Object target, Exception ex) {
// System.out.println("执行异常通知");
// }
public void afterThrowing(Exception ex) throws
Throwable {
System.out.println("执行异常通过-schema-base 方式");
}
}
2. Configure in ApplicationContext.xml
<bean id="mythrow" class="com.jax.advice.MyThrow"></bean>
<aop:config>
<aop:pointcut expression="execution(*com.jax.test.Demo.demo1())" id="mypoint"/>
<aop:advisor advice-ref="mythrow" pointcut-ref="mypoint" />
</aop:config>
<bean id="demo" class="com.jax.test.Demo"></bean>
Sixth, surround notification (Schema-based method)
1. Write both the pre-notification and the post-notification into one notification to form a surround notification
2. Implementation steps
Create a new class to implement MethodInterceptor
public class MyArround implements MethodInterceptor {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("环绕-前置");
Object result = arg0.proceed();//放行,调用切点方式
System.out.println("环绕-后置");
return result;
}
}
Configure application.xml
<bean id="myarround" class="com.jax.advice.MyArround"></bean>
<aop:config>
<aop:pointcut expression="execution( *com.jax.test.Demo.demo1())" id="mypoint"/>
<aop:advisor advice-ref="myarround" pointcut-ref="mypoint" />
</aop:config>
<bean id="demo" class="com.jax.test.Demo"></bean>
Seven, use AspectJ
1. Create a new class, do not need to implement
1.1, the method name in the class is arbitrary
public class MyAdvice {
public void mybefore(String name1,int age1){
System.out.println("前置"+name1 );
}
public void mybefore1(String name1){
System.out.println("前置:"+name1);
}
public void myaftering(){
System.out.println("后置 2");
}
public void myafter(){
System.out.println("后置 1");
}
public void mythrow(){
System.out.println("异常");
}
public Object myarround(ProceedingJoinPoint p) throws Throwable{
System.out.println("执行环绕");
System.out.println("环绕-前置");
Object result = p.proceed();
System.out.println("环绕后置");
return result;
}
}
1.2, configure spring configuration file
- aop:after/ post notification, whether there is an exception, it will be executed
- aop:after-returing/ post notification, only executed when the cut point is executed correctly
- aop:after/ and aop:after-returing/ and aop:after-throwing/ execution order is related to configuration order
- execution() brackets cannot be expanded with args
- Use and in the middle and cannot use &&. Spring will parse and into &&
- args (name) name custom. The order corresponds to demo1 (parameters, parameters)
- aop:before/ arg-names=” name” The name comes from
args() in expression=”” , the name must be the same, args() has several parameters, arg-names must have several parameters, arg-names=” "The
name inside must correspond to the parameter name of the notification method
<aop:config>
<aop:aspect ref="myadvice">
<aop:pointcut expression="execution(*com.jax.test.Demo.demo1(String,int)) and args(name1,age1)" id="mypoint"/>
<aop:pointcut expression="execution(*com.jax.test.Demo.demo1(String)) and args(name1)" id="mypoint1"/>
<aop:before method="mybefore" pointcut-ref="mypoint" arg-names="name1,age1"/>
<aop:before method="mybefore1" pointcut-ref="mypoint1" arg-names="name1"/>
<!-- <aop:after method="myafter"
pointcut-ref="mypoint"/>
<aop:after-returning method="myaftering"
pointcut-ref="mypoint"/>
<aop:after-throwing method="mythrow"
pointcut-ref="mypoint"/>
<aop:around method="myarround"
pointcut-ref="mypoint"/>-->
</aop:aspect>
</aop:config>
8. Use annotations (based on Aspect)
1. Spring will not automatically look for annotations. You must tell spring which packages under the class may have annotations
1.1 Introduce xmlns:context
<context:component-scan base-package="com.jax.advice"></context:component-scan>
2、@Component
- Equivalent to
- If there are no parameters, change the first letter of the class name to lowercase, which is equivalent to
- @Component("Custom Name")
3. Implementation steps:
3.1. Set the annotations in which packages in the spring configuration file
<context:component-scanbase-package="com.jax.advice,com.jax.test"></context:component-scan>
3.2. Add @Componet to the Demo class and add
@Pointcut(“”) to the method to define the cut point
@Component
public class Demo {
@Pointcut("execution(*com.jax.test.Demo.demo1())")
public void demo1() throws Exception{
// int i = 5/0;
System.out.println("demo1");
}
}
3.3 Configure in the notification class
- @Component class is managed by spring
- @Aspect is equivalent to aop:aspect/ indicates that the notification method is in the current class
@Component
@Aspect
public class MyAdvice {
@Before("com.jax.test.Demo.demo1()")
public void mybefore(){
System.out.println("前置");
}
@After("com.jax.test.Demo.demo1()")
public void myafter(){
System.out.println("后置通知");
}
@AfterThrowing("com.jax.test.Demo.demo1()")
public void mythrow(){
System.out.println("异常通知");
}
@Around("com.jax.test.Demo.demo1()")
public Object myarround(ProceedingJoinPoint p) throws Throwable{
System.out.println("环绕-前置");
Object result = p.proceed();
System.out.println("环绕-后置");
return result;
}
}