Let’s learn the use of SF framework series 7.2-spring-AOP-AOP

Spring AOP has two usage modes: @AspectJ configuration mode and xml configuration mode.

@AspectJ configuration mode

Configuration

1. Add dependency packages:

    <!--spring aop依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aop</artifactId>
        <version>6.0.2</version>
    </dependency>
    <!-- spring aspects依赖-->
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-aspects</artifactId>
        <version>6.0.2</version>
    </dependency>

2. Add configuration file:

<beans xmlns="http://www.springframework.org/schema/beans"
	...
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
		...
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd">

	<!-- 开启aop注解方式,默认为false -->
	<aop:aspectj-autoproxy></aop:aspectj-autoproxy>

Example

Aspect definition

@Component
// @Aspect切面注解,表示该类是切面类
@Aspect
public class AspectLog {
    
     
	// before advice,括号中是切入点配置,省略了“pointcut”(execution是pointcut语法的固定开头) 注1
    @Before("execution(* com.learnsf.demo.spring.aop.BzServiceImpl.*(..))")
	public void before() {
    
    
		System.out.println("方法执行advice-before");
	}

	// After advice,括号中是切入点配置,省略了“pointcut”
    @After("execution(* com.learnsf.demo.spring.aop.BzServiceImpl.*(..))")
	public void after() {
    
    
		System.out.println("方法执行advice-after");
	}

	// AfterReturning advice,括号中是切入点配置,省略了“pointcut”
    @AfterReturning("execution(* com.learnsf.demo.spring.aop.BzServiceImpl.*(..))")
	public void afterReturning() {
    
    
		System.out.println("方法执行advice-afterReturning");
	}

	// Around advice,括号中是切入点配置,省略了“pointcut” 注2
    /**在使用环绕注解时,可以传入ProceedingJoinPoint的对象来获取业务方法的返回值*/
    @Around("execution(* com.learnsf.demo.spring.aop.BzServiceImpl.around*(..))")
    public void around(ProceedingJoinPoint pj) throws Throwable {
    
    
        // 执行方法前处理
        System.out.println("方法执行advice-@Around前");
        // 执行方法本身
        BzService bzService =(BzService) pj.proceed();
        // 执行方法后处理
        System.out.println("方法执行advice-@Around后,返回值-"+bzService);
    }

	// AfterThrowing advice,其中pointcut是切入点,throwing是传入切面异常命名为"ex" 注3
    @AfterThrowing(pointcut="execution(* com.learnsf.demo.spring.aop.BzServiceImpl.throw*(..))",throwing="ex")
	public void afterThrowing(JoinPoint jp, Throwable ex) {
    
    
		System.out.println("method " + jp.getTarget().getClass().getName() + "." + jp.getSignature().getName() + " throw exception: "+ex.getMessage());
	}
}

Note 1: See subsequent chapters for how to define entry points.
Note 2: ProceedingJoinPoint inherits from JoinPoint. Where "pj.proceed()" is the execution connection point method itself. This is the characteristic of around advice: the aspect program needs to execute the connection point method itself; other advice is executed by the framework.
Note 3: The JoinPoint interface provides information that aspects can access join point methods. Useful methods are as follows:
getArgs(): Returns method parameters.
getThis(): Returns the proxy object.
getTarget(): Returns the target object.
getSignature(): Returns the method description of the current Advice.
toString(): Print the description of the current Advice method.

Example class

public interface BzService {
    
    
    public void add();

    public void delete();

    public void update();

    public void query();
    
    public BzService aroundTest();
    
	public BzServiceImpl throwTest() throws Exception;
}

@Component
public class BzServiceImpl implements BzService{
    
    
	@Override
    public void add() {
    
    
        System.out.println("业务增加!");
    }

	@Override
    public void delete() {
    
    
        System.out.println("业务删除!");
    }

	@Override
    public void update() {
    
    
        System.out.println("业务修改!");
    }

	@Override
    public void query() {
    
    
        System.out.println("业务查询!");
    }

	@Override
	public BzServiceImpl aroundTest() {
    
    
        System.out.println("该方法被@Around Annotation!");
        return null;
    }
	@Override
	public BzServiceImpl throwTest() throws Exception{
    
    
        System.out.println("该方法被throw!");
		throw new IllegalArgumentException("测试异常抛出");
	}
}

Run class

@Component
public class DemoAop {
    
    
	@Autowired
	BzService bzService;
	
	public void demo() {
    
    
		bzService.add();
		bzService.delete();
		bzService.update();
		bzService.aroundTest();
		try {
    
    
			bzService.throwTest();
		} catch (Exception e) {
    
    
			// TODO Auto-generated catch block
			//e.printStackTrace();
		}
	}
}

