Spring注解驱动开发-AOP、Tx和Servlet3.0

时间:2023-01-26 09:01:56

1 AOP

1.1 什么是AOP?

  • 在程序运行期间动态的将某段代码切入到指定方法指定位置进行运行的编程方式。
  • 底层就是动态代理。

1.2 AOP的应用

  • 步骤:
    • ①定义一个目标类以及目标方法。
    • ②定义一个切面类,以及前置通知、后置通知等,使用各自的注解将通知织入到目标方法上。
    • ③将目标类和切面类注册到容器中。
    • ④在切面类上标注@Aspect注解,来告诉Spring这是一个切面类。
    • ⑤在配置类上加上@EnableAspectJAutoProxy开启AspectJ自动代理(开启注解的AOP模式)。  

 

  • 示例:
    • MathCalculator.java  
package com.xuweiwei.spring.aop;

/**
 * @describe: 定义一个业务逻辑类MathCalculator:在业务逻辑类运行的时候将日志进行打印(方法之前、方法之后、方法正常返回结果、方法出现异常信息)等
 * @author: 不为往事扰,余生只爱笑。
 * @version: 1.0
 */
public class MathCalculator {

    public int div(int a, int b) {
        return a / b;
    }


}
    • LogAspect.java  
package com.xuweiwei.spring.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;

import java.util.Arrays;

/**
 * @describe: 定义一个日志切面类LogAspect:切面类里面的方法需要动态的感知MathCalculator.div运行到那个阶段。
 * 所谓的通知方法:
 * 前置通知(@Before):在目标方法运行之前执行
 * 后置通知(@After):在目标方法运行之后执行
 * 返回通知(@AfterReturning):在目标方法正常返回之后运行
 * 异常通知(@AfterThrowing):在目标方法出现异常以后运行
 * 环绕通知(@Around):动态代理,手动推进目标方法运行
 * @author: 不为往事扰,余生只爱笑。
 * @version: 1.0
 */
@Aspect //标注这个类是切面类
public class LogAspect {

    @Pointcut("execution(* com.xuweiwei.spring.aop.MathCalculator.div(..))")
    public void pointcut() {

    }

    @Before(value = "pointcut()")
    public void logStart(JoinPoint joinpoint) {
        Object[] args = joinpoint.getArgs();
        System.out.println(joinpoint.getSignature().getName() + "方法开始^_^,参数列表是:" + Arrays.asList(args));
    }

    @After(value = "pointcut()")
    public void logEnd(JoinPoint joinpoint) {
        System.out.println(joinpoint.getSignature().getName() + "方法结束^_^");
    }

    @AfterReturning(value = "pointcut()", returning = "val")
    public void logReturn(JoinPoint joinpoint, Object val) {
        System.out.println(joinpoint.getSignature().getName() + "方法正常返回……运行结果:{" + val + "}");
    }

    @AfterThrowing(value = "pointcut()", throwing = "ex")
    public void logThrow(Exception ex) {
        System.out.println("除法出现异常……异常信息:{" + ex.getMessage() + "}");
    }


}
    • 配置类:将目标类和切面类都加入到Spring的容器中,并开启AspectJ自动代理  
package com.xuweiwei.spring.config;

import com.xuweiwei.spring.aop.LogAspect;
import com.xuweiwei.spring.aop.MathCalculator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * @describe:
 * @author: 不为往事扰,余生只爱笑。
 * @version: 1.0
 */
@EnableAspectJAutoProxy
@Configuration
public class MainConfig {

    @Bean
    public MathCalculator mathCalculator(){
        return new MathCalculator();
    }

    @Bean
    public LogAspect logAspect(){
        return new LogAspect();
    }

}
    • 测试  
package com.xuweiwei.sping;

import com.xuweiwei.spring.aop.MathCalculator;
import com.xuweiwei.spring.config.MainConfig;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ConfigurationSpringTest {

    @Test
    public void test() {
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);

        MathCalculator mathCalculator = context.getBean(MathCalculator.class);

        int result = mathCalculator.div(1, 1);

        System.out.println("返回结果:" + result);
    }

}

 

2 声明式事务

2.1 步骤

  • ①导入相关的依赖(数据源、驱动和ORM)。
  • ②配置数据源和JdbcTempleate、事务管理器。
  • ③给方法上标注@Transactional注解。
  • ④在配置类上标注@EnableTransactionManagement注解,开启基于注解的事务管理功能。

2.2 应用

  • 示例:
    • 数据库脚本.sql  
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `age` int(11) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 3 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
    • UserDao.java  
package com.xuweiwei.spring.dao;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Repository;

/**
 * @describe:
 * @author: 不为往事扰,余生只爱笑。
 * @version: 1.0
 */
@Repository
public class UserDao {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * 新增
     */
    public void insert(String username,Integer age){
        String sql = " insert into user (username,age) values (?,?) ";
        jdbcTemplate.update(sql,username,age);
    }


}
    • UserService.java  
package com.xuweiwei.spring.service;

import com.xuweiwei.spring.dao.UserDao;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @describe:
 * @author: 不为往事扰,余生只爱笑。
 * @version: 1.0
 */
@Transactional
@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    public void insert(String username, Integer age) {
        userDao.insert(username, age);
        int i = 10 / 0;
    }

}
    • 配置类  
package com.xuweiwei.spring.config;

import com.mchange.v2.c3p0.ComboPooledDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;

import javax.sql.DataSource;
import java.beans.PropertyVetoException;

/**
 * @describe:
 * @author: 不为往事扰,余生只爱笑。
 * @version: 1.0
 */
@ComponentScan(value = {"com.xuweiwei.spring.dao","com.xuweiwei.spring.service"})
@Configuration
@EnableTransactionManagement //开启基于注解的事务管理功能
public class MainConfig {
    /**
     * 将数据源注册到容器中
     *
     * @return
     */
    @Bean
    public DataSource dataSource() throws PropertyVetoException {
        ComboPooledDataSource dataSource = new ComboPooledDataSource();
        dataSource.setDriverClass("com.mysql.jdbc.Driver");
        dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUser("root");
        dataSource.setPassword("123456");
        return dataSource;
    }

    @Bean
    public JdbcTemplate jdbcTemplate() throws PropertyVetoException {
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        jdbcTemplate.setDataSource(dataSource());
        return jdbcTemplate;
    }

    /**
     * 配置事务管理器
     * @return
     */
    @Bean
    public PlatformTransactionManager platformTransactionManager() throws PropertyVetoException {
        DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource());
        return dataSourceTransactionManager;
    }

}
    • 测试  
Spring注解驱动开发-AOP、Tx和Servlet3.0Spring注解驱动开发-AOP、Tx和Servlet3.0
package com.xuweiwei.sping;

import com.xuweiwei.spring.config.MainConfig;
import com.xuweiwei.spring.service.UserService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class ConfigurationSpringTest {

    @Test
    public void test() {
        ApplicationContext context = new AnnotationConfigApplicationContext(MainConfig.class);
        UserService userService = context.getBean(UserService.class);

        userService.insert("许威威", 27);
    }

}
View Code

 

3 Servlet3.0

3.1 Servlet标准以及对应支持的Tomcat

Spring注解驱动开发-AOP、Tx和Servlet3.0

3.2 Web三大组件在Servlet3.0规范中的应用

  • 示例:  
package com.xuweiwei.servlet;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @describe:
 * @author: 不为往事扰,余生只爱笑。
 * @version: 1.0
 */
@WebServlet(name = "HelloServlet",urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setContentType("text/html;charset=utf-8");
        response.getWriter().println("你好,世界");
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        this.doPost(request,response);
    }
}