Spring学习笔记

Spring学习笔记(基于Idea,maven)

耦合: 程序间的依赖关系.在开发中,应该做到解决编译期依赖,即编译期不依赖,运行时才依赖.
解耦的思路: 使用反射来创建对象,而避免使用new关键字,并通过读取配置文件来获取要创建的对象全限定类名.

IOC(控制反转)

pom.xml
<packaging>jar</packaging>
<dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
    </dependencies>
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--把对象的创建交给spring来管理 -->
    
    <!--第一种创建Bean的方式 -->
    <!--将UserServiceImpl 加载进spring容器 -->
    <bean id="userServiceImpl" class="com.cgx.service.impl.UserServiceImpl" >
    </bean>
    <!--将UserDaoImpl 加载进spring容器 -->
    <bean id="userDaoImpl" class="com.cgx.dao.impl.UserDaoImpl">
    </bean>
    
    <!--第二种创建Bean的方式 -->
    <!--将userFactory 工厂加载进spring容器 -->
    <bean id="userFactory" class="com.cgx.service.factory.userFactory" >
    </bean>
    <!--通过userFactory工厂将userService加载进spring容器 
          factoty-bean:指定那个bean的id来创建
          factory-method:指定那个方法名称来创建
     -->
    <bean id="userService" factoty-bean="userFactory"  factory-method="getUsetService">
    </bean>
    
    <!--第三种创建Bean的方式 使用工厂中的静态方法-->
    <bean id="userService" class="com.cgx.factory.UserFactory"
          factorymethod="getUserService2"></bean>
    
</beans>
public static void main(String[] args) {
 
        //获取spring核心容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        //根据id获取bean对象
        UserService us = (UserService) ac.getBean("userServiceImpl");
        UserDao ud = ac.getBean("userDaoImpl", UserDao.class);
    
        System.out.println(us);
        System.out.println(ud);

    }
ApplicationContext接口的注意事项

ApplicationContext接口的实现类中我们常用的容器有三种:

ClassPathXmlApplicationContext:它是从根目录下加载配置文件

FileSystemXmlApplicationContext:它是从磁盘路径下加载配置文件

AnnotationConfigApplicationContext:读取注解创建容器

ApplicationContext接口 单例对象使用

​ 他在构建核心容器时,创建对象采取的策略是立即加载的方式。只要一读取玩配置文件就会创建配置文件中配置的对象

**Beanfactory接口 ** 多例对象使用

他在构建核心容器时,创建对象采取的策略是延迟加载的方式。什么时候根据id获取对象了,什么时候才创建对象

bean标签的属性
  • 作用: 配置托管给spring的对象,默认情况下调用类的无参构造函数,若果没有无参构造函数则不能创建成功
  • 属性:
    1. id: 指定对象在容器中的标识,将其作为参数传入getBean()方法可以获取获取对应对象.
    2. class: 指定类的全类名,默认情况下调用无参构造函数
    3. scope: 指定对象的作用范围,可选值如下
      • singleton: 单例对象,默认值
      • prototype: 多例对象
      • request: 将对象存入到web项目的request域
      • session: 将对象存入到web项目的session域
      • global session: 将对象存入到web项目集群的session域中,若不存在集群,则global session相当于session
    4. init-method:指定类中的初始化方法名称,在对象创建成功之后执行
    5. destroy-method:指定类中销毁方法名称,对prototype多例对象没有作用,因为多利对象的销毁时机不受容器控制
Bean的生命周期

单例对象

出生:容器创建时对象出生

活着:只要容器还在对象一直活着

死亡:容器销毁,对象消亡

总结:单例对象的生命周期和容器相同

多例对象

出生:当我们使用对象是spring框架为我们创建

活着:对象只要在使用过程中就一直活着

死亡:当对象尝试不用,且没有对象引用时,由java的垃圾回收器来回收

DI(依赖注入)

在当前类需要其他类的对象时,由spring为我们提供,我们只需要在配置文件中说明

依赖关系的维护就称之为依赖注入

