Spring

Spring

Java应用最广泛的框架 ,它的成功来源于理念,而不是技术本身。

  • IOC 控制反转

  • AOP 面向切面编程

  • DI 依赖注入

非侵入式设计: 无需继承框架提供的任何一个类,更换框架,代码基本上不需要大改

 

Spring优势

  • 低侵入/低耦合

  • 声明式事务(基于AOP)

  • 方便集成其他框架

  • 降低了Java的开发难度

  • 提供了JavaWeb三层的每一层的解决方案

 

 

SpringBean

SpringBean是JavaBean的扩展,但是已经完全不是一回事了。

现在的JavaBean作为对象,要求每个属性提供setget方法,Spring的bean只需要为接收设置的值注入提供set方法

 

 

什么是Bean管理

  • Spring创建对象

  • Spring注入属性

 

Bean管理操作的方式

  • 基于xml配置文件方式实现

  • 基于注解方式实现

 

Spring的Bean生命周期

1.构造

2.注入

3.初始化

4.销毁

 

懒初始化(延迟初始化)

1.servlet的初始化 默认为懒初始化 Load-on-startup

2.spring的IOC容器 默认就是非懒初始化,只要spring的容器启动 所有的bean都会加载 都会初始化

 

IOC

控制反转 IOC容器!!!

基于xml配置文件方式实现

IOC操作Bean管理 (基于XML方式)

  • 基于xml创建对象

  • 基于xml注入属性

 

注入属性

第一种注入属性方式:Set注入

<!-- set方式注入属性-->
<!--创建对象 -->
   <bean id="book" class="com.jsoft.entity.Book">
       <!--set注入属性-->
       <property name="name" value="张三讲刑法"></property>
       <property name="author" value="张三"></property>
   </bean>

第二种注入方式 使用有参构造器注入

 <!--创建对象 -->
   <bean id="book" class="com.jsoft.entity.Book">
       <!--有参构造注入属性-->
       <constructor-arg name="name" value="西游记"></constructor-arg>
       <constructor-arg name="author" value="孙悟空"></constructor-arg>
   </bean>

P名称空间注入(了解)

  • 使用P名称空间注入 可以简化基于xml配置

<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      <!--p 名称空间声明-->
      xmlns:p="http://www.springframework.org/schema/p"
     
      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 https://www.springframework.org/schema/context/spring-context.xsd">


<!--创建对象 p名称空间赋值-->
   <bean id="book" class="com.jsoft.entity.Book" p:name="九阳神功" p:author="无名氏"> </bean>

测试类调用创建的对象

 public void testPrintBook(){

   //1.加载配置文件
ClassPathXmlApplicationContext context =
                   new ClassPathXmlApplicationContext("application.xml");

   //2.获取配置对象
   Book book = context.getBean("book",Book.class);

   //3.调用方法 打印
   book.printBook();
}

 

注入null值

使用<null/>

<property name="address"><null/></property>

 

注入特殊符号

  1. 使用&lt ; &gt ;

  2. 把带特殊符号的内容写道CDATA中去 <![CDATA[特殊符号的具体值]]>

<property name="address">
<value><![CDATA[<<南京>>]]></value>
</property>

 

注入外部Bean

xml 部分
<!-- 1.service 和 dao对象创建 -->
   <bean id="bookDao" class="com.jsoft.dao.BookDaoImpl"></bean>
   <bean id="bookService" class="com.jsoft.service.BookService">
       <!-- 注入userDao对象
           name 类里面属性名称
           ref 依赖 创建userDao对象bean的id值
       -->
       <property name="bookDao" ref="bookDao"></property>
   </bean>

 

java部分
 @Test
 public void testPrintBook(){

       //1.加载配置文件
       ClassPathXmlApplicationContext context =
                       new ClassPathXmlApplicationContext("application.xml");

       //2.获取配置对象 xml文件配置什么对象 这里获取什么
       BookService bookService = context.getBean("bookService", BookService.class);

       //3.调用方法 打印
      bookService.add();
  }

 

注入属性内部Bean

 <!--常规定义Bean-->
