第6章Spring框架深入学习

AOP五种增强方式

注意:当目标方法出错时,后置增强不执行,最终增强会执行;有异常执行异常增强,不报错执行后置增强

前置增强(又称前置通知)的特点

前置增强使用@Befor注解标识,增强方法优先于目标方法执行。在核心功能之前执行的额外功能。

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;
 
@Aspect
@Component
public class MyAspect {
    
    @Before("execution(* com.example.MyService.myMethod(..))")
    public void beforeMethod(JoinPoint joinPoint) {
        // 在目标方法执行之前执行的通知逻辑
        
        // 可以在此处编写需要在目标方法执行之前执行的代码或操作
        
    }
}

后置增强(又称后置通知)的特点

后置增强用@After标识,增强方法在目标方法执行后执行,无论目标方法运行期间是否出现异常。在核心功能之后执行的额外功能。

@Aspect
@Component
public class MyAspect {
    
    @After("execution(* com.example.MyService.myMethod(..))")
    public void afterMethod(JoinPoint joinPoint) {
        // 在目标方法执行之后执行的通知逻辑
        
        // 可以在此处编写需要在目标方法执行之后执行的代码或操作
        
    }
}

环绕增强(又称环绕通知)的特点

环绕增强由@Around修饰,可以实现上述@Before,@After,@AfterReturning和@AfterThrowing四种增强效果,可以实现动态代理全过程。在核心功能之前以及之后执行的额外功能。
注意:@Around修饰的方法中有ProceedingJoinPoint类型的参数,该变量可以决定是否执行目标方法;
@Before、@After、@AfterRunning和@AfterThrowing修饰的方法没有返回值;而@Around修饰的方法必须有返回值,返回值为目标方法的返回值;

@Aspect
@Component
public class MyAspect {
    
    @Around("execution(* com.example.MyService.myMethod(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 在目标方法前后执行的通知逻辑
        
        // 可以在此处编写需要在目标方法前后执行的代码或操作
        
        Object result;
        try {
            // 调用proceed()方法执行目标方法
            result = joinPoint.proceed();
            
            // 目标方法执行后的操作
            // 可以获取目标方法的返回值:result
            
        } catch (Exception ex) {
            // 异常处理操作
            throw ex;
        }
        
        return result;
    }
}

异常增强(又称异常通知)的特点

异常增强以@AfterThrowing注解为标识,目标方法抛出异常之后执行,可以访问到异常对象,且可以指定在出现哪种异常时才执行增强代码。在核心功能发生异常时执行的额外功能,先捕获,后抛出 。

@Aspect
@Component
public class MyAspect {
    
    @After("execution(* com.example.MyService.myMethod(..))")
    public void afterMethod(JoinPoint joinPoint) {
        // 在目标方法执行之后执行的通知逻辑
        
        // 可以在此处编写需要在目标方法执行之后执行的代码或操作
        
    }
}

P命名空间注入

p 命名空间是 setter 方式属性注入的一种快捷实现方式。通过它,我们能够以 bean 属性的形式实现 setter 方式的属性注入,而不再使用嵌套的 元素,以实现简化 Spring 的 XML 配置的目的。
首先我们需要在配置文件的 元素中导入以下 XML 约束。

xmlns:p=“http://www.springframework.org/schema/p”

在导入 XML 约束后,我们就能通过以下形式实现属性注入。

<bean id=“唯一标识” class=“类的全路径”
p:“属性1”=“注入的值” p:“属性2”=“注入的值” />
<bean id=“唯一标识” class=“类的全路径”
p:属性-ref=“注入的Bean” />

使用 p 命名空间注入依赖时,必须注意以下 3 点:

Java 类中必须有 setter 方法;
Java 类中必须有无参构造器(类中不包含任何带参构造函数的情况,无参构造函数默认存在);
在使用 p 命名空间实现属性注入前,XML 配置的 元素内必须先导入 p 命名空间的 XML 约束。

不同数据类型注入

简介

如果需要传递类似于 Java Collection 类型的值,例如 List、Set、Map 和 properties,可以使用 Spring 提供的集合配置标签,如下表所示:

如何使用List

package com.cskt.pojo;

import lombok.Data;

import java.util.List;

@Data
public class UserList {
    List manList;
}


<!--注入不同数据类型 list-->
 <bean id="userList" class="com.cskt.pojo.UserList">
        <property name="manList">
            <list>
                <value>test01</value>
                <value>test02</value>
                <value>test03</value>
                <value>test04</value>
            </list>
        </property>
 </<bean>


测试类

 public void UserList(){
       ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
       UserList list= (UserList) context.getBean("userList");
        list.getManList().stream().forEach(p->{
           System.out.println(p);
       });
   }

 如何使用Set

package com.cskt.pojo;

import lombok.Data;

import java.util.Set;

@Data
public class UserList {
     Set manSet;
}


<!--注入不同数据类型 list-->
 <bean id="userList" class="com.cskt.pojo.UserList">
        <property name="manSet">
              <set>
                <value>test01</value>
                <value>test02</value>
                <value>test03</value>
                <value>test04</value>
            </set>
        </property>
 </<bean>

测试类 

 public void UserList(){
       ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
       UserList list= (UserList) context.getBean("userList");
       list.getManSet().stream().forEach(p->{
            System.out.println(p);
        });
   }

 如何使用Map