能注入三种类型:

① 基本类型和String

② 其他bean类型(在配置文件中或注解配置过的)

③ 复杂类型和集合类型

注入的三种方式

①set注入

在bean标签的内部使用 property 标签

标签的属性:

​ name:用于指定给构造函数的指定名称的参数赋值

​ value:用于提供基本数据类型和string类型的数据

​ ref:用于指定其他bean的类型数据。他指的就是在spring中IOC核心容器中出现过的bean对象

bean.xml
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <!--    set注入-->
    <bean id="accountService" class="com.cgx.service.impl.AccountServiceImpl">
        <property name="name" value="翠花"></property>
        <property name="age" value="45"></property>
        <property name="birthday" ref="date"></property>
    </bean>
    
    <!-- 使用spring管理创建对象并加入容器-->
    <bean id="date" class="java.util.Date"></bean>

</beans>
AccountServiceImpl.java
public class AccountServiceImpl implements AccountService {

    private String name;
    private Integer age;
    private Date birthday;

    public void setName(String name) {
        this.name = name;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    @Override
    public void saveAccount() {
        System.out.println("account save ..............."+name+age+birthday);
    }
}

测试类
public class UserController {


    public static void main(String[] args) {

        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        AccountService as = ac.getBean("accountService", AccountService.class);
        as.saveAccount();

    }
}
运行结果

“C:\Program Files\Java\jdk1.8.0_73\bin\java.exe”
[INFO] Scanning for projects…
[INFO]
[INFO] ---------------------< org.example:Spring_Demo_01 >---------------------
[INFO] Building Spring_Demo_01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] — exec-maven-plugin:1.6.0:exec (default-cli) @ Spring_Demo_01 —
account save …翠花45Wed Jul 29 17:01:31 CST 2020
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 2.028 s
[INFO] Finished at: 2020-07-29T17:01:31+08:00
[INFO] ------------------------------------------------------------------------

复杂和集合类型注入

用于给list结构注入的标签:

list set array

用于给map 结构注入的标签:

map props

节构相同标签可以互换

bean.xml
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean id="arrayService" class="com.cgx.service.impl.ArrayServiceImpl">
          <property name="str">
              <array>
                  <value>AAA</value>
              </array>
          </property>
          <property name="list">
              <list>
                  <value>AAA</value>
              </list>
          </property>
          <property name="set">
              <set>
                  <value>AAA</value>
              </set>
          </property>
          <property name="map">
              <map>
                  <entry key="aaa" value="AAA"></entry>
              </map>
          </property>
          <property name="property">
              <props>
                  <prop key="aaa">AAA</prop>
              </props>
          </property>
    </bean>


</beans>
ArrayServiceImpl.java
public class ArrayServiceImpl implements ArrayService {

    private String[] str;
    private List<String> list;
    private Set<String> set;
    private Map<String ,String> map;
    private Properties property;

    public void setStr(String[] str) {
        this.str = str;
    }

    public void setList(List<String> list) {
        this.list = list;
    }

    public void setSet(Set<String> set) {
        this.set = set;
    }

    public void setMap(Map<String, String> map) {
        this.map = map;
    }

    public void setProperty(Properties property) {
        this.property = property;
    }

    @Override
    public void test() {
        System.out.println(Arrays.toString(str));
        System.out.println(set);
        System.out.println(list);
        System.out.println(map);
        System.out.println(property);
    }
}

测试类
public class UserController {

    public static void main(String[] args) {

        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        AccountService as = ac.getBean("accountService", AccountService.class);
        as.saveAccount();
        ArrayService ass = ac.getBean("arrayService", ArrayService.class);
        ass.test();

    }
}

运行结果

[INFO] Scanning for projects…
[INFO]
[INFO] ---------------------< org.example:Spring_Demo_01 >---------------------
[INFO] Building Spring_Demo_01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] — exec-maven-plugin:1.6.0:exec (default-cli) @ Spring_Demo_01 —
account save …翠花45Wed Jul 29 17:49:29 CST 2020
[AAA]
[AAA]
[AAA]
{aaa=AAA}
{aaa=AAA}
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.748 s
[INFO] Finished at: 2020-07-29T17:49:29+08:00
[INFO] ------------------------------------------------------------------------