<bean id="emp" class="com.jsoft.entity.Emp">
               <property name="name" value="张三"></property>
               <property name="gender" value="男"></property>
  <!--定义内部Bean-->
               <property name="dept">
                       <bean id="dept" class="com.jsoft.entity.Dept">
                               <property name="name" value="安保部"></property>
                       </bean>
               </property>
       </bean>

 

级联赋值

(1)第一种写法 外部定义bean 直接赋值

 <bean id="emp" class="com.jsoft.entity.Emp">
       <property name="name" value="张三"></property>
       <property name="gender" value="男"></property
          <!--级联赋值 -->
       <property name="dept" ref="dept"></property>
</bean>

<bean id="dept" class="com.jsoft.entity.Dept">      
  <property name="name" value="安保部"></property>
</bean>

 

(2)第二种写法 外部定义bean 在内部调用属性赋值

  <bean id="emp" class="com.jsoft.entity.Emp">
     <property name="name" value="张三"></property>
     <property name="gender" value="男"></property>
     <!--级联赋值 -->
     <property name="dept" ref="dept"></property>
     <!--调用dept属性name赋值   需要dept类 有get方法 -->
     <property name="dept.name" value="财务部"></property>
 </bean>
       
 <bean id="dept" class="com.jsoft.entity.Dept"></bean>

 

Bean类型

  1. 普通bean 在配置文件中定义的bean类型和返回类型相同

  2. 工厂bean(FactoryBean) 配置文件定义的bean类型可以和返回类型不同

    • 第一步 创建类 让这个类作为工厂bean 实现接口FactoryBean

    • 第二步 实现接口里面的方法 在实现的方法中定义返回的bean类型

 

IOC操作Bean管理(bean作用域)

  1. 在spring里面 可以设置创建bean实例是单实例还是多实例

  2. 在spring里面 默认情况下 bean是单实例对象

  3. 如何设置是单实例还是多实例

    • 在spring配置文件bean标签里面有属性(scope)用于设置单实例还是多实例

    • scope属性值

      • 第一个值 默认值 singleton 表示单例模式

      • 第二个值 prototype 表示是多实例对象

    • singleton和prototype区别

      • 第一 singleton 是单实例 prototype 是多实例

      • 设置scope值是singleton时候 加载spring配置文件时候就会创建单实例对象

      • 设置scope值是prototype时候 不是在加载spring配置文件时候创建对象 在调用getBean方法时候创建多实例对象

 <!--创建对象 -->
   <bean id="book" class="com.jsoft.entity.Book" scope="prototype">
       <property name="name" value="大话西游"></property>
       <property name="author" value="孙悟空"></property>
       <property name="address">
           <value><![CDATA[<<南京>>]]></value>
       </property>
   </bean>

singleton 比较两个对象 true     prototype 比较两个对象 false

 

IOC操作Bean管理(bean生命周期)

  1. 通过构造器创建bean实例(无参构造器)

  2. 为bean的属性设置值和对其他bean引用(调用set方法)

  3. 调用bean的初始化的方法(需要进行配置初始化的方法)

  4. bean可以使用了(对象获取到了)

  5. 当容器关闭时候 调用bean的销毁的方法 (需要进行配置销毁的方法) 默认不调用 需要手动销毁bean

public class Orders {
   private String name;

   public void setName(String name) {
       this.name = name;
       System.out.println("第二步 调用set方法设置属性");
  }
   
   public Orders() {
       System.out.println("第一步 执行无参构造创建bean实例");
  }

   public void initMethod(){
       System.out.println("第三步 执行初始化的方法");
  }

   public void destoryMethod(){
       System.out.println("第五步 执行了销毁方法");
  }

   @Override
   public String toString() {
       return "Orders{" +
               "name='" + name + '\'' +
               '}';
  }
}


//调用方法
public void test2(){
       ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("bean2.xml");
       Orders orders = context.getBean("orders", Orders.class);
       System.out.println("第四步 获取了创建的bean实例对象");
       System.out.println(orders);
       context.close(); //如果不写close 默认不启动销毁  
  }
   <bean id="orders" class="com.jsoft.entity.Orders" 
        init-method="initMethod" destroy-method="destoryMethod">
      <!--手动设置初始化方法和销毁方法-->
               <property name="name" value="手机"></property>
       </bean>

 

