一、AOP演示

1.1 xml配置文件

1.1.1 导包

  • 4 + 2 + 4

    • 最后一个4

      • Spring的AOP包

        1. spring-aspects-4.2.4.RELEASE.jar
        2. spring-aop-4.2.4.RELEASE.jar
      • Spring需要的第三方AOP包

        1. com.springsource.org.aopalliance-1.0.0.jar
        2. com.springsource.org.aspectj.weaver-1.6.8.RELEASE.jar

1.1.2 准备目标对象

package a_springaop;

// 切入点的类
public class UserServiceImpl implements UserService {

    @Override
    public void add() {
//        异常
        int a = 1/0;
        System.out.println("add");
    }

    @Override
    public void delete() {
        System.out.println("delete");
    }

    @Override
    public void modify() {
        System.out.println("modify");
    }

    @Override
    public void find() {
        System.out.println("find");
    }
}

1.1.3 准备通知

  1. 前置通知:在切入点之前执行
  2. 后置通知:在切入点之后执行(无论有没有异常都执行)
  3. 环绕通知:切入点之前和之后都执行;如果遇到异常,之后的代码就不执行
  4. 异常通知:在切入点遇到异常后执行
  5. 后置通知:在切入点正常结束后才执行
package a_springaop;

import org.aspectj.lang.ProceedingJoinPoint;

// 通知类 - 基本了解
// 前置通知
    // -在切入点之前执行
// 后置通知
    // -在切入点之后执行(无论有没有异常都执行)
// 环绕通知 ProceedingJoinPoint
    // 切入点之前和之后都执行
    // 如果遇到异常,之后的代码就不执行
// 异常通知
    // 在切入点遇到异常后执行
// 后置通知 afterReturning
    // 在切入点正常结束后才执行
public class MyAdvice {
    // 前置通知
    public void before() {
        System.out.println("前置通知");
    }
    public void after() {
        System.out.println("后置通知1");
    }
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕通知前");
        // 执行原来方法
        jp.proceed();
        System.out.println("环绕通知后");
    }
    public void afterException() {
        System.out.println("异常通知");
    }
    public void afterReturnning() {
        System.out.println("后置通知2");
    }
}

1.1.4 将通知织入到目标对象中

  1. 配置切入点
  2. 配置通知类
  3. 织入:添加新的命名空间:aop

    1. aop:config

      1. 切入点配置:aop:pointcut

        1. 配置方法:expressionexpression="execution(* a_springaop.*ServiceImpl.*(..))"
        2. 切入点id:id
      2. 配置切面:aop:aspect
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
    
    <!-- 1.配置切入点类 -->
    <bean name="userService" class="a_springaop.UserServiceImpl"></bean>
    <!-- 2.配置通知类 -->
    <bean name="myAdvice" class="a_springaop.MyAdvice"></bean>
    
    <!-- 3.织入 添加新的命名空间:aop -->
    <aop:config>
        <!-- 切入点配置:要增强的方法
                void a_springaop.UserServiceImpl.add()
                * a_springaop.UserServiceImpl.add()
                * a_springaop.UserServiceImpl.*()
                * a_springaop.*ServiceImpl.*()
                * a_springaop.*ServiceImpl.*(..)
         -->
        <aop:pointcut expression="execution(* a_springaop.*ServiceImpl.*(..))" id="pc"/>
        <!-- 配置切面 -->
        <aop:aspect ref="myAdvice">
            <aop:before method="before" pointcut-ref="pc"/>
            <aop:after method="after" pointcut-ref="pc"/>
            <aop:around method="around" pointcut-ref="pc"/>
            <aop:after-throwing method="afterException" pointcut-ref="pc"/>
            <aop:after-returning method="afterReturnning" pointcut-ref="pc"/>
        </aop:aspect>
    </aop:config>
</beans>

1.2 注解配置

1.2.1 导包(与配置文件一致)

1.2.2 准备目标对象(与配置文件一致)

1.2.3 准备通知(一定要在配置文件中开启注解)

  • 使用注解之前,配置文件中开启注解

    • <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
// 通知类 - 基本了解
// 前置通知
    // -在切入点之前执行
// 后置通知
    // -在切入点之后执行(无论有没有异常都执行)