②构造器注入

在 bean 标签的内部使用 constructor-arg 标签来注入

标签的属性

​ type:用于指定要注入的数据的数据类型,该数据类型也是构造函数中某个后某些参数的构造类型

​ index:用于指定要注入数据给构造函数中指定索引的位置参数,从0开始

​ name:用于指定给构造函数的指定名称的参数赋值

以上三个标签是给构造函数赋值的======

​ value:用于提供基本数据类型和string类型的数据

​ ref:用于指定其他bean的类型数据。他指的就是在spring中IOC核心容器中出现过的bean对象

优势:

​ 在获取bean对象时,注入的数据是必须的操作,否则对象无法创建成功

弊端:

​ 改变了bean对象的实例化方式,使我们在穿件对象时,用不到这些对象时,页必须提供

bean.xml配置文件
<?xml version="1.0" encoding="utf-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

      <bean id="accountService" class="com.cgx.service.impl.AccountServiceImpl">
          <constructor-arg name="name" value="张三"></constructor-arg>
          <constructor-arg name="age" value="18"></constructor-arg>
          <constructor-arg name="birthday" ref="date"></constructor-arg>
      </bean>
      
      <bean id="date" class="java.util.Date"></bean>

</beans>
AccountServiceImpl.java
public class AccountServiceImpl implements AccountService {

    private String name;
    private Integer age;
    private Date birthday;

    public AccountServiceImpl(String name, Integer age, Date birthday) {
        this.name = name;
        this.age = age;
        this.birthday = birthday;
    }

    @Override
    public void saveAccount() {
        System.out.println("account save ..............."+name+age+birthday);
    }
}
main方法
public class UserController {

    int id;
    public static void main(String[] args) {
        //获取核心容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
        //根据id获取bean对象
        AccountService as = ac.getBean("accountService", AccountService.class);
        as.saveAccount();

    }
}
运行结果

[INFO] Scanning for projects…
[INFO]
[INFO] ---------------------< org.example:Spring_Demo_01 >---------------------
[INFO] Building Spring_Demo_01 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] — exec-maven-plugin:1.6.0:exec (default-cli) @ Spring_Demo_01 —
account save …张三18Wed Jul 29 16:38:30 CST 2020
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.791 s
[INFO] Finished at: 2020-07-29T16:38:30+08:00
[INFO] ------------------------------------------------------------------------

③ 注解注入
spring的常用注解

使用注解配置的方式实现IOC

用于创建对象的

他们的作用就和bean标签的实现的功能是一样的

使用前提: 需要在bean.xml中配置扫描的包

​ @Component【(“accountService”) 】

​ 作用:用于把当前类加载到spring容器

​ 属性:value 用于指定配置bean的id。当我们不写时默认为当前类的首字母小写

​ @Controller:用于表现层

​ @Service:用于业务层

​ @ Repository:用于持久层

以上三个注解和@Component作用是一样的

bean.xml
<?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">

    <!--开启扫描注解 -->
    <context:component-scan base-package="com.cgx"/>

</beans>
AccountServiceImpl.java
@Component("accountService")
public class AccountServiceImpl implements AccountService {

    @Override
    public void test() {
        System.out.println("service test() Execute.........");
    }
}

main方法
public class Client {

    public static void main(String[] args) {
        //获取spring核心容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //根据id获取bean对象
        AccountService as = ac.getBean("accountService", AccountService.class);
        as.test();
    }

}

用于注入数据的

@Autowired

作用:自动按照类型注入。只要容器中有唯一 一个bean对象类型和要注入的类型匹配,就可以注入成功。

​ 如果IOC容器中没有任何bean的类型的类型和要注入的变量类型相匹配,则报错。