如果加入 bean的后置处理器 bean的生命周期有七步

  1. 通过构造器创建bean实例(无参构造器)

  2. 为bean的属性设置值和对其他bean引用(调用set方法)

  3. 把bean实例传递给bean后置处理器 postProcessBeforeInitialization

  4. 调用bean的初始化的方法(需要进行配置初始化的方法)

  5. 把bean实例传递给bean后置处理 postProcessAfterInitialization

  6. bean可以使用了(对象获取到了)

  7. 当容器关闭时候 调用bean的销毁的方法 (需要进行配置销毁的方法) 默认不调用 需要手动销毁bean

//创建后置处理器   实现BeanPostProcessor 接口 并重写方法
public class MyBeanPost implements BeanPostProcessor {
   @Override
   public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
       System.out.println("初始化前");
       return BeanPostProcessor.super.postProcessBeforeInitialization(bean, beanName);
  }

   @Override
   public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
       System.out.println("初始化后");
       return BeanPostProcessor.super.postProcessAfterInitialization(bean, beanName);
  }
}
 <!-- 配置后置处理器  该配置文件里的所有bean都可以使用-->
       <bean id="myBeanPost" class="com.jsoft.entity.MyBeanPost"></bean>

 

IOC操作Bean管理(xml自动装配 autowire)

什么是自动装配

  • 根据指定装配规则,(属性名称或者属性类型),spring自动将匹配的属性值进行注入

    • bean 标签属性 autowire 配置自动注入

    • autowire 属性常用两个值:

      • byName 根据属性名注入 注入的bean的id值和类属性名称一样

      • ByType 根据属性类型注入

<!-- autowire    两种类型(根据名称 根据类型) 配置好文件后他自己回去找名字相同的类或属性-->
<bean id="emp" class="com.jsoft.entity.Emp" autowire="byType/byName">    
     <!-- <property name="dept" ref="dept"></property>-->
</bean>

<bean id="dept" class="com.jsoft.entity.Dept"></bean>

 

IOC操作Bean管理(外部属性文件)

  1. 直接配置数据库信息

    (1) 配置Druid连接池

      <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
           <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
           <property name="url" value="jdbc:mysql://localhost:3306/mhl
                              ?rewriteBatchedStatements=true"></property>
           <property name="username" value="root"></property>
           <property name="password" value="123"></property>
       </bean>

    测试类

     public void test() throws SQLException {
           ClassPathXmlApplicationContext context =
              new ClassPathXmlApplicationContext("bean4.xml");
           DataSource dateSource = (DataSource)context.getBean("dataSource");
           Connection connection = dateSource.getConnection();
           System.out.println(connection);
           connection.close();
      }

     

    (2) 引入Druid连接池依赖Jar包

<?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:p="http://www.springframework.org/schema/p"
      xmlns:util="http://www.springframework.org/schema/util"
      xmlns:context="http://www.springframework.org/schema/context"
      <!--1.引入contest上下文-->
      xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
                          http://www.springframework.org/schema/util https://www.springframework.org/schema/util/spring-util.xsd
                          http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
   
   <!--2.引入外部属性文件 -->
   <context:property-placeholder location="classpath:druid.properties"/>
<!--3.配置数据源-->
   <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
      <property name="driverClassName" value="${druid.driverClassName}"></property>
      <property name="url" value="${druid.url}"></property>
      <property name="username" value="${druid.username}"></property>
      <property name="password" value="${druid.password}"></property>
  </bean>
</beans>

 

基于注解方式实现

IOC操作Bean管理 (基于注解方式)

 

什么是注解?

  • 注解是代码特殊标记 格式:@注解名称(属性名称=属性值,属性名称=属性值...)

  • 使用注解 注解作用在类 方法 属性上面

  • 使用注解的目的? 简化xml文件配置

 

Spring针对Bean管理中创建对象提供注解

(*下面四个注解功能都是一样的 都可以用来创建bean实例)

@Component:可以用于注册所有bean

@Controller:主要用于注册控制层的bean

@Service:主要用于注册服务层的bean

@Repository:主要用于注册dao层的bean

 

Bean管理注解方式(创建对象)

  1. 配置文件

  2. 开启组件扫描

 <!-- 开启组件扫描-->
       <content:component-scan base-package="com.jsoft"></content:component-scan>
  1. 创建类 在类上面添加创建对象注解

