Spring basics (5)

AOP (Aspect Oriented Programming)

The underlying implementation of springAOP uses proxy mode!

The role of static proxy mode:

  • Abstract role: generally use interface or implementation class to solve
  • Real role: the role being proxied
  • Agent role: the real role of the agent, the agent role will add some subsidiary operations
  • Client: The person who visits the proxy object

Benefits of the agent model:

  1. Make the real role more pure, focus on one's own business, and differently consider some public business
  2. Hand over the public business to the agent! Realize the division of work!
  3. For the extended business, use the business in the extended agent class! Convenient for several kinds of management!

Disadvantages of static proxy:

  • A real object will produce a proxy object; increase the amount of code!

Dynamic proxy can solve the problem of increasing code volume,Because the dynamic proxy uses a reflection mechanism! The static proxy is proxied at compile time, and the dynamic proxy is proxied at runtime.

  • The proxy class of the dynamic proxy is dynamically generated, not directly written by us.

Insert picture description here

AOP in Spring makes extensive use of proxy mode for horizontal development!

Elements needed to implement AOP

The role of AOP: to provide declarative transactions, allowing users to customize aspects!

  1. Crosscutting concerns: functions to be crosscutted into, such as logging, security, etc.
  2. Aspect : The cross-cutting concerns are modularized into classes. (Because crosscutting concerns may have a lot of logic, put them in a class for easy management. Among them are business methods that need to be extended)
  3. Notice : The method of crosscutting the class that is modularized into the focus. (One way is to expand the business)
  4. Target: real object.
  5. Proxy: proxy object.
  6. Entry point : the definition of the place where the "aspect notice" is implemented. (It’s the place to insert and expand the business)
  7. Link point: The place where the entry point is executed. (That is the place where the proxy object method is run)

In SpringAOP, the crosscutting logic is defined through Advice, and Spring supports 5 Advices: ( that is to say, using Advice provided by spring can add new functions without changing the original code, and add functions at the connection point )

Notification type Junction Implement the interface
Advance notice Before the method org.springframework.aop.MethodBeforeAdvice
Post notification After the method org.springframework.aop.AfterReturningAdvice
Surround notification Before and after the method org.springframework.aop.MethodInterceptor
Exception thrown notification When the method is abnormal org.springframework.aop.ThorowAdvice
Referral notice When adding new method attributes to the class org.springframework.aop.IntroductionInterceptor

Use spring to implement AOP

Use spring's API interface to implement aspect classes

Use spring's API interface to implement aspect classes, so as to achieve AOP!

You need to import the AOP package before using AOP!

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.9.4</version>
</dependency>
public interface UserService {
    
    
    void add();
    void delete();
    void modify();
    Object select();
}
public class UserServiceImpl implements UserService {
    
    
    public void add() {
    
    
        System.out.println("增加\n");
    }
    public void delete() {
    
    
        System.out.println("删除\n");
    }
    public void modify() {
    
    
        System.out.println("修改\n");
    }
    public Object select() {
    
    
        System.out.println("查询\n");
        return null;
    }
}
// 实现spring提供的接口创建切面
public class Log implements MethodBeforeAdvice {
    
    
    @Override
    public void before(Method method, Object[] args, Object target) throws Throwable {
    
    
        System.out.println("在"+target.getClass().getName()+"中的方法"+method.getName()+"之前执行了!");
    }
}
<?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="userService" class="pers.qiu.service.UserServiceImpl"></bean>
    <bean id="log" class="pers.qiu.log.Log"></bean>

    <aop:config>
        <!--需要一个切入点  id 表达式=execution(返回值 类名.方法名(参数) )  表示执行的位置-->
        <!--.*代表所有方法,..代表接收一切参数-->
        <aop:pointcut id="pointcut" expression="execution(* pers.qiu.service.UserServiceImpl.*(..))"/>

        <!--执行环绕增加,就是将log这个切面增加到切入点方法中.它就自动的环绕在业务逻辑之前或之后.-->
        <aop:advisor advice-ref="log" pointcut-ref="pointcut"/>

    </aop:config>
    