// 环绕通知 ProceedingJoinPoint
    // 切入点之前和之后都执行
    // 如果遇到异常,之后的代码就不执行
// 异常通知
    // 在切入点遇到异常后执行
// 后置通知 afterReturning
    // 在切入点正常结束后才执行
// 使用注解之前,配置文件中开启注解
// <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
  • 配置文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
        
        <!-- 1.配置切入点类 -->
        <bean name="userService" class="b_annotationaop.UserServiceImpl"></bean>
        <!-- 2.配置通知类 -->
        <bean name="myAdvice" class="b_annotationaop.MyAdvice"></bean>
        <!-- 3.使用注解配置织入过程 -->
        <!-- 开启aop的注解配置 -->
        <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
    </beans>

1.2.4 将通知织入目标对象中

package b_annotationaop;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;

// 通知类 - 基本了解
// 前置通知
    // -在切入点之前执行
// 后置通知
    // -在切入点之后执行(无论有没有异常都执行)
// 环绕通知 ProceedingJoinPoint
    // 切入点之前和之后都执行
    // 如果遇到异常,之后的代码就不执行
// 异常通知
    // 在切入点遇到异常后执行
// 后置通知 afterReturning
    // 在切入点正常结束后才执行
// 使用注解之前,配置文件中开启注解
// <aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Aspect // 标志类是通知类
public class MyAdvice {
    @Pointcut("execution(* b_annotationaop.*ServiceImpl.*(..))")
    public void pc() {
        // 方法唯一的用处就是为了承载注解
    }
    // 前置通知
    @Before("MyAdvice.pc()")
    public void before() {
        System.out.println("前置通知");
    }
    @After("MyAdvice.pc()")
    public void after() {
        System.out.println("后置通知1");
    }
    @Around("execution(* b_annotationaop.*ServiceImpl.*(..))")
    public void around(ProceedingJoinPoint jp) throws Throwable {
        System.out.println("环绕通知前");
        // 执行原来方法
        jp.proceed();
        System.out.println("环绕通知后");
    }
    @AfterThrowing("execution(* b_annotationaop.*ServiceImpl.*(..))")
    public void afterException() {
        System.out.println("异常通知");
    }
    @AfterReturning("execution(* b_annotationaop.*ServiceImpl.*(..))")
    public void afterReturnning() {
        System.out.println("后置通知2");
    }
}

二、Spring整合JDBC

2.1 Spring提供的DAO层模板

2.2 JdbcTemplate

  • 功能与DBUtilsQueryRunner类似

    //0. 准备连接池
    ComboPooledDataSource dataSource = new ComboPooledDataSource();
    dataSource.setDriverClass("com.mysql.jdbc.Driver");
    dataSource.setJdbcUrl("jdbc:mysql:///ssh");
    dataSource.setUser("root");
    dataSource.setPassword("root");
    
    //1. 创建JDBC模板对象
    JdbcTemplate jt = new JdbcTemplate();
    jt.setDataSource(dataSource);
    
    //2. 书写sql,并执行
    String sql = "insert into user values(null, 'rose')";
    jt.update(sql);

2.3 步骤

2.3.1 导包

  1. 4 + 2:4个核心+2个日志
  2. 测试和切面需要的

    1. spring-test
    2. spring-aop
    3. junit4类库
  3. 数据库

    1. c3p0连接池
    2. JDBC驱动
  4. 事务

    1. spring-jdbc
    2. spring-tx事务

2.3.2 准备数据库

2.3.3 书写DAO

package c_jdbctemplate;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;


public class UserDaoImpl implements UserDao {
    private JdbcTemplate jdbcTemplate;
    //增
    @Override
    public void addUser(User user) {
        String sql = "insert into user values(null,?)";
        jdbcTemplate.update(sql, user.getName());
    }
    //删
    @Override
    public void deleteUserById(int id) {
        String sql = "delete from user where id = ?";
        jdbcTemplate.update(sql, id);
    }
    //改
    @Override
    public void updateUser(User user) {
        String sql = "update user where id=? and name=?";
        jdbcTemplate.update(sql, user.getId(), user.getName());
    }
    //查全部
    @Override
    public List<User> findAll() {
        String sql = "select * from user";
        List<User> list = jdbcTemplate.query(sql, new RowMapper<User>() {

            @Override
            public User mapRow(ResultSet rs, int index) throws SQLException {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                User user = new User();
                user.setId(id);
                user.setName(name);
                return user;
            }
            
        });
        return list;
    }
    //查单个
    @Override
    public User getUser(int id) {
        String sql = "select * from user where id = ?";
        
        User user = jdbcTemplate.queryForObject(sql, new RowMapper<User>() {

            @Override
            public User mapRow(ResultSet rs, int index) throws SQLException {
                int id1 = rs.getInt("id");
                String name1 = rs.getString("name");
                User user = new User();
                user.setId(id1);
                user.setName(name1);
                return user;
            }
            
        }, id);
        return user;
    }
    