//就相当于 <bean id="" class="">
   // 在注解里面value属性值可以省略不写   默认值是类名称 首字母小写

@Component(value = "userService")
public class UserService {
   
   public void add(){
       System.out.println("service add....");
  }
   
}

 

Bean管理注解方式(扫描配置)

use-default-filters 默认为trye 扫描默认路径 false 扫描自定义配置

content:include-filter 设置扫描哪些内容

content:exclude-filter 设置不扫描哪些内容

expression 扫描或不扫描类型

<content:component-scan base-package="com.jsoft" use-default-filters="false">
       <content:include-filter type="annotation"
                               expression="org.springframework.stereotype.Controller"/>
</content:component-scan>

<content:component-scan base-package="com.jsoft">
               <content:exclude-filter type="annotation"
                                expression="org.springframework.stereotype.Controller"/>
       </content:component-scan>

 

Bean管理注解方式(注入属性@Autowired和Qualifier)

  1. @Autowired 根据属性类型自动注入

  2. @Qualifier 根据属性名称自动注入 (需要搭配@Autowired使用)

  3. @Resource 根据引用类型注入 也可以根据名称注入 (它是javax包中的 不属于spring)

  4. @Value 注入普通类型属性

@Service    //注册
public class UserService {

   //定义dao类型属性
   //不需要添加set方法
   //添加注入属性注解
   @Autowired 或     @Resource  
   @Qualifier(value = "userDaoImpl1")   或  @Resource(name = "userDaoImpl1"
   private UserDao userDao;
   
   @Value(value = "二大爷")
   private String name;

   public void add(){
       System.out.println("service add...."+name);
       userDao.add();
  }
}


@Repository(value = "userDaoImpl1")
public class UserDaoImpl implements UserDao{
   @Override
   public void add() {
       System.out.println("aaaaaaa...");
  }
}

 

Bean管理注解方式(完全注解开发)

  1. 创建配置类 代替配置文件

  2. 编写测试类

@Configuration          //作为配置类   代替配置文件xml
@ComponentScan(basePackages = {"com.jsoft"})     //开启组件扫描
public class SpringConfig {
}

@Test
   public void testService(){
       /*ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");*/

       ApplicationContext context =
          new AnnotationConfigApplicationContext(SpringConfig.class);//读取配置类
       
       UserService userService = context.getBean("userService", UserService.class);
       userService.add();
  }

测试类

public class UserTest {
   @Test
   public void testService(){
       /*ApplicationContext context = new ClassPathXmlApplicationContext("bean1.xml");*/

       ApplicationContext context =
            new AnnotationConfigApplicationContext(SpringConfig.class);
       UserService userService = context.getBean("userService", UserService.class);
       userService.add();
  }
}

 

AOP

  • 面向切面编程 主要用来解决一些系统层面上的问题 比如日志 事务 权限

  • 在不改变原有逻辑的基础上 增加一些额外的功能

  • AOP是OOP(面向对象)的补充和完善

  • AOP横切技术 剖解开对象的内部 把一些和业务无关 却可以为业务共同的调用的逻辑封装起来 减少重复代码的使用

 

底层原理

AOP底层动态代理

  • 有接口情况 使用JDK动态代理

    创建一个该接口实现类的代理对象 增强类的方法

    public class JDKProxy {
    @Test
       public void test(){

           //创建接口实现类代理对象
           Class[] interfaces = {UserDao.class};

           UserDaoImpl userDao = new UserDaoImpl();
           Object o = Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
           UserDao dao = (UserDao) o;
           int res = dao.add(1, 2);
           System.out.println("result:"+res);
      }
    }

    //创建代理对象代码
    class UserDaoProxy implements InvocationHandler{

       //把创建的是谁的对象,把谁传递过来
       //有参构造器
       private Object obj;
       public UserDaoProxy(Object obj){
           this.obj=obj;
      }


       @Override
       public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
           //方法之前
           System.out.println("方法之前执行。。。"+method.getName()+" 传递的参数为:"+ Arrays.toString(args));

           //被增强的方法执行
           Object res = method.invoke(obj, args);

           //方法之后
           System.out.println("方法之后执行。。。"+obj);