​ 如果IOC容器中有多个类型时,如图所示:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oyWsedtp-1596699794005)(D:\杂物\Typora笔记文档\image\image-20200730162814109.png)]

位置: 可以是变量上也可以是方法上

@Qualifier(“accountDaoImpl”)

作用:在按照类中注入的基础之上再按名称注入,不能单独使用,但是在个方法参数注入是可以。

属性:value:用于指定注入bean的id

@Resource【(name=“accountDaoImpl”)】

作用:直接按照bean的id注入。他可以独立使用。

属性:name:用于指定bean的id。注入的接口只有一个实现类是可以不写。

以上三个注入都只能注入其他bean类型的数据,而基本类型和String类型无法使用上述注解实现。

另外集合类型的注入只能通过XMl来实现

用于于改变他们作用范围的

@Scope

他的作用就和bean标签中scope属性实现的功能是一样。

作用:指定bean的作用 范围

属性: value:指定范围的取值。常用的取值: singleton prototype

和生命周期相关的

作用就和在bean标签中使用init-methode和destroy-methode的作用是一样。

PreDestroy

​ 用于指定销毁方法

PostConstruct

​ 用于指定初始化方法

基于dbutils案例

pom文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Spring_Demo_02</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>commons-dbutils</groupId>
            <artifactId>commons-dbutils</artifactId>
            <version>1.4</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.19</version>
        </dependency>

        <dependency>
            <groupId>c3p0</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.1.2</version>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

</project>

Accountdao AccountService

public interface AccountDao {


    //查询
    List<Account> findSelectAll();

    //查询单个
    Account findById(int id);

    //添加
    void addAccount(Account account);

    //修改
    void updateAccount(Account account);

    //删除
    void deleteAccount(int id);
}

AccountServiceImpl

@Component
public class AccountServiceImpl implements AccountService {

    @Resource(name="accountDaoImpl")
    private AccountDao accountDao;


    @Override
    public List<Account> findSelectAll() {
        return accountDao.findSelectAll();
    }

    @Override
    public Account findById(int id) {
        return accountDao.findById(id);
    }

    @Override
    public void addAccount(Account account) {
        accountDao.addAccount(account);
    }

    @Override
    public void updateAccount(Account account) {
        accountDao.updateAccount(account);
    }

    @Override
    public void deleteAccount(int id) {
        accountDao.deleteAccount(id);
    }
}

AccountDaoImpl

@Repository
public class AccountDaoImpl implements AccountDao {

    @Resource
    private QueryRunner qr;