    public JdbcTemplate getJdbcTemplate() {
        return jdbcTemplate;
    }

    public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }
}

2.3.4 Spring配置

  • 逐层注入原理

  • 因此要在配置文件中,都要注入。需要什么,注入什么

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns="http://www.springframework.org/schema/beans"
        xmlns:p="http://www.springframework.org/schema/p"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:aop="http://www.springframework.org/schema/aop"
        xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">
        
        <!-- 注册Dao -->
        <bean name="userDao" class="c_jdbctemplate.UserDaoImpl">
            <property name="jdbcTemplate" ref="jdbcTemplate"></property>
        </bean>
        <!-- 注册jdbcTemplate -->
        <bean name="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        <!-- 注册DataSource -->
        <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql:///ssh"></property>
            <property name="user" value="root"></property>
            <property name="password" value="123456"></property>
        </bean>
    </beans>

2.3.5 测试

package c_jdbctemplate;

import java.util.List;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:c_jdbctemplate/applicationContext.xml")
public class JdbcTemplateDemo {
    @Autowired
    private UserDao ud;
    @Test
    public void test01() {
        User user = new User();
        user.setName("lucy");
        ud.addUser(user);
    }
    
    @Test
    public void test02() {
        User user = ud.findUserById(1);
        System.out.println(user);
    }
    
    @Test
    public void test03() {
        List<User> list = ud.findAll();
        System.out.println(list);
    }
}

2.4 进阶内容(JdbcDaoSupport)

2.4.1 原理

  • JdbcTemplate的注入交给别人(JdbcDaoSupport)来做,注入过程少了一个步骤

  • AccountDaoImpl:继承JdbcDaoSupport

    package d_transaction;
    
    import org.springframework.jdbc.core.support.JdbcDaoSupport;
    
    // JdbcDaoSupport已经包含了 JdbcTemplate
    public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
        
        @Override
        public void decrement(int fromId, double money) {
            String sql = "update account set money = money - ? where id = ?";
            // 调用父类的JdbcTemplate对象
            getJdbcTemplate().update(sql, money, fromId);
        }
    
        @Override
        public void increment(int toId, double money) {
            String sql = "update account set money = money + ? where id = ?";
            getJdbcTemplate().update(sql, money, toId);
        }
    }
  • 配置文件中进行注册

        <!-- 1.注册service -->
        <bean name="accountService" class="d_transaction.AccountServiceImpl" >
            <property name="ad" ref="accountDao"></property>
        </bean>
        
        <!-- 2.注册dao -->
        <bean name="accountDao" class="d_transaction.AccountDaoImpl">
            <property name="dataSource" ref="dataSource"></property>
        </bean>
        
        <!-- 4.注册dataSource -->
        <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
            <property name="jdbcUrl" value="jdbc:mysql:///ssh"></property>
            <property name="user" value="root"></property>
            <property name="password" value="123456"></property>
        </bean>

2.4.1 读取外部的Properties配置

  • 外部配置文件:db.properties

    jdbc.driverClass=com.mysql.jdbc.Driver
    jdbc.jdbcUrl=jdbc:mysql:///ssh
    jdbc.user=root
    jdbc.password=root
  • 配置文件中注意加前缀context:

        <!-- 1.引入src/db.properties配置文件 -->
        <context:property-placeholder location="classpath:db.properties"/>
        <!-- 3.注册dataSource -->
        <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driverClass}"></property>
            <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property>
            <property name="user" value="root"></property>
            <property name="password" value="123456"></property>
        </bean>
Last modification:September 7th, 2019 at 11:11 am