           return res;
      }
    }

     

  • 没有接口情况 使用CGLIB动态代理

    创建当前子类的代理对象 增强类的方法

 

AOP动态代理

使用JDK动态代理 使用Proxy类里面的方法 newProxyInstance 创建代理对象

该方法有三个参数:

第一个参数 类加载器

第二个参数 增强方法的所在的类 这个类实现的接口 支持多接口

第三个参数 实现这个接口InvocationHandler 创建代理对象 写增强的方法

public class JDKProxy {
@Test
   public void test(){

       //创建接口实现类代理对象
       Class[] interfaces = {UserDao.class};

       UserDaoImpl userDao = new UserDaoImpl();
       Object o = Proxy.newProxyInstance(JDKProxy.class.getClassLoader(), interfaces, new UserDaoProxy(userDao));
       UserDao dao = (UserDao) o;
       int res = dao.add(1, 2);
       System.out.println("result:"+res);
  }
}

//创建代理对象代码
class UserDaoProxy implements InvocationHandler{

   //把创建的是谁的对象,把谁传递过来
   //有参构造器
   private Object obj;
   public UserDaoProxy(Object obj){
       this.obj=obj;
  }


   @Override
   public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
       //方法之前
       System.out.println("方法之前执行。。。"+method.getName()+" 传递的参数为:"+ Arrays.toString(args));

       //被增强的方法执行
       Object res = method.invoke(obj, args);

       //方法之后
       System.out.println("方法之后执行。。。"+obj);

       return res;
  }
}


//接口实现类
public class UserDaoImpl implements UserDao{
   @Override
   public int add(int a, int b) {
       return a+b;
  }

   @Override
   public String update(String id) {
       return id;

  }
}

//接口
public interface UserDao {

   public int add(int a,int b );

   public String update(String id);
}

 

AOP(术语)

通知(增强)

实际被增强的逻辑部分就称为通知(增强)

  • 通知有多种类型

    • 前置通知 @Before 方法执行前执行

    • 后置通知 @AfterReturning 方法执行后执行

    • 环绕通知 @Around 方法执行前后后都执行(优先级最高)

    • 异常通知 @AfterThrowing 方法发生异常时执行

    • 最终通知 @After 方法无论发生什么都执行(类似finally)

连接点

类里面哪些方法可以被增强,这些方法就被称为连接点

切入点

实际被增强的方法 就称为切入点

切面

把通知应用到切入点的过程就是切面 是一个动作

织入

被通知的对象 真正的业务逻辑 可以毫不知情。两者互相之间可能并不知情 专注于自己该做的事

 

AOP操作(准备)

Spring框架一般都是基于AspectJ实现AOP操作

什么是AspectJ?

AspectJ不是Spring组成部分 独立AOP框架 一般把AspectJ和Spring框架一起使用,进行AOP操作

 

基于AspectJ实现AOP操作

切入点表达式

切入点表达式作用 知道对哪个类里面的哪个方法进行增强

语法结构 execution ( [权限修饰符] [返回类型] [类全路径] [方法名称] ([参数列表]) )

例: 对com.jsoft.dao.BookDao 类里面的add进行增强 execution(* com.jsoft.dao.BookDao.add(...))

对com.jsoft.dao.BookDao类里面的所有的方法进行增强 execution(* com.jsoft.dao.BookDao.*(...))

对com.jsoft.dao 包里面的所有类 所有方法进行增强 execution(*com.jsoft.dao. *. * (...))

 

AOP操作(基于AspectJ注解方式)

步骤:

(1)创建类 在类里面定义方法

public class User {
   public void add(){
       System.out.println("add...");
  }
}

(2)创建增强类(编写增强逻辑)

public class UserProxy {
   public void before(){
       System.out.println("before...");
  }
}

(3)进行通知的配置

(3.1)在Spring配置文件中 开启注解扫描

 <context:component-scan base-package="com.aop"></context:component-scan>

(3.2)使用注解创建User和UserProxy对象

@Component
public class UserProxy {
   public void before(){
       System.out.println("before...");
  }
}

@Component
public class User {
   public void add(){
       System.out.println("add...");
  }
}

(3.3)在增强类上面添加注解@Aspect( 切面声明)

