Spring知识点

Spring基本配置

1、导入对应jar包:
官方文档:
The org.springframework.beans and org.springframework.context packages 
are the basis for Spring Framework’s IoC container.

我这里是使用的Maven管理项目。实际上这两个包还依赖以下几个包:
spring-aop、spring-core、spring-expression、spring-jcl
maven会帮我们自动导入。
<dependency>
	 <groupId>org.springframework</groupId>
	 <artifactId>spring-beans</artifactId>
	 <version>5.2.0.RELEASE</version>
</dependency>
<dependency>
	  <groupId>org.springframework</groupId>
	  <artifactId>spring-context</artifactId>
	  <version>5.2.0.RELEASE</version>
</dependency>
2、编写配置文件
很多人不知道基础的xml配置文件哪里找。
实际上在官方文档里就一节专门写了几种[SpringXMLSchema](https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#appendix)。
这里我们进行最基础的配置,使用“10.1.4. The Beans Schema”中的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 https://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean  id="person1" name="person1" class="beans.Person">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>
</beans>
3、进行测试
ClassPath指向target/classes/下。
 ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
 Person person1 = (Person) context.getBean("person1");
 System.out.println(person1);

Spring基础知识

Bean的id和name的区别

配置一个bean的时候,我们可以不设置id,也可以不设置name,spring默认会使用类的全限定名作为bean的标识符。
id和name都必须唯一。
只有id或name时,id/name就是Bean的标识符。
既有id又有name时,name相当于Bean的别名。
name可以写多个值,id只能写一个值。
name属性设置多个值。不设置id,那么第一个被用作标识符,其他的被视为别名。如果设置了id,那么name的所有值都是别名。

为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"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
	<bean  id="person1" name="person1" class="beans.Person">
        <!-- additional collaborators and configuration for this bean go here -->
    </bean>
    <alias name="person1" alias="p1"/>
</beans>
 ApplicationContext context = new ClassPathXmlApplicationContext("application.xml");
 Person person1 = (Person) context.getBean("p1");//p1是person1的别名
 System.out.println(person1);

三种组装Bean的方式

若无任何配置,Spring容器会使用无参的构造函数进行实例化Bean。

1、构造器注入(根据设置的参数,调用不同的构造函数,没有符合的构造函数时,配置文件就会报错)。
<!--构造器注入-->
    <bean  name="person-constructor" class="beans.Person">
        <constructor-arg name="age" value="20"/>
        <constructor-arg name="name" value="Mark"/>
        <constructor-arg name="nation" value="China"/>
    </bean>
2、静态工厂注入。
<!--静态工厂注入-->
<!--factory-method指明由哪个方法实例化-->
   <bean  name="person-static-factory" class="beans.Person" factory-method="factory">
   </bean>
//该方法要写在Person类中
public static Person factory() {
    return new Person("Mark", 18, "China");
}
3、实例工厂注入。
<!--实例工厂注入-->
<!--工厂bean-->
<bean id="InstancingFactory" class="beans.PersonFactory"/>
<!--待实例化bean-->
<bean name="person-instancing-factory" class="beans.Person" factory-bean="InstancingFactory" factory-method="InstancingPerson"/>
//实例工厂
public class PersonFactory {
    public Person InstancingPerson(){
        return new Person("a",18,"b");
    }
}

依赖注入

如下代码所示,Circle类依赖Point类。
public class Circle {
    private Point center;
    private Float radius;
}
如何向Circle类注入Point类?

1、基于构造器的依赖注入。编写带有Point参数的构造函数,实例化时就可以注入。
	<!--构造器依赖注入(本质上就是实例化复合bean)-->
    <bean name="circle-constructor-DI" class="beans.Circle">
        <constructor-arg name="center" ref="center"/>
        <constructor-arg name="radius" value="18.5"/>
    </bean>
    <bean id="center" name="center" class="beans.Point"/>
2、基于set方法的依赖注入。编写center的set方法。
	<!--set方法依赖注入-->
    <bean name="circle-set-DI" class="beans.Circle">
        <property name="center" ref="center"/>
        <property name="radius" value="16.5"/>
    </bean>
注意流程:想要使用类的set方法,该类首先得实例化。
set注入属性可以和组装bean一起使用。先组装bean后使用set方法。
若类没有提供对应的set方法,那么配置文件就会报错。

set注入集合示例

<bean id="moreComplexObject" class="example.ComplexObject">
    <!-- results in a setAdminEmails(java.util.Properties) call -->
    <property name="adminEmails">
        <props>
            <prop key="administrator">administrator@example.org</prop>
            <prop key="support">support@example.org</prop>
            <prop key="development">development@example.org</prop>
        </props>
    </property>
    <!-- results in a setSomeList(java.util.List) call -->
    <property name="someList">
        <list>
            <value>a list element followed by a reference</value>
            <ref bean="myDataSource" />
        </list>
    </property>
    <!-- results in a setSomeMap(java.util.Map) call -->
    <property name="someMap">
        <map>
            <entry key="an entry" value="just some string"/>
            <entry key ="a ref" value-ref="myDataSource"/>
        </map>
    </property>
    <!-- results in a setSomeSet(java.util.Set) call -->
    <property name="someSet">
        <set>
            <value>just some string</value>
            <ref bean="myDataSource" />
        </set>
    </property>
</bean>

设置空字符串和null值

 <bean class="ExampleBean">
    <property name="email" value=""/>
 </bean>
 等同于:exampleBean.setEmail("");
 
 <bean class="ExampleBean">
     <property name="email">
          <null/>
      </property>
 </bean>
 等同于:exampleBean.setEmail(null);

depends-on

<bean id="beanOne" class="ExampleBean" depends-on="manager"/>
<bean id="manager" class="ManagerBean" />
确保manager在beanOne实例化之前被实例化。

lazy-init

<bean id="lazy" class="com.something.ExpensiveToCreateBean" lazy-init="true"/>
确保在第一次使用该bean时,才实例化
 
 <beans default-lazy-init="true">
     <!-- no beans will be pre-instantiated... -->
 </beans>
 为全局添加lazy-init属性

Scope

1、singleton(默认)
   <bean id="accountService" class="com.something.DefaultAccountService" scope="singleton"/>
   spring容器只会创建一个实例对象。

2、prototype
   <bean id="accountService" class="com.something.DefaultAccountService" scope="prototype"/>
   每次引用都会创建一个新对象。
3、request
4、session
5、application
6、websocket
后四种详细介绍请看官网:
https://docs.spring.io/spring-framework/docs/current/reference/html/core.html#beans-factory-scopes

初始化和销毁函数

 自定义初始化和销毁函数
 <bean id="exampleInitBean" class="examples.ExampleBean" init-method="init"/>
 	init-method = "函数方法名"指定函数名称
 <bean id="exampleInitBean" class="examples.ExampleBean" destroy-method="cleanup"/>
 
 实现初始化和销毁函数的方式不只这一种,
 还可以通过实现特定接口:The InitializingBean and DisposableBean callback interfaces
 和注解的方法:The @PostConstruct and @PreDestroy annotations.
 来实现
 注意:这三种方法设定的函数互不影响,会按指定的顺序执行:Combining Lifecycle Mechanisms(该标题下有详细的顺序)
     
 同时可以对整个容器的bean设置
 <beans default-init-method="init">

Bean的继承

Bean定义的继承
child会继承parent的属性(除开: depends on, autowire mode, dependency check, singleton, and lazy init.)
同一属性会覆盖
 	<!--Bean Definition inherent-->
    <bean name="parent-person" class="beans.Person">
        <property name="age" value="18"/>
        <property name="name" value="aaa"/>
    </bean>

    <bean name="child-person" class="beans.Person" parent="parent-person">
        <property name="age" value="25"/>
        <property name="nation" value="China"/>
    </bean>

使用注解配置Bean

使用新配置文件

10.1.3. The context Schema
<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
        https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

    <!--<context:annotation-config/>-->
    <!--根据官方文档,该配置能隐式启动上面的开启注解驱动配置,所以只需要这一个即可-->
    <context:component-scan base-package="beans"/>
</beans>

Spring整合Junit单元测试

1、添加jar。
 <!--开启测试-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test</artifactId>
            <version> 5.1.5.RELEASE</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.13-beta-2</version>
            <scope>compile</scope>
        </dependency>
2、编写测试方法
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application-annotation.xml"})
public class TestAnnotation {
    /**
     * @Autowired
     * 自动装配
     * @Qualifier
     * 当配置文件中有多个同类型的Bean时,可加上Qualifier标签,唯一标志一个bean
     * 同时在要自动注入的bean上加上@Qualifier注解,表明要导入那个bean
     */
    @Autowired
    @Qualifier("bread")
    private Food food;

    @Test
    public void test2(){
        System.out.println(food);
    }
}
后续测试都在整合了的单元测试中进行。

@Autowired和@Qualifier

<!--注册Food为Bean-->
<bean name="bread" class="beans.Food">
     <property name="name" value="面包"/>
     <property name="price" value="18.5"/>
     <qualifier value="breadA"/>
 </bean>
	/**
     * @Autowired
     * 自动装配,根据类型匹配。当有多个同类型的Bean时,需加上@Qualifier指定要装配的Bean的name。
     * Autowired在有多个同类型bean存在时,默认匹配与当前变量名同名的bean,没有或者有多个则需要
     * Quanlifier注解
     * 
     * @Qualifier
     * 当配置文件中有多个同类型的Bean时,可加上Qualifier标签,唯一标志一个bean
     * 同时在要自动注入的bean上加上@Qualifier注解,表明要导入那个bean
     */
    @Autowired
    @Qualifier("breadA")
    private Food food;
@Autowired还可以加在set方法和构造器上

@Autowired
Person  jack
等同于
@Autowired
@Quanlifer("jack")
Person  XXX
@Autowired
public void setAnimal(Animal animal){
	this.animal = animal;
}

public BussinessPerson(@Autowired @Qualifier("dog") Animal animal){
	this.animal = animal;
}

@Primary

@Component
@Primary
public class Cat implements Animal {
    @Override
    public void name() {
        System.out.println("cat");
    }
}
@Component()
public class Dog implements Animal{
    @Override
    public void name() {
        System.out.println("dog");
    }
}
	/**
     * Dog和Cat都实现了Animal接口并且使用注解注册为bean
     * 在当前情况下除了使用@Qualifier进行指定还可以使用@Primary
     * Spring会加载使用了@Primary注解的类
     * 本例中会加载Cat类
     */
    @Autowired
    private Animal animal;

@Resource

<bean name="coke" class="beans.Food">
    <property name="name" value="可乐"/>
    <property name="price" value="2.5"/>
 </bean>
 	/**
     * @Resource(name="beanName")
     * 功能与Autowired一致,按照beanName进行自动注入
     * 若不指定name属性,则会根据变量名进行匹配
     */
    @Resource(name = "coke")
    private Food cokeByName;
    @Resource
    private Food coke;

@PostConstruct和@PreDestroy

    /**
     * @PostConstruct
     * 定义初始化方法
     * @PreDestroy
     * 定义销毁方法
     */
	@PostConstruct
    public void init(){
        System.out.println("init:"+this.name);
    }

    @PreDestroy
    public void destroy(){
        System.out.println("destroy:"+this.name);
    }

@Repository、@Service、@Component、@Controller

需要开启包扫描

    /**
     * 通过注解注册Bean
     * @Repository
     * @Service
     * @Component
     * @Controller
     * 这四个注解功能是一样的
     * 
     * @Component("name")可以指定装配Bean的name,如果不指定,则会使用类名首字母小写作为name
     * 
     * 必须先开启包扫描(可通过XML或者配置类的形式开启)
     * Spring才会主动扫描包下添加了注解的类
     *
     * 想要使用注解,必须开启注解驱动
     * 想要使用注解注册Bean必须配置包扫描
     *
     * 包扫描的配置隐式启动了注解驱动配置,所以只配置这一个即可(配置了包扫描就无需显式开启注解驱动)
     * There is usually no need to include the <context:annotation-config> element when using <context:component-scan>.
     */
    @Autowired
    private MyDao myDao1;
    @Autowired
    private MyDao myDao2;
	@Repository
	public class MyDao {
	}

@Scope

可以配置Bean的单例和多例模式(实际上Scope的属性不止这几种)
@Scope("prototype")
@Scope("singleton")
加在类上即可。
@Scope("prototype")
public class MyDao {
}

SpringAOP

基本概念

在这里插入图片描述
连接点:可以被切入方法的点。
切入点:已经被切入了方法的点。
通知:指切入的方法。分为前置、后置、等通知。
切面:切入点和通知的结合。
织入:指把通知应用到目标对象创建代理对象的过程

简单来讲,通知是要对原始类进行强化的方法,切点是决定通知加在那里,而切面正是包含了通知和切点。
切面表现为一个类,类中配置了切点,和通知(通知表现为类方法)。

执行顺序

在这里插入图片描述

注意

只有被当作bean注入的类的方法,才会被aop织入
单纯new一个类执行方法不会得到预期的结果

配置

1、引入jar包。
     <dependency>
          <groupId>org.aspectj</groupId>
          <artifactId>aspectjweaver</artifactId>
          <version>1.9.2</version>
      </dependency>
2、配置文件。
<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd 
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

        <aop:aspectj-autoproxy/>
        <context:component-scan base-package="aop"/>
</beans>

采用注解方式配置

@Service
public class MyService {
    public void doServiceWork(String param){
        System.out.println("service进行业务逻辑操作");
    }
}
@Component
@Aspect   //声明切面
@Order(1) //存在多个切面时,指定切面执行的顺序
public class ServiceExecutor {
	//execution表达式可参照 Declaring a PointCut中的Example章节
	@Pointcut("execution(* aop.MyService.*(..))")
    public void myPointcut(){}

    //一种是写切入点,由切入点找到要切入的方法
    @Before("myPointcut()")
    public void beforeMyPointcut(){
        System.out.println("beforeMyPointcut");
    }
    
	//一种是写要切入的方法
	// joinPoint可以获取代理对象方法的各种信息,包括参数
	// args()可以将代理方法的对应参数传入通知中
    @Before("execution(* aop.MyService.*(..)) && args(param)")
    public void before(JoinPoint joinPoint,String param){
        System.out.println("前置通知,方法调用前执行");
    }

    @AfterReturning("execution(* aop.MyService.*(..))")
    public void afterReturning() {
        System.out.println("后置通知,返回后调用,遇到异常时不调用");
    }

    @AfterReturning(value="execution(* aop.MyService.*(..))", returning="retVal")
    public void afterReturningWithReturn(Object retVal) {//可以获取返回对象
        System.out.println("后置通知,该方法返回值是:"+retVal);
    }

    @AfterThrowing("execution(* aop.MyService.*(..))")
    public void afterThrowing() {
        System.out.println("方法发生异常时被执行");
    }

    @AfterThrowing(value="execution(* aop.MyService.*(..))",throwing="ex")
    public void afterThrowingWithEx(Exception ex) {//异常通知可以获取异常
        System.out.println("异常通知:"+ex.getMessage());
        ex.printStackTrace();
    }

    @After("execution(* aop.MyService.*(..))")
    public void after() {
        System.out.println("最终通知,方法返回后执行,无论是否发生异常都会执行");
    }


    /**
     * ProceedingJoinPoint pjp
     * 可以获取更多目标对象执行的方法的信息
     * getThis(): Returns the proxy object.
     * getArgs(): Returns the method arguments.
     * getTarget(): Returns the target object.
     * getSignature(): Returns a description of the method that is being advised.
     * toString(): Prints a useful description of the method being advised.
     */
    @Around("execution(* aop.MyService.*(..))")
    public Object around(ProceedingJoinPoint pjp) throws Throwable {
        System.out.println("环绕通知,方法开始前");
        Object retVal = pjp.proceed(); //retVal是目标对象执行方法返回的结果
        System.out.println("环绕通知,方法返回后");
        return retVal;
    }
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {"classpath:application-aspect.xml"})
public class TestAOP {

	/**
	*只有被当作bean注入的类的方法,才会被aop织入
	*单纯new一个service执行操作不会得到预期的结果
	*/
    @Autowired
    private MyService service;

    @Test
    public void test1(){
        service.doServiceWork();
    }
}

采用XML方式配置

//定义切面类,里面的方法为通知
public class ServiceExecutorXML {

    public void before(){
        System.out.println("this is xml before");
    }
}
在配置文件中配置切面
<?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"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <aop:aspectj-autoproxy/>
    <context:component-scan base-package="aop"/>

    <!--基于XML编写切面-->
    <!--将切面注册为bean-->
    <bean id="serviceExecutorXML" class="aop.ServiceExecutorXML"/>
    <!--aop配置结点-->
    <aop:config>
        <!--配置切面-->
        <aop:aspect id="aspect" ref="serviceExecutorXML">
            <!--定义切点-->
            <aop:pointcut id="p1" expression="execution(* aop.MyService.*(..))"/>
            <!--编写通知-->
            <aop:before method="before" pointcut-ref="p1"/>
        </aop:aspect>
    </aop:config>
</beans>

配置事务

针对Service层进行事务管理。
事务只针对范围(由execution表达式确定)里的方法起作用,一个方法里的行为要么全都成功要么全都失败。
所以一套完整的业务流程要写在一个方法中。

XML方式配置

1、导入jar包。
		<!--配置事务-->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.1.20.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.2.0.RELEASE</version>
        </dependency>
        <!-- 数据库连接池 -->
        <dependency>
            <groupId>com.mchange</groupId>
            <artifactId>c3p0</artifactId>
            <version>0.9.5</version>
        </dependency>
2、事务管理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"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        https://www.springframework.org/schema/beans/spring-beans.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
        http://www.springframework.org/schema/context
        https://www.springframework.org/schema/context/spring-context.xsd">

        <!--配置事务的schema,需要导入spring-tx.jar-->

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

        <!--通知-->
        <tx:advice id="txAdvice" transaction-manager="transactionManager">
             <tx:attributes>
                <!--REQUIRED:支持当前事务,如果不存在则新建,用于增删改业务-->
                <!--SUPPORTS:支持当前事务,如果不存在,不新建,用于查询业务-->
                <!--name:要添加事务的方法名,可以有通配符-->
                <tx:method name="doServiceWork" propagation="REQUIRED"/>
                <tx:method name="select*" propagation="SUPPORTS" read-only="true"/>
                <tx:method name="update*" propagation="REQUIRED"/>
                <tx:method name="insert*" propagation="REQUIRED"/>
                <tx:method name="delete*" propagation="REQUIRED"/>
            </tx:attributes>
        </tx:advice>

        <!--切面(将通知织入切入点)-->
        <aop:config>
            <!--切入点-->
            <aop:pointcut id="MyServiceTXPointCut" expression="execution(* aop.MyService.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="MyServiceTXPointCut"/>
        </aop:config>

        <!--引入外部properties文件-->
        <context:property-placeholder location="classpath:db.properties"/>
        <!--配置数据源-->
        <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="jdbcUrl" value="${jdbc.url}"/>
            <property name="driverClass" value="${jdbc.driver}"/>
            <property name="user" value="${jdbc.username}"/>
            <property name="password" value="${jdbc.password}"/>
            <!--还可以通过property配置更多属性,如最大连接数-->
        </bean>
</beans>
可以看见Spring事务管理使用了AOP(XML配置形式)。

注解形式(很少使用)

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

    <!--配置事务的schema,需要导入spring-tx.jar-->

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

    <!--开启注解事务管理-->
    <tx:annotation-driven/>

    <!--引入外部properties文件-->
    <context:property-placeholder location="classpath:db.properties"/>
    <!--配置数据源-->
    <bean name="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="jdbcUrl" value="${jdbc.url}"/>
        <property name="driverClass" value="${jdbc.driver}"/>
        <property name="user" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
        <!--还可以通过property配置更多属性,如最大连接数-->
    </bean>
</beans>
2、为Service层类或方法添加注解。
@Service
//为类中方法添加事务
@Transactional
public class MyService {
	//为单个方法添加事务
    @Transactional(propagation = Propagation.REQUIRED)
    public String doServiceWork(){
        System.out.println("service进行业务逻辑操作");
        return "SUCCESS";
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值