    @Override
    public List<Account> findSelectAll() {
        try {
            return qr.query("select * from account",
                    new BeanListHandler<Account>(Account.class));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public Account findById(int id) {

        try {
            return qr.query("select * from account where id= ?", new BeanHandler<Account>(Account.class),id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void addAccount(Account account) {
        try {
            qr.update("insert into account set name = ?, money = ?",
                    account.getName(),
                    account.getMoney());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void updateAccount(Account account) {
        try {
            qr.update("update account set name = ?, money=? where id = ?",
                    account.getName(),account.getMoney(),account.getId());
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void deleteAccount(int id) {
        try {
            qr.update("delete from account where id = ?", id);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}

bean.xml

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

    <!--扫描包 -->
    <context:component-scan base-package="com.cgx"/>

    <bean id="qr" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">
      <!--引入数据源 -->
        <constructor-arg name="ds" ref="dataSource"></constructor-arg>
    </bean>

    <!-- 配置数据源-->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">

        <!-- 配置连接信息-->
        <property name="driverClass" value="com.mysql.cj.jdbc.Driver"></property>
        <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?serverTimezone=UTC"></property>
        <property name="user" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
</beans>

测试

public class Client {

    public static void main(String[] args) {
        //获取spring核心容器
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        //根据id获取bean对象
        AccountService as = ac.getBean("accountServiceImpl", AccountService.class);

        System.out.println(as.findSelectAll());

//        System.out.println(as.findById(3));

//        Account account = new Account();
//        account.setMoney(1200f);
//        account.setName("FFF");
//        as.addAccount(account);

//        as.deleteAccount(4);

//        Account account = new Account();
//        account.setId(5);
//        account.setMoney(1200f);
//        account.setName("GGG");
//        as.updateAccou配置nt(account);

    }

}

使用注解实现配置(了解)

创建一个配置类,他的作用和bean.xml是一样

@Configuration

​ 作用:表示当前类是一个配置类

​ 位置:放到类名的最上方

@ComponentScan(“com.cgx”)

​ 作用:通过该注解可以指定spring创建容器时要扫描的包

​ 位置:放到类名的上方

​ 属性: value:他和basePackages 的作用是一样指定spring创建容器时要扫描的包

​ 相当于: <context:component-scan base-package=“com.cgx”/>

@Bean(“xx”)

作用:用于把当前方法的返回值作为bean对象存入spring的IOC容器中

属性: name:用于指定bean的id,当不写时,默认值是方法名

细节:当我们使用注解配置方法时,如果方法有参数,spring框架会去容器中查找有没有的可用的bean对象。 查找的方式和Autowirte一样 。

ConfigSpring.java

@Configuration
@ComponentScan("com.cgx")
public class ConfigSpring {

    /**
     * 创建一个返回QueryRunner的方法
     * @param dataSource
     * @return
     */
    @Bean("qr")
    public QueryRunner getQueryRunner(DataSource dataSource){
        return new QueryRunner(dataSource);
    }


    @Bean(name = "dateSource")
    @Scope("prototype")
    public DataSource getDaoSource(){
        try {
            ComboPooledDataSource cpds = new ComboPooledDataSource();
            cpds.setDriverClass("com.mysql.cj.jdbc.Driver");
            cpds.setJdbcUrl("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
            cpds.setUser("root");
            cpds.setPassword("root");
            return cpds;
        } catch (PropertyVetoException e) {
            throw new RuntimeException(e);
        }
    }
}

测试类

public class Client {

    public static void main(String[] args) {
        //获取spring核心容器
        ApplicationContext ac =
                new AnnotationConfigApplicationContext(ConfigSpring.class);
        
        //根据id获取bean对象
        AccountService as = ac.getBean("accountServiceImpl", AccountService.class);

        System.out.println(as.findSelectAll());

    }

}

动态代理回顾

特点: 字节码随用随创建,随用随加载

作用:不修改源码的基础上对方法增强

分类:①基于接口 ② 基于类

基于接口的动态代理

涉及的类:Proxy

提供者:JDK官方

如何创建代理对象:使用Proxy类中的静态方法newProxyIntance

要求:被代理类至少实现一个接口。没有不能使用

newProxyIntance()的参数

​ ClassLoader :他是用于加载对象字节码的,和被代理对象使用相同类型的加载器。固定写法。

​ Class<?>[] :字节码数组,他是用于代理对象和被代理对象有相同的方法。固定写法。

​ InvocationHandler:用于提供增强的代码,他是让我们写如何代理,我们一般都是一些该接口的实现类,同城情况下都是匿名内部类,但不是必须的。此接口的实现类都是谁用谁写。

​ 方法参数含义:proxy 代理对象的引用 method:当前执行的方法 args:当前执行方法所需要的参数 返回和被代理对象方法有相同的返回值。

AOP面向切面

通过动态代理的方式实现。

Spring基于xml配置AOP

把通知bean也交给spring来管理

使用 aop:config 标签表名开始AOP的配置

使用 aop:aspect标签表明配置切面

​ id:是给切面提供唯一标识

​ ref:是指定通知类bean的Id

在 aop:aspect标签内部使用对应的标签来配置通知类型

​ aop:berfore:表示配置前置通知

​ method:用于指定通知类中那个方法是前置通知

​ pointcut:用于指定切入点表达式,该表达式的含义是对指定方法增强

​ 切入点表达式的写法:

关键字:execution(“表达式”)

​ 表达式写法

​ public void com.cgx.service.impl.AccountServiceImpl.saveAccont();

​ 访问修饰符可以省略

​ void com.cgx.service.impl.AccountServiceImpl.saveAccont();

​ 返回值类型可以使用通配符

​ * com.cgx.service.impl.AccountServiceImpl.saveAccont();

                      //包名可以使用通配符  
                   *  *.*.*.*.*.saveAccount();
                      //类名和方法名也能使用通配符
                   *  *.*.*.*.AccountServiceImpl.saveAccount();  
                   *  *.*.*.*.*.*();
                   *  *..*.*();
                   //参数列表
                   /**
                   *可以直接写数据类型
                   *   基本数据类型直接写  int
                   *   引用数据类型写包名.类名  java.lang.String
                   *   可以使用通配符表示任意参数类型,但是必须要参数
                   *   可以使用..表示,有无参数均可
                   */ 
                   //全统配写法
                   *  *..*.*(..);
                   //常用写法
                   * com.cgx.service.impl.*.*(..)

案例

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Spring_Demo_03</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

</project>
AccountServieImpl.java
package com.cgx.service.impl;

import com.cgx.service.AccountService;

public class AccountServiceImpl implements AccountService {
    @Override
    public void saveAccount() {
        System.out.println("saveAccount execute......");
    }

    @Override
    public void updateAccount(int i) {
        System.out.println("updateAccount execute......"+i);
    }

    @Override
    public int deleteAccount() {
        System.out.println("deleteAccount execute......");
        return 0;
    }
}

Logges
package com.cgx.utils;

public class Logges {

    public void berfor(){
        System.out.println("前置通知执行了");
    }
}

bean.xml
<?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="log" class="com.cgx.utils.Logges"></bean>

    <bean id="accountServiceImpl" class="com.cgx.service.impl.AccountServiceImpl"></bean>
    <aop:config>
        <aop:aspect id="loge" ref="log">
            <aop:before method="berfor" pointcut="execution(* com..AccountServiceImpl.*(..))"></aop:before>
        </aop:aspect>
    </aop:config>
        
    <!-- 
        <aop:config>
          <aop:pointcut id="pointcut" expression="execution(* com.cgx.service.impl.*.*(..))"/>
          <aop:aspect id="loge" ref="log">
            <aop:before method="berfor" pointcut-ref="pointcut"></aop:before>
          </aop:aspect>
    </aop:config>-->
</beans>
测试类
import com.cgx.service.AccountService;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class Test01 {

    @Test
    public void test01(){

        ApplicationContext ac=new ClassPathXmlApplicationContext("bean.xml");
        AccountService as = ac.getBean("accountServiceImpl",AccountService.class);
        as.saveAccount();
        as.deleteAccount();
        as.updateAccount(1);
    }

}

结果

前置通知执行了
saveAccount execute…
前置通知执行了
deleteAccount execute…
前置通知执行了
updateAccount execute…1

Spring中JdbcTemplate

他是spring框架中提供的一个对象,是对原始Jdbc API对象的简单封装。

JdbcTemplate使用的简单案例

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>org.example</groupId>
    <artifactId>Spring_Demo_03</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <dependencies>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.9.2</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.41</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>
    </dependencies>

</project>
bean.xml
<?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="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
        <property name="dataSource" ref="dmd"></property>
    </bean>

    <!--配置数据源 -->
    <bean id="dmd" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>
</beans>
测试类
package com.cgx.jdbcTemplate;

import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

public class TemplateSpring {

//    @Test
//    public void test(){
//        DriverManagerDataSource dmd = new DriverManagerDataSource();
//        dmd.setDriverClassName("com.mysql.jdbc.Driver");
//        dmd.setUrl("jdbc:mysql://localhost:3306/test");
//        dmd.setUsername("root");
//        dmd.setPassword("root");
//
//        JdbcTemplate jdbcTemplate = new JdbcTemplate(dmd);
//        jdbcTemplate.update("insert into account set name='QQQ',money=1000");
//    }
    @Test
    public void test2(){
        ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
        JdbcTemplate jdbcTemplate = ac.getBean("jdbcTemplate", JdbcTemplate.class);
        jdbcTemplate.execute("insert into account set name='EEE',money=1000");
        List<Account> accounts = jdbcTemplate.query("select * from account",
                new BeanPropertyRowMapper<Account>(Account.class));
        accounts.stream().forEach(account -> System.out.println(account));

    }
}

基于xml的aop事务控制

事务控制是基于业务层的。

①配置数据源

​ 属性:

​ id:指定唯一标识 、(dataSource)

​ class:由spring提供的数据源 (可以使用其他数据源)

​ org.springframework.jdbc.datasource.DriverManagerDataSource

set注入:

​ 数据库连接驱动 、 URL、 用户名、密码

②配置事务管理器

​ id:指定唯一标识

​ class:spring提供的事务管理器

​ org.springframework.jdbc.datasource.DataSourceTransactionManager

​ set注入数据源

​ id:DataSourceTransactionManager的方法setDataSource(dataSource)

​ ref:配置的数据源的id

③配置事务通知

​ id:指定唯一标识

​ transaction-manage:指定事务管理器的id

​ 配置事务增强

​ < tx:attributes>
​ < tx:method >中的属性

​ name:增强的方法

​ propagation=“REQUIRED” 事务的隔离级别

​ read-only="false"是否只读

④配置aop

配置切入点表达式

配置事务通知和切入点表达式的连接

<?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"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/tx/spring-context.xsd
        http://www.springframework.org/schema/tx
        https://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        https://www.springframework.org/schema/aop/spring-aop.xsd">

    <bean id="accountService" class="com.cgx.service.impl.AccountServiceImpl">
        <property name="accountDao" ref="accountDao"></property>
    </bean>

    <bean id="accountDao" class="com.cgx.dao.impl.AccountDaoImpl">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    
    <!-- 导入db.properties文件 
	<context:property-placeholder location="classpath:db.properties" />
     -->
    <!--配置数据源 -->
    <bean id="dataSource"
          class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
        <property name="url" value="jdbc:mysql://localhost:3306/test"></property>
        <property name="username" value="root"></property>
        <property name="password" value="root"></property>
    </bean>

    <!--配置事务管理器 -->
    <bean id="transactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!--配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
         <!--配置事务增强 -->
        <tx:attributes>
            <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
            <tx:method name="add*" propagation="REQUIRED" read-only="false"/>
            <tx:method name="update*" propagation="REQUIRED" read-only="false"/>
            <tx:method name="delete*" propagation="REQUIRED" read-only="false"/>
        </tx:attributes>
    </tx:advice>

    <!--配置aop-->
    <aop:config>
        <!--配置切入点表达式
        <aop:pointcut id="pointcut"
                      expression="execution(* com.cgx.service.impl.*.*(..))"/>
         -->
        <!--配置事务通知和切入点表达式的连接 -->
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.cgx.service.impl.*.*(..))"/>
    </aop:config>

</beans>

anagerDataSource">




<!--配置事务管理器 -->
<bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!--配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
     <!--配置事务增强 -->
    <tx:attributes>
        <tx:method name="find*" propagation="SUPPORTS" read-only="true"/>
        <tx:method name="add*" propagation="REQUIRED" read-only="false"/>
        <tx:method name="update*" propagation="REQUIRED" read-only="false"/>
        <tx:method name="delete*" propagation="REQUIRED" read-only="false"/>
    </tx:attributes>
</tx:advice>

<!--配置aop-->
<aop:config>
    <!--配置切入点表达式
    <aop:pointcut id="pointcut"
                  expression="execution(* com.cgx.service.impl.*.*(..))"/>
     -->
    <!--配置事务通知和切入点表达式的连接 -->
    <aop:advisor advice-ref="txAdvice" pointcut="execution(* com.cgx.service.impl.*.*(..))"/>
</aop:config>
```
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值