@Component
@Aspect
public class UserProxy {
   public void before(){
       System.out.println("before...");
  }
}

 

(3.4)在Spring配置文件中开启生成代理对象

<!--开启AspectJ生成代理对象-->
       <aop:aspectj-autoproxy></aop:aspectj-autoproxy>

(4)配置不同类型的通知

//在方法名前  加@Before修饰符
@Before(value = "execution(* com.aop.User.add(..))")
   public void before(){
       System.out.println("before...");
  }

@After(value = "execution(* com.aop.User.add(..))")
   public void after(){
       System.out.println("after...");
  }

@AfterThrowing(value = "execution(* com.aop.User.add(..))")
   public void exception(){
       System.out.println("exception...");
  }

@Around(value = "execution(* com.aop.User.add(..))")
   public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
       System.out.println("aaa....");
       proceedingJoinPoint.proceed();
       System.out.println("bbb...");
  }

@AfterReturning(value = "execution(* com.aop.User.add(..))")
   public void afterReturning(){
       System.out.println("adasdasd.....");
  }

 

公共切入点抽取

对于重复调用的切入点 抽取出来

 //创建切入点方法point
@Pointcut(value = "execution(* com.aop.User.add(..))")
   public void point(){
  }

//直接在注释里面调用配置了切入点的方法point
   @Before(value = "point()")
   public void before(){
       System.out.println("before...");
  }

 

增强类优先级

有多个增强类同时增强一个方法 可以设置增强类优先级

@Component
@Aspect
public class PersonProxy {

   @Before(value = "execution(* com.aop.User.add(..))")
   @Order(0) //两个通知同时增强一个方法 可以使用@Order进行优先级排序(数字越小优先级高)
   public void personBefore(){
       System.out.println("aaaaaa。。。");
  }
}

 

 

AOP操作(基于AspectJ配置文件)

操作步骤:

1.创建两个类 增强类和被增强类 创建方法

public class Animal {
   public void eat(){
       System.out.println("一顿八碗米。。。");
  }
}

public class AnimalProxy {
   public void eatPro(){
       System.out.println("一顿吃十碗。。。");
  }
}

2.在spring 配置文件中创建两个类对象

<bean id="animal" class="com.aop1.Animal"></bean>
<bean id="animalProxy" class="com.aop1.AnimalProxy"></bean>

3.在spring配置文件中配置切入点

   <!--配置aop增强-->
       <aop:config>
               <!--声明切入点-->
               <aop:pointcut id="p" expression="execution(* com.aop1.Animal.eat(..))"/>
               <!--配置切面-->
               <aop:aspect ref="animalProxy">
                       <!--配置作用在具体方法上-->
                       <aop:before method="eatPro" pointcut-ref="p"/>
               </aop:aspect>
       </aop:config>

测试类

public class Test {
   @org.junit.Test
   public void test(){
       ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("aop1.xml");
       Animal animal = context.getBean("animal", Animal.class);
       animal.eat();
  }
}

完全使用注解开发

1.创建配置类

@Configuration
@ComponentScan(basePackages = {"com.aop1"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class ConfigAop {
}

2.创建增强类和被增强类并注入ioc容器中

@Component
public class Animal {
   public void eat(){
       System.out.println("一顿八碗米。。。");
  }
}

@Component
@Aspect //切面声明
public class AnimalProxy {

   @Before(value = "execution(* com.aop1.Animal.eat(..))")
   public void eatPro(){
       System.out.println("一顿吃十碗。。。");
  }
}

 

 

JdbcTemplate(暂定)

 

 

Spring事务的7种传播行为

  1. required 如果当前没有事务 新建一个事务 如果有 就加入这个事务

  2. supports 支持当前的事务 如果没有事务 就以非事务的方法运行

  3. mandatory 使用当前的事务 如果没有事务 就抛异常

  4. requires_new 新建事务 如果当前存在事务 就把当前事务挂起

  5. not_supported 以非事务刚发执行 如果有事务 当没事务执行

  6. never 如果没有事务 正常运行 如果有事务 就抛异常

  7. nested 如果存在事务 嵌套事务内执行 如果没有事务 则创建事务

posted @ 2022-10-11 11:33  李哈哈lyh  阅读(178)  评论(0)    收藏  举报