l 在軟件業,AOP爲Aspect Oriented Programming的縮寫,意爲:面向切面編程,經過預編譯方式和運行期動態代理實現程序功能的統一維護的一種技術。AOP是OOP(面向對象編程)的延續,是軟件開發中的一個熱點,也是Spring框架中的一個重要內容,是函數式編程的一種衍生範型。利用AOP能夠對業務邏輯的各個部分進行隔離,從而使得業務邏輯各部分之間的耦合度下降,提升程序的可重用性,同時提升了開發的效率。java
l AOP採起橫向抽取機制,取代了傳統縱向繼承體系重複性代碼mysql
l 經典應用:事務管理、性能監視、安全檢查、緩存 、日誌等spring
l Spring AOP使用純Java實現,不須要專門的編譯過程和類加載器,在運行期經過代理方式向目標類織入加強代碼sql
l AspectJ是一個基於Java語言的AOP框架,Spring2.0開始,Spring AOP引入對Aspect的支持,AspectJ擴展了Java語言,提供了一個專門的編譯器,在編譯時提供橫向代碼的織入express
l aop底層將採用代理機制進行實現。apache
l 接口 + 實現類 :spring採用 jdk 的動態代理Proxy。編程
l 實現類:spring 採用 cglib字節碼加強。設計模式
1.target:目標類,須要被代理的類。例如:UserServiceapi
2.Joinpoint(鏈接點):所謂鏈接點是指那些可能被攔截到的方法。例如:全部的方法緩存
3.PointCut 切入點:已經被加強的鏈接點。例如:addUser()
4.advice 通知/加強,加強代碼。例如:after、before
5. Weaving(織入):是指把加強advice應用到目標對象target來建立新的代理對象proxy的過程.
6.proxy 代理類
7. Aspect(切面): 是切入點pointcut和通知advice的結合
一個線是一個特殊的面。
一個切入點和一個通知,組成成一個特殊的面。
l JDK動態代理 對「裝飾者」設計模式 簡化。使用前提:必須有接口
1.目標類:接口 + 實現類
2.切面類:用於存通知 MyAspect
3.工廠類:編寫工廠生成代理
4.測試
public interface UserService {
public void addUser(); public void updateUser(); public void deleteUser();
} |
public class MyAspect {
public void before(){ System.out.println("雞首"); }
public void after(){ System.out.println("牛後"); }
}
|
public class MyBeanFactory {
public static UserService createService(){ //1 目標類 final UserService userService = new UserServiceImpl(); //2切面類 final MyAspect myAspect = new MyAspect(); /* 3 代理類:將目標類(切入點)和 切面類(通知) 結合 --> 切面 * Proxy.newProxyInstance * 參數1:loader ,類加載器,動態代理類 運行時建立,任何類都須要類加載器將其加載到內存。 * 通常狀況:當前類.class.getClassLoader(); * 目標類實例.getClass().get... * 參數2:Class[] interfaces 代理類須要實現的全部接口 * 方式1:目標類實例.getClass().getInterfaces() ;注意:只能得到本身接口,不能得到父元素接口 * 方式2:new Class[]{UserService.class} * 例如:jdbc 驅動 --> DriverManager 得到接口 Connection * 參數3:InvocationHandler 處理類,接口,必須進行實現類,通常採用匿名內部 * 提供 invoke 方法,代理類的每個方法執行時,都將調用一次invoke * 參數31:Object proxy :代理對象 * 參數32:Method method : 代理對象當前執行的方法的描述對象(反射) * 執行方法名:method.getName() * 執行方法:method.invoke(對象,實際參數) * 參數33:Object[] args :方法實際參數 * */ UserService proxService = (UserService)Proxy.newProxyInstance( MyBeanFactory.class.getClassLoader(), userService.getClass().getInterfaces(), new InvocationHandler() {
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//前執行 myAspect.before();
//執行目標類的方法 Object obj = method.invoke(userService, args);
//後執行 myAspect.after();
return obj; } });
return proxService; }
} |
@Test public void demo01(){ UserService userService = MyBeanFactory.createService(); userService.addUser(); userService.updateUser(); userService.deleteUser(); } |
l 沒有接口,只有實現類。
l 採用字節碼加強框架 cglib,在運行時 建立目標類的子類,從而對目標類進行加強。
l 導入jar包:
本身導包(瞭解):
核心:hibernate-distribution-3.6.10.Final\lib\bytecode\cglib\cglib-2.2.jar
依賴:struts-2.3.15.3\apps\struts2-blank\WEB-INF\lib\asm-3.3.jar
spring-core..jar 已經整合以上兩個內容
public class MyBeanFactory {
public static UserServiceImpl createService(){ //1 目標類 final UserServiceImpl userService = new UserServiceImpl(); //2切面類 final MyAspect myAspect = new MyAspect(); // 3.代理類 ,採用cglib,底層建立目標類的子類 //3.1 核心類 Enhancer enhancer = new Enhancer(); //3.2 肯定父類 enhancer.setSuperclass(userService.getClass()); /* 3.3 設置回調函數 , MethodInterceptor接口 等效 jdk InvocationHandler接口 * intercept() 等效 jdk invoke() * 參數1、參數2、參數3:以invoke同樣 * 參數4:methodProxy 方法的代理 * * */ enhancer.setCallback(new MethodInterceptor(){
@Override public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
//前 myAspect.before();
//執行目標類的方法 Object obj = method.invoke(userService, args); // * 執行代理類的父類 ,執行目標類 (目標類和代理類 父子關係) methodProxy.invokeSuper(proxy, args);
//後 myAspect.after();
return obj; } }); //3.4 建立代理 UserServiceImpl proxService = (UserServiceImpl) enhancer.create();
return proxService; }
} |
l AOP聯盟爲通知Advice定義了org.aopalliance.aop.Advice l Spring按照通知Advice在目標類方法的鏈接點位置,能夠分爲5類
|
環繞通知,必須手動執行目標方法 try{ //前置通知 //執行目標方法 //後置通知 } catch(){ //拋出異常通知 } |
l 讓spring 建立代理對象,從spring容器中手動的獲取代理對象。
l 導入jar包:
核心:4+1
AOP:AOP聯盟(規範)、spring-aop (實現)
public interface UserService {
public void addUser(); public void updateUser(); public void deleteUser();
} |
/** * 切面類中肯定通知,須要實現不一樣接口,接口就是規範,從而就肯定方法名稱。 * * 採用「環繞通知」 MethodInterceptor * */ public class MyAspect implements MethodInterceptor {
@Override public Object invoke(MethodInvocation mi) throws Throwable {
System.out.println("前3");
//手動執行目標方法 Object obj = mi.proceed();
System.out.println("後3"); return obj; } } |
<!-- 1 建立目標類 --> <bean id="userServiceId" class="com.itheima.b_factory_bean.UserServiceImpl"></bean> <!-- 2 建立切面類 --> <bean id="myAspectId" class="com.itheima.b_factory_bean.MyAspect"></bean>
<!-- 3 建立代理類 * 使用工廠bean FactoryBean ,底層調用 getObject() 返回特殊bean * ProxyFactoryBean 用於建立代理工廠bean,生成特殊代理對象 interfaces : 肯定接口們 經過<array>能夠設置多個值 只有一個值時,value="" target : 肯定目標類 interceptorNames : 通知 切面類的名稱,類型String[],若是設置一個值 value="" optimize :強制使用cglib <property name="optimize" value="true"></property> 底層機制 若是目標類有接口,採用jdk動態代理 若是沒有接口,採用cglib 字節碼加強 若是聲明 optimize = true ,不管是否有接口,都採用cglib
--> <bean id="proxyServiceId" class="org.springframework.aop.framework.ProxyFactoryBean"> <property name="interfaces" value="com.itheima.b_factory_bean.UserService"></property> <property name="target" ref="userServiceId"></property> <property name="interceptorNames" value="myAspectId"></property> </bean> |
@Test public void demo01(){ String xmlPath = "com/itheima/b_factory_bean/beans.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
//得到代理類 UserService userService = (UserService) applicationContext.getBean("proxyServiceId"); userService.addUser(); userService.updateUser(); userService.deleteUser(); } |
l 從spring容器得到目標類,若是配置aop,spring將自動生成代理。
l 要肯定目標類,aspectj 切入點表達式,導入jar包
spring-framework-3.0.2.RELEASE-dependencies\org.aspectj\com.springsource.org.aspectj.weaver\1.6.8.RELEASE
<?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"> <!-- 1 建立目標類 --> <bean id="userServiceId" class="com.itheima.c_spring_aop.UserServiceImpl"></bean> <!-- 2 建立切面類(通知) --> <bean id="myAspectId" class="com.itheima.c_spring_aop.MyAspect"></bean> <!-- 3 aop編程 3.1 導入命名空間 3.2 使用 <aop:config>進行配置 proxy-target-class="true" 聲明時使用cglib代理 <aop:pointcut> 切入點 ,從目標對象得到具體方法 <aop:advisor> 特殊的切面,只有一個通知 和 一個切入點 advice-ref 通知引用 pointcut-ref 切入點引用 3.3 切入點表達式 execution(* com.itheima.c_spring_aop.*.*(..)) 選擇方法 返回值任意 包 類名任意 方法名任意 參數任意
--> <aop:config proxy-target-class="true"> <aop:pointcut expression="execution(* com.itheima.c_spring_aop.*.*(..))" id="myPointCut"/> <aop:advisor advice-ref="myAspectId" pointcut-ref="myPointCut"/> </aop:config> </beans> |
@Test public void demo01(){ String xmlPath = "com/itheima/c_spring_aop/beans.xml"; ApplicationContext applicationContext = new ClassPathXmlApplicationContext(xmlPath);
//得到目標類 UserService userService = (UserService) applicationContext.getBean("userServiceId"); userService.addUser(); userService.updateUser(); userService.deleteUser(); } |
l AspectJ是一個基於Java語言的AOP框架
l Spring2.0之後新增了對AspectJ切點表達式支持
l @AspectJ 是AspectJ1.5新增功能,經過JDK5註解技術,容許直接在Bean類中定義切面
新版本Spring框架,建議使用AspectJ方式來開發AOP
l 主要用途:自定義開發
1.execution() 用於描述方法 【掌握】
語法:execution(修飾符 返回值 包.類.方法名(參數) throws異常)
修飾符,通常省略
public 公共方法
* 任意
返回值,不能省略
void 返回沒有值
String 返回值字符串
* 任意
包,[省略]
com.itheima.crm 固定包
com.itheima.crm.*.service crm包下面子包任意 (例如:com.itheima.crm.staff.service)
com.itheima.crm.. crm包下面的全部子包(含本身)
com.itheima.crm.*.service.. crm包下面任意子包,固定目錄service,service目錄任意包
類,[省略]
UserServiceImpl 指定類
*Impl 以Impl結尾
User* 以User開頭
* 任意
方法名,不能省略
addUser 固定方法
add* 以add開頭
*Do 以Do結尾
* 任意
(參數)
() 無參
(int) 一個整型
(int ,int) 兩個
(..) 參數任意
throws ,可省略,通常不寫。
綜合1
execution(* com.itheima.crm.*.service..*.*(..))
綜合2
<aop:pointcut expression="execution(* com.itheima.*WithCommit.*(..)) ||
execution(* com.itheima.*Service.*(..))" id="myPointCut"/>
2.within:匹配包或子包中的方法(瞭解)
within(com.itheima.aop..*)
3.this:匹配實現接口的代理對象中的方法(瞭解)
this(com.itheima.aop.user.UserDAO)
4.target:匹配實現接口的目標對象中的方法(瞭解)
target(com.itheima.aop.user.UserDAO)
5.args:匹配參數格式符合標準的方法(瞭解)
args(int,int)
6.bean(id) 對指定的bean全部的方法(瞭解)
bean('userServiceId')
l aop聯盟定義通知類型,具備特性接口,必須實現,從而肯定方法名稱。
l aspectj 通知類型,只定義類型名稱。已經方法格式。
l 個數:6種,知道5種,掌握1中。
before:前置通知(應用:各類校驗)
在方法執行前執行,若是通知拋出異常,阻止方法運行
afterReturning:後置通知(應用:常規數據處理)
方法正常返回後執行,若是方法中拋出異常,通知沒法執行
必須在方法執行後才執行,因此能夠得到方法的返回值。
around:環繞通知(應用:十分強大,能夠作任何事情)
方法執行先後分別執行,能夠阻止方法的執行
必須手動執行目標方法
afterThrowing:拋出異常通知(應用:包裝異常信息)
方法拋出異常後執行,若是方法沒有拋出異常,沒法執行
after:最終通知(應用:清理現場)
方法執行完畢後執行,不管方法中是否出現異常
環繞
try{ //前置:before //手動執行目標方法 //後置:afterRetruning } catch(){ //拋出異常 afterThrowing } finally{ //最終 after } |
l 4個:
aop聯盟規範
spring aop 實現
aspect 規範
spring aspect 實現
1.目標類:接口 + 實現
2.切面類:編寫多個通知,採用aspectj 通知名稱任意(方法名任意)
3.aop編程,將通知應用到目標類
4.測試
/** * 切面類,含有多個通知 */ public class MyAspect {
public void myBefore(JoinPoint joinPoint){ System.out.println("前置通知 : " + joinPoint.getSignature().getName()); }
public void myAfterReturning(JoinPoint joinPoint,Object ret){ System.out.println("後置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret); }
public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("前"); //手動執行目標方法 Object obj = joinPoint.proceed();
System.out.println("後"); return obj; }
public void myAfterThrowing(JoinPoint joinPoint,Throwable e){ System.out.println("拋出異常通知 : " + e.getMessage()); }
public void myAfter(JoinPoint joinPoint){ System.out.println("最終通知"); }
} |
<!-- 1 建立目標類 --> <bean id="userServiceId" class="com.itheima.d_aspect.a_xml.UserServiceImpl"></bean> <!-- 2 建立切面類(通知) --> <bean id="myAspectId" class="com.itheima.d_aspect.a_xml.MyAspect"></bean> <!-- 3 aop編程 <aop:aspect> 將切面類 聲明「切面」,從而得到通知(方法) ref 切面類引用 <aop:pointcut> 聲明一個切入點,全部的通知均可以使用。 expression 切入點表達式 id 名稱,用於其它通知引用 --> <aop:config> <aop:aspect ref="myAspectId"> <aop:pointcut expression="execution(* com.itheima.d_aspect.a_xml.UserServiceImpl.*(..))" id="myPointCut"/>
<!-- 3.1 前置通知 <aop:before method="" pointcut="" pointcut-ref=""/> method : 通知,及方法名 pointcut :切入點表達式,此表達式只能當前通知使用。 pointcut-ref : 切入點引用,能夠與其餘通知共享切入點。 通知方法格式:public void myBefore(JoinPoint joinPoint){ 參數1:org.aspectj.lang.JoinPoint 用於描述鏈接點(目標方法),得到目標方法名等 例如: <aop:before method="myBefore" pointcut-ref="myPointCut"/> -->
<!-- 3.2後置通知 ,目標方法後執行,得到返回值 <aop:after-returning method="" pointcut-ref="" returning=""/> returning 通知方法第二個參數的名稱 通知方法格式:public void myAfterReturning(JoinPoint joinPoint,Object ret){ 參數1:鏈接點描述 參數2:類型Object,參數名 returning="ret" 配置的 例如: <aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" /> -->
<!-- 3.3 環繞通知 <aop:around method="" pointcut-ref=""/> 通知方法格式:public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{ 返回值類型:Object 方法名:任意 參數:org.aspectj.lang.ProceedingJoinPoint 拋出異常 執行目標方法:Object obj = joinPoint.proceed(); 例如: <aop:around method="myAround" pointcut-ref="myPointCut"/> --> <!-- 3.4 拋出異常 <aop:after-throwing method="" pointcut-ref="" throwing=""/> throwing :通知方法的第二個參數名稱 通知方法格式:public void myAfterThrowing(JoinPoint joinPoint,Throwable e){ 參數1:鏈接點描述對象 參數2:得到異常信息,類型Throwable ,參數名由throwing="e" 配置 例如: <aop:after-throwing method="myAfterThrowing" pointcut-ref="myPointCut" throwing="e"/> --> <!-- 3.5 最終通知 --> <aop:after method="myAfter" pointcut-ref="myPointCut"/>
</aop:aspect> </aop:config> |
<!-- 1 建立目標類 --> <bean id="userServiceId" class="com.itheima.d_aspect.b_anno.UserServiceImpl"></bean> <!-- 2 建立切面類(通知) --> <bean id="myAspectId" class="com.itheima.d_aspect.b_anno.MyAspect"></bean> |
l 注意:掃描
<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" 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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd"> <!-- 1.掃描 註解類 --> <context:component-scan base-package="com.itheima.d_aspect.b_anno"></context:component-scan> |
l 必須進行aspectj 自動代理
<!-- 2.肯定 aop註解生效 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> |
l 聲明切面
<aop:aspect ref="myAspectId"> |
l 替換前置通知
<aop:before method="myBefore" pointcut="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))"/> |
//切入點當前有效 @Before("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))") public void myBefore(JoinPoint joinPoint){ System.out.println("前置通知 : " + joinPoint.getSignature().getName()); } |
l 替換 公共切入點
<aop:pointcut expression="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" id="myPointCut"/> |
//聲明公共切入點 @Pointcut("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))") private void myPointCut(){ } |
l 替換後置
<aop:after-returning method="myAfterReturning" pointcut-ref="myPointCut" returning="ret" /> |
@AfterReturning(value="myPointCut()" ,returning="ret") public void myAfterReturning(JoinPoint joinPoint,Object ret){ System.out.println("後置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret); } |
l 替換環繞
<aop:around method="myAround" pointcut-ref="myPointCut"/> |
@Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("前"); //手動執行目標方法 Object obj = joinPoint.proceed();
System.out.println("後"); return obj; } |
l 替換拋出異常
<aop:after-throwing method="myAfterThrowing" pointcut="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" throwing="e"/> |
@AfterThrowing(value="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" ,throwing="e") public void myAfterThrowing(JoinPoint joinPoint,Throwable e){ System.out.println("拋出異常通知 : " + e.getMessage()); } |
/** * 切面類,含有多個通知 */ @Component @Aspect public class MyAspect {
//切入點當前有效 // @Before("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))") public void myBefore(JoinPoint joinPoint){ System.out.println("前置通知 : " + joinPoint.getSignature().getName()); }
//聲明公共切入點 @Pointcut("execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))") private void myPointCut(){ }
// @AfterReturning(value="myPointCut()" ,returning="ret") public void myAfterReturning(JoinPoint joinPoint,Object ret){ System.out.println("後置通知 : " + joinPoint.getSignature().getName() + " , -->" + ret); }
// @Around(value = "myPointCut()") public Object myAround(ProceedingJoinPoint joinPoint) throws Throwable{ System.out.println("前"); //手動執行目標方法 Object obj = joinPoint.proceed();
System.out.println("後"); return obj; }
// @AfterThrowing(value="execution(* com.itheima.d_aspect.b_anno.UserServiceImpl.*(..))" ,throwing="e") public void myAfterThrowing(JoinPoint joinPoint,Throwable e){ System.out.println("拋出異常通知 : " + e.getMessage()); }
@After("myPointCut()") public void myAfter(JoinPoint joinPoint){ System.out.println("最終通知"); }
}
|
<!-- 1.掃描 註解類 --> <context:component-scan base-package="com.itheima.d_aspect.b_anno"></context:component-scan>
<!-- 2.肯定 aop註解生效 --> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> |
@Aspect 聲明切面,修飾切面類,從而得到 通知。
通知
@Before 前置
@AfterReturning 後置
@Around 環繞
@AfterThrowing 拋出異常
@After 最終
切入點
@PointCut ,修飾方法 private void xxx(){} 以後經過「方法名」得到切入點引用
l spring 提供用於操做JDBC工具類,相似:DBUtils。
l 依賴 鏈接池DataSource (數據源)
create database ee19_spring_day02; use ee19_spring_day02; create table t_user( id int primary key auto_increment, username varchar(50), password varchar(32) );
insert into t_user(username,password) values('jack','1234'); insert into t_user(username,password) values('rose','5678'); |
package com.itheima.domain;
public class User {
private Integer id; private String username; private String password; |
public static void main(String[] args) {
//1 建立數據源(鏈接池) dbcp BasicDataSource dataSource = new BasicDataSource(); // * 基本4項 dataSource.setDriverClassName("com.mysql.jdbc.Driver"); dataSource.setUrl("jdbc:mysql://localhost:3306/ee19_spring_day02"); dataSource.setUsername("root"); dataSource.setPassword("1234");
//2 建立模板 JdbcTemplate jdbcTemplate = new JdbcTemplate(); jdbcTemplate.setDataSource(dataSource);
//3 經過api操做 jdbcTemplate.update("insert into t_user(username,password) values(?,?);", "tom","998");
} |
<!-- 建立數據源 --> <bean id="dataSourceId" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost:3306/ee19_spring_day02"></property> <property name="username" value="root"></property> <property name="password" value="1234"></property> </bean> <!-- 建立模板 ,須要注入數據源--> <bean id="jdbcTemplateId" class="org.springframework.jdbc.core.JdbcTemplate"> <property name="dataSource" ref="dataSourceId"></property> </bean>
<!-- 配置dao --> <bean id="userDaoId" class="com.itheima.c_dbcp.UserDao"> <property name="jdbcTemplate" ref="jdbcTemplateId"></property> </bean> |
<!-- 建立數據源 c3p0--> <bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/ee19_spring_day02"></property> <property name="user" value="root"></property> <property name="password" value="1234"></property> </bean> |
<!-- 配置dao * dao 繼承 JdbcDaoSupport,以後只須要注入數據源,底層將自動建立模板 --> <bean id="userDaoId" class="com.itheima.e_jdbcdaosupport.UserDao"> <property name="dataSource" ref="dataSourceId"></property> </bean> |
jdbc.driverClass=com.mysql.jdbc.Driver jdbc.jdbcUrl=jdbc:mysql://localhost:3306/ee19_spring_day02 jdbc.user=root jdbc.password=1234 |
<!-- 加載配置文件 "classpath:"前綴表示 src下 在配置文件以後經過 ${key} 得到內容 --> <context:property-placeholder location="classpath:com/itheima/f_properties/jdbcInfo.properties"/>
<!-- 建立數據源 c3p0--> <bean id="dataSourceId" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${jdbc.driverClass}"></property> <property name="jdbcUrl" value="${jdbc.jdbcUrl}"></property> <property name="user" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> </bean> |