package com.cskt.pojo;

import lombok.Data;

import java.util.Map;

@Data
public class UserList {
     Map manMap;
}


<!--注入不同数据类型 list-->
 <bean id="userList" class="com.cskt.pojo.UserList">
        <property name="manMap">
            <map>
                <entry key="1" value="test01" />
                <entry key="2" value="test02" />
                <entry key="3" value="test03" />
                <entry key="4" value="test04" />
            </map>
        </property>
 </<bean>

测试类

 public void UserList(){
       ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
       UserList list= (UserList) context.getBean("userList");
         list.getManMap().forEach((key,value) -> {
            System.out.println(key + ":" + value);
        });
   }

 如何使用Properties

package com.cskt.pojo;

import lombok.Data;
import java.util.Properties;

@Data
public class UserList {
    Properties manProp;
}


<!--注入不同数据类型 list-->
 <bean id="userList" class="com.cskt.pojo.UserList">
       <property name="manProp">
            <props>
                <prop key="one">test01</prop>
                <prop key="one">test04</prop>
                <prop key="two">test05</prop>
                <prop key="three">test06</prop>
                <prop key="four">test07</prop>
            </props>
        </property>
 </<bean>

测试类

 public void UserList(){
       ApplicationContext context=new ClassPathXmlApplicationContext("applicationContext.xml");
       UserList list= (UserList) context.getBean("userList");
          list.getManProp().forEach((key,value) -> {
            System.out.println(key + ":" + value);
        });
   }

 

使用注解实现Spring Ioc

常用的注解Ioc

@Component 将类标记为组件,表示它需要由Spring容器进行管理。
@Autowired
自动装配依赖,将相关的依赖注入到标记了该注解的字段、构造方法或者Setter方法中。

@Qualifier 与@Autowired一起使用,指定具体的依赖Bean。
@Value 将配置值注入到属性中。
@Configuration 将类标记为配置类,用于定义Bean的创建和依赖关系。
@Bean 在配置类中使用该注解来声明一个Bean,并提供其创建和初始化的逻辑。
@Repository 用于标注DAO类
@Service 用于标注业务类
@Controller 用于标注控制器类

实现方法

@Repository("userDao")// 与在XML配置文件中编写
//<bean id="userDao" class="dao.impl.UserDaoImpl" />等效
 
public class UserDaoImpl implements UserDao {
	…
}

使用@Autowired注解实现Bean的自动装配

默认按类型匹配,可使用@Qualifier指定Bean的名称



@Service("userService")
public class UserServiceImpl implements UserService {
	@Autowired
	@Qualifier("userDao")
	private UserDao dao;//为dao属性注入名为userDao的Bean
	……
}

 修改配置文件使注解生效,完成Bean的定义和组装

<?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:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd">
	<!– 扫描包中注解标注的类>
    <!--指定需要被Spring扫描的基准包范围(多个包名之间用逗号隔开)-->
	<context:component-scan base-package="service,dao" />
</beans>

使用Java标准注解完成装配

使用@Resource注解实现组件装配

@Service("userService")
public class UserServiceImpl implements UserService {
	@Resource
	private UserDao dao;//查询名为dao的Bean,并注入给dao属性
	……
}


@Service("userService")
public class UserServiceImpl implements UserService {
	@Resource(name="userDao")
	private UserDao dao;// 为dao属性注入名为userDao的Bean
	……
}

使用注解实现Spring Aop


@Aspect
public class MyAspect {
    //前置增强  方法前面 执行  后置增强  环绕增强  异常增强  最终增强
    //切面 Aspect  Advice  beforeAdvice pointCut
    // 给那个方法增强 。。。。。,
   @Before("execution( * com.cskt.service..*.*(..))")
   public void before(){

       System.out.println("前置通知.... 在方法之前要執行的公共代码放在这里");
   }
    @Aspect
@Component
public class MyAspect {
    
    @Pointcut("execution(* com.example.MyService.myMethod(..))")
    public void myMethodPointcut() {
        // 定义切入点
    }
    
    @Before("myMethodPointcut()")
    public void beforeMethod(JoinPoint joinPoint) {
        // 在目标方法执行之前执行的通知逻辑
    }
    
    @AfterThrowing(pointcut = "myMethodPointcut()", throwing = "ex")
    public void afterThrowingMethod(JoinPoint joinPoint, Exception ex) {
        // 在目标方法抛出异常后执行的通知逻辑
    }
    
    @AfterReturning(pointcut = "myMethodPointcut()", returning = "result")
    public void afterReturningMethod(JoinPoint joinPoint, Object result) {
        // 在目标方法成功返回结果后执行的通知逻辑
    }
    
    @Around("myMethodPointcut()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        // 环绕通知:在目标方法前后执行一些操作,需要手动调用proceed()方法执行目标方法
        Object result;
        try {
            // 目标方法执行前的操作
            result = joinPoint.proceed();
            // 目标方法执行后的操作
        } catch (Exception ex) {
            // 异常处理操作
            throw ex;
        }
        return result;
    }
    
    @After("myMethodPointcut()")
    public void afterMethod(JoinPoint joinPoint) {
        // 在目标方法执行之后执行的通知逻辑
    }
}

  • 27
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值