<!-- 也可以使用多个切入点
	<aop:config>
		<aop:pointcut id="addpointcut" expression="execution(* pers.qiu.service.UserServiceImpl.add(..))"/>

		<aop:pointcut id="deletepointcut" expression="execution(* pers.qiu.service.UserServiceImpl.add(..))"/>

		<aop:advisor advice-ref="log" pointcut-ref="addpointcut"/>
		<aop:advisor advice-ref="log" pointcut-ref="deletepointcut"/>
	</aop:config>
 -->
</beans>

After the aop configuration is used, the proxy object of the user Service is obtained when getBean. The acquisition is completed when the proxy object is generated into the spring container.

public class MyTest {
    
    
    @Test
    public void text01(){
    
    
        ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
        UserService userService = (UserService) context.getBean("userService");
        userService.add();
    }
}

Insert picture description here

With AOP, you can see: only its business logic is written in the real class; only the extended logic is written in the aspect class; the connection configuration through xml can generate a proxy class that connects the two functions!

Use custom classes to implement aspect classes

Use a custom class as the aspect class, instead of using the four types provided in the spring package as the aspect class!

// 自定义切面
public class MyCutFact {
    
    
    public void before(){
    
    
        System.out.println("在切点前面执行!");
    }

    public void after(){
    
    
        System.out.println("在切点后面执行!");
    }
}
<?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="userService" class="pers.qiu.service.UserServiceImpl"></bean>
    <bean id="log" class="pers.qiu.log.Log"></bean>

    <bean id="cutFact" class="pers.qiu.log.MyCutFact"></bean>
    <aop:config>
        <!--切面-->
        <aop:aspect ref="cutFact">
            <!--切入点-->
            <aop:pointcut id="pointcut" expression="execution(* pers.qiu.service.UserServiceImpl.*(..))"/>
			<!--通知-->
            <aop:before method="before" pointcut-ref="pointcut"/>
        </aop:aspect>
    </aop:config>
</beans>

As you can see: The use of AOP requires:

  • Noodles
  • Entry point
  • Notice on the use of noodles

The difference between a custom aspect and the implementation of an aspect class using the spring interface:

  1. Use the spring interface to implement the aspect class, which has specialized in the function of the aspect class. That is, the implementation of the specified interface can only be done before or after the entry point or around. The custom aspect class does not have a specified override method, so the method can only be named before and after for notification settings.
    • Therefore, you need to declare the aspect display in the xml (the way to implement the spring interface is already encapsulated, so there is no need to do it)
    • The notification used also needs to be declared explicitly (the way to implement the spring interface is spring encapsulated, and spring is specialized, so there is no need to do it)
    • All need to declare an entry point!

Insert picture description here

Use annotations to implement AOP

@Aspect
@Component
public class AnnotationCutFect {
    
    
    // 直接在通知上定义切入点,创建AnnotationCutFect对象时直接将切入点内置到里面。getBean时直接得到组合后的代理对象。
    @Before("execution(* pers.qiu.service.UserServiceImpl.*(..))")
    public void before(){
    
    
        System.out.println("方法执行前!");
    }
}
@Configuration
@ComponentScan({
    
    "pers.qiu.log", "pers.qiu.service"})
@Component
// 开启自动代理(必开,否则不会代理它)
@EnableAspectJAutoProxy
public class MyApplicationContext {
    
    
    @Bean
    public UserServiceImpl userService(){
    
    
        return new UserServiceImpl();
    }

    @Bean
    public AnnotationCutFect annotationCutFect(){
    
    
        return new AnnotationCutFect();
    }
}
public class MyTest {
    
    
    @Test
    public void test02(){
    
    
        ApplicationContext context = new AnnotationConfigApplicationContext(MyApplicationContext.class);
        UserService userService = (UserService) context.getBean("userService");
        AnnotationCutFect annotationCutFect = (AnnotationCutFect) context.getBean("annotationCutFect");
        userService.add();
    }
}

If you do not enable the automatic proxy in MyApplicationContext, you need to use xml to enable configuration and use XMLApplicationContext to obtain the spring container. (Too troublesome, or all annotations, or all configuration files, mix and match eight Taihang!) :

<?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">

    <aop:aspectj-autoproxy/>
</beans>

Guess you like

Origin blog.csdn.net/qq_43477218/article/details/113836563