// 主程序
public class Main {
    
    
    public static void main(String[] args) {
    
    
        //创建springframework容器,初始化文件为app.xml
    	ApplicationContext context = new ClassPathXmlApplicationContext("app.xml");
        DemoAop demoAop = (RunDemo)context.getBean("DemoAop");
        demoAop .demo();
    }
}

XML configuration schema

Configuration

Configuration file added:

<beans xmlns="http://www.springframework.org/schema/beans"
	...
	xmlns:aop="http://www.springframework.org/schema/aop"
	xsi:schemaLocation="
		...
		http://www.springframework.org/schema/aop
		http://www.springframework.org/schema/aop/spring-aop.xsd">

	...
	<!--AOP实现方式之一:xml配置模式-->
    <aop:config>
        <!-- 定义切入点:id切入点的id,expression:确定要切入的地方和其详细信息  -->
        <aop:pointcut id="pointcut" expression="execution(* com.learnsf.demo.spring.aop.BzServiceImplForXml.*(..))"/>
        <!-- 同切面关联:advice-ref定义切面 使用的切点pointcut-ref -->
        <aop:advisor advice-ref="springAopLog" pointcut-ref="pointcut"/>
    </aop:config>
    ...

Example

Section type

// 通过继承实现对方法的参数、返回值等的访问
@Component
public class SpringAopLog implements MethodBeforeAdvice,AfterReturningAdvice {
    
    
	// implement MethodBeforeAdvice(BeforeAdvice只是个标记接口,MethodBeforeAdvice为实际接口)
	@Override
	public void before(Method method, Object[] args, @Nullable Object target) {
    
    
		System.out.println("[前置Advice]: "+target.getClass().getName()+"的"+method.getName()+"方法被执行了");
	}

	//implement AfterReturningAdvice(AfterAdvice只是个标记接口,AfterReturningAdvice为实际接口)
	// returnValue:切入目标方法的返回值,切入的后置方法可以对返回值进行操作
    @Override
    public void afterReturning(Object returnValue, Method method, Object[] args, Object target) throws Throwable {
    
    
        System.out.println("[后置Advice]: 执行了"+method.getName()+"方法,返回值为"+returnValue);
    }
}

Example class

@Component
public class BzServiceImplForXml {
    
    
    public BzPojo add(BzPojo bzPojo) {
    
    
        System.out.println("BzServiceImplForXml-业务增加!");
        return bzPojo;
    }

    public BzPojo update(BzPojo bzPojo) {
    
    
        System.out.println("BzServiceImplForXml-业务修改!");
        return bzPojo;
    }

    public boolean delete(Integer id) {
    
    
        System.out.println("BzServiceImplForXml-业务删除!");
        return true;
    }

    public void query(Integer id) {
    
    
        System.out.println("BzServiceImplForXml-业务查询!");
    }
}

run

@Component
public class DemoAop {
    
    
	@Autowired
	BzServiceImplForXml bzServiceImplForXml;
	
	public void demo() {
    
    
		BzPojo bzPojo=new BzPojo();
		bzServiceImplForXml.add(bzPojo);
		bzServiceImplForXml.update(bzPojo);
		bzServiceImplForXml.delete(1);
	}
}
// 主程序
public class Main {
    
    
    public static void main(String[] args) {
    
    
        //创建springframework容器,初始化文件为app.xml
    	ApplicationContext context = new ClassPathXmlApplicationContext("app.xml");
        DemoAop demoAop = (RunDemo)context.getBean("DemoAop");
        demoAop .demo();
    }
}

How to choose an application

How to choose @AspectJ configuration mode or XML configuration mode for an application, you need to understand the difference between the two:
1. Use Spring AOP to support @AspectJ configuration mode or XML configuration mode at the same time. If you only use complete AspectJ, you can only use @AspectJ mode.
2. The XML configuration mode is the mode that Spring has been using since its birth, and it is also the mode that many programmers are most familiar with. Therefore, when using AOP as a tool for configuring enterprise services, XML may be a good choice. The advantages of the xml configuration mode are: 1. You can see more clearly what aspects exist in the system from the configuration; 2. The configuration can be changed independently of the program. There are also two shortcomings: first, it does not completely encapsulate the implementation of the requirements it solves in a single location, violating the DRY principle (that is, any responsibility in the system should have a single, clear representation); second, it is different from @ Compared to AspectJ configuration mode, XML configuration mode is slightly limited in what it can express: only "singleton" aspect instantiation models are supported, and it is not possible to combine named pointcuts declared in XML.
In fact, the two can be mixed.

Pointcut expression syntax

Pointcut syntax (quoted from: https://blog.51cto.com/panyujie/5604327).
Insert image description here

Guess you like

Origin blog.csdn.net/davidwkx/article/details/131736546