IOC基礎使用
1、利用xml方式進行Bean管理
<?xml version="1.0" encoding="UTF-8"?>
<beans default-lazy-init="true"
xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
<!-- bean標籤中屬性值:
id:標識做用,不能含有特殊符號
name:遺留屬性,幾乎不用,與id相似,可使用'/'特殊符號
class:映射的class的全路徑
scope:該Bean的做用範圍
singleton:默認值,單表該Bean爲一個單實例對象,即每次使用的都是同一個Bean,與Servlet同樣
prototype:標識該Bean爲一個多實例對象,與Action同樣
request:spring建立一個Bean示例對象後存入request域對象中
session:spring建立一個Bean示例對象後存入session域對象中
globalSession:應用在Porlet環境中,若是沒有Porlet環境,那麼至關與Session
init-method:Bean示例初始化時執行該方法
destroy-method:Bean實例銷燬時執行該方法,若是想執行該方法,必須是單實例對象,並且只有在ApplicationContext(工廠)關閉時纔會執行
lazy-init:只對單例對象有用,是否延遲建立對象 默認值爲default,即false,在加載配置文件時即建立實例對象
true:在加載配置文件時延遲建立實例對象,調用applicationContext.getBean()方法時建立實例對象
在beans標籤中配置default-lazy-init="true",即將lazy-init的默認值設爲對應的true or false ,控制全部的bean -->
<!-- 利用靜態工廠建立Bean對象示例 -->
<bean id="beanFactory" factory-method="getCustomer"
class="cn.zz.spring.factory.BeanFactory"></bean>
<!-- 利用實例工廠建立Bean對象示例
1.先建立示例工廠對象
2.經過示例工廠中對應方法建立Bean示例對象
-->
<bean id="beanFactory2" class="cn.zz.spring.factory.BeanFactory2"></bean>
<bean id="customer" factory-bean="beanFactory2" factory-method="getCustomer"></bean>
<!-- 利用無參構造建立Bean實例對象 -->
<bean id="user" class="cn.zz.spring.domain.User" scope="singleton"
init-method="init" destroy-method="destroy" lazy-init="false">
<!-- 利用set方法注入String類型屬性 -->
<property name="string" value="str"></property>
<!-- 利用set方法注入List集合類型屬性 -->
<property name="list">
<list>
<value>123</value>
<value>456</value>
<value>789</value>
<value>123</value>
<value>456</value>
</list>
</property>
<!-- 利用set方法注入int類型屬性 -->
<property name="i" value="1"></property>
<!-- 利用set方法注入double類型屬性 -->
<property name="d" value="10.05"></property>
<!-- 利用set方法注入boolean類型屬性 -->
<property name="b" value="1"></property>
<!-- 利用set方法注入數組類型屬性 -->
<property name="arrs">
<array>
<value>111</value>
<value>222</value>
<value>333</value>
<value>444</value>
<!-- <ref bean="xxx"/> -->
</array>
</property>
<!-- 利用set方法注入Properties類型屬性 -->
<property name="properties">
<props>
<prop key="name">123</prop>
<prop key="word">456</prop>
<prop key="age">789</prop>
</props>
</property>
<!-- 利用set方法注入Map集合類型屬性 -->
<property name="map">
<map>
<entry key="a" value="123"></entry>
<entry key="b" value="456"></entry>
<entry key="c" value="789"></entry>
<!-- <entry key-ref="xxx" value-ref="xxx"></entry> -->
</map>
</property>
</bean>
<!-- 利用無參構造建立實例對象 -->
<bean name="people" class="cn.zz.spring.domain.People">
<!-- 利用set方法注入集合類型屬性 -->
<property name="userlist">
<list>
<!-- 注入object類型集合數據 -->
<ref bean="user" />
<ref bean="user" />
<ref bean="user" />
</list>
</property>
</bean>
<!-- 利用無參構造建立實例對象 -->
<bean name="customer2" class="cn.zz.spring.domain.Customer">
<constructor-arg name="cname" value="李四"></constructor-arg>
<constructor-arg index="1" value="lalala"></constructor-arg>
<constructor-arg index="2" value="18"></constructor-arg>
<!-- <constructor-arg name="cpassword" value="lalala"></constructor-arg>
<constructor-arg name="age" value="18" type="int"></constructor-arg> -->
</bean>
<!--使用p名稱空間進行屬性注入
1.引入P名稱空間:xmlns:p="http://www.springframework.org/schema/p"
2.使用P名稱空間
*普通類型屬性: p:屬性名稱="值"
*對象類型屬性 p:屬性名稱-ref="beanId"
-->
<bean name="customerSupper" class="cn.zz.spring.domain.CustomerSupper" p:customer-ref="customer2" p:name="小黑"></bean>
<!-- 使用SpEL(Spring Expression Language)方式進行屬性注入
SpEl是Spring3.x後的版本提供的方法
設置普通值:value="#{'String'}"
設置值對象中的的屬性:value="#{BeanId.Attribute}"或者value="#{BeanId.methodName()}"
-->
<bean name="customerSupper2" class="cn.zz.spring.domain.CustomerSupper">
<property name="customer" ref="#{'customer2'}"></property>
<property name="name" value="#{customer2.getCname()}"></property>
</bean>
<!-- 引入另外一個applicattionContext文件,進行分模塊管理classpath:表示類路徑,可省略
在同一個applicationContext文件中,bean標籤的id屬性不可重複
在不一樣的applicationContext文件中,bean標籤的id屬性可重複,後加載的會覆蓋先加載的
-->
<import resource="classpath:applicationContext2.xml"/>
</beans>java
2、利用註解方式進行Bean管理
1.作Spring的IOC註解開發,須要引入新的約束
<?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="cn.zz.spring"></context:component-scan>
<!-- 開啓註解掃描,但只會掃描屬性上的註解 -->
<!-- <context:annotation-config></context:annotation-config> -->
</beans>
2.利用註解方式建立對象
在須要被建立的對象的類上添加註解
設置該對象的一些屬性
@Scope(value="prototype")設置該對象爲多實例對象
3.利用註解注入屬性
注入普通類型屬性:在對應的屬性上添加
@Value(value="xxx")註解,與xml中配置不一樣,該方式不須要屬性提供set方法;
注入對象類型屬性:@Autowired和@Qualifier聯合使用注入多態類型屬性(spring框架中的註解)
@Autowired
@Quakifier(value="BeanId")
@Resource一個頂兩(javax即java擴展功能中的註解,官方不建議使用)
@Resource(name="BeanId")
4.利用註解設置Bean實例的生命週期
在對應要設置的方式的方法中添加對應的註解
通常建議使用xml配置的無參構造方式建立對象,能夠自行定義各類屬性,註解有必定侷限性
AOP學習基礎
AOP概念
全稱是Aspect-Oriented Programming,即面向切面的程序設計,底層使用動態代理實現
1、JDK代理,針對有接口的動態代理
public class TestDynamicProxy {
public static void main(String[] args) {
//1.得到一個已知實現類對象
ILook look = new LookImpl();
//2.利用proxy進行動態代理,獲取代理類
ILook look2 = (ILook) Proxy.newProxyInstance(look.getClass().getClassLoader(), look.getClass().getInterfaces(),new ProxyClass(look));
look2.look();
}
}
/**
* InvocationHandler 是代理實例的調用處理程序 實現的接口
* 即建立一個代理實例
* @author ZZ
*
*/
class ProxyClass implements InvocationHandler{
//設置一個成員變量用來接收被代理類的對象,look即被代理對象
ILook look;
public ProxyClass(ILook look){
this.look = look;
}
/**
* proxy:表示當前這個代理類對象
* method:表示當前方法
* args:表示方法參數
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//加強指定的方法
if("look".equals(method.getName())){
System.out.println("加強look...");
return null;
}
//放心其它的方法
return method.invoke(look, args);
}
}
2、Cglib代理,針對沒有接口的動態代理
public class TestCglibDynamicProxy {
public static void main(String[] args) {
//1.得到被代理的對象
See see = new SeeChild();
//建立一個Cglib動態代理類
ProxyClassCglib pr = new ProxyClassCglib(see);
//得到代理對象
See creatSee = pr.creatSee();
creatSee.see();
}
}
class ProxyClassCglib implements MethodInterceptor{
//1.建立一個用來接收代理類對象的成員變量
private See see;
//2.設置構造
public ProxyClassCglib(See see){
this.see = see;
}
/**
* 加強指定方法
*/
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
if("see".equals(method.getName())){
/**
* methodProxy.invokeSuper(proxy, args);
* 執行當前代理類的父類中的see的對應方法
* method.invoke(see, args);
* 執行被代理類的對應方法
*/
method.invoke(see, args);
methodProxy.invokeSuper(proxy, args);
System.out.println("加強see");
return null;
}
return method.invoke(see, args);
}
//4.返回代理對象
public See creatSee(){
//1.建立Cglib核心文件
Enhancer enhancer = new Enhancer();
//2.設置父類(設置父類的話,若是設置爲父類.class,能夠在加強方法中便可調用當前類的方法,也能夠調用代理類對應的方法;若是設置代理對象.class,則只能夠在加強方法中執行代理對象中對應的方法)
enhancer.setSuperclass(See.class);
//3.設置回調Callback類型,Callback應該是個MethodInterceptor的父接口,沒有源碼、、
enhancer.setCallback(this);
//4.生成代理類
See see = (See) enhancer.create();
//返回代理對象
return see;
}
}
Spring基於AspectJ的AOP開發
1、操做術語
2、xml方式操做AspectJ進行AOP開發
AspectJ表達式
基本樣式:execution(<訪問修飾符>?<返回類型><方法名>(<參數>)<異常>)
經常使用表達式
1.得到指定方法
execution(* cn.zz.xxx.method(..))
* 表示訪問修飾符和返回值類型是任意的,method(..)表示指定的方法名,參數任意
2.同理能夠設置全部方法名,全部包各類。。。
execution(* *.*(..))即全部包中的全部方法
execution(* cn.zz.*.*(..)) 即zz包下的全部方法
3.execution(*.xxx*(..))方法名稱是save開頭作加強
4.execution(* cn.zz..*(..)zz包和其全部子包,孫包中的全部方法
5.excution(* cn.zz.xxx.Ixxx+.*(..)) 當前包下指定接口的全部實現類中的全部方法(-:暫時未知)
3.通知類型
<bean id="customer2" class="cn.zz.spring.domain.Customer2"></bean>
<bean id="user2" class="cn.zz.spring.domain.User2"></bean>
<aop:config>
<aop:pointcut expression="execution(* cn.zz.spring.domain.User2.run(..))" id="p1"/>
<aop:aspect ref="customer2">
<aop:before method="run" pointcut-ref="p1"/>
</aop:aspect>
</aop:config>
<aop:before>:前置通知
<aop:aroubd>:環繞通知
<aop:after-returning>:後置通知
<aop:after-throw>:異常通知
<aop:after>:最終通知
3、註解方式操做AspectJ進行AOP開發
<!-- 配置開啓AOP中的註解掃描 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
在加強方法的類上添加註解@Aspect
在對應方法上添加@Before,@After等等。。配置value="execution()"AspectJ表達式
4、Spring整合Junit
引入Spring-test.jar包
在須要被建立的對象中設置兩個註解
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext.xml")
JdbcTemplate模板操做
配置信息
<!-- 得到外部引入的方式的鏈接池配置參數 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:c3p0.properties"></property>
</bean>
<!-- 得到外部文件的參數第二種方式
<context:property-placeholder location="classpath:c3p0.properties"/>
-->
<!-- 配置鏈接池IOC -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
<!-- 配置JdbcTemplate -->
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
測試代碼
/**
* 利用spring自帶的鏈接池得到單個數據
*/
@Test
public void testDemo1(){
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("com.mysql.jdbc.Driver");
dataSource.setUrl("jdbc:mysql:///test_spring");
dataSource.setUsername("root");
dataSource.setPassword("root");
JdbcTemplate template = new JdbcTemplate(dataSource);
String sql = "select count(*) from customer";
Integer i = template.queryForObject(sql, Integer.class);
System.out.println(i);
}
/**
* 利用C3P0鏈接池得到單個對象
*/
@Test
public void testDemo2(){
ComboPooledDataSource dataSource = new ComboPooledDataSource();
try {
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test_spring");
dataSource.setUser("root");
dataSource.setPassword("root");
JdbcTemplate template = new JdbcTemplate(dataSource);
String sql = "select * from customer where cname=?";
Customer customer = template.queryForObject(sql, new RowMapper<Customer>(){
@Override
public Customer mapRow(ResultSet set, int rows) throws SQLException {
Customer customer = new Customer();
String cname = set.getString("cname");
String address = set.getString("address");
customer.setCname(cname);
customer.setAddress(address);
return customer;
}
}, "網易");
System.out.println(customer.getAddress());
} catch (PropertyVetoException e) {
e.printStackTrace();
}
}
/**
* 利用IOC方式得到各個對象來得到對象集合
*/
@SuppressWarnings("resource")
@Test
public void testDemo3(){
ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
JdbcTemplate template = (JdbcTemplate) context.getBean("template");
String sql = "select * from customer";
List<Customer> list = template.query(sql, new RowMapper<Customer>(){
@Override
public Customer mapRow(ResultSet set, int rows) throws SQLException {
String cname = set.getString("cname");
String address = set.getString("address");
Customer customer = new Customer();
customer.setCname(cname);
customer.setAddress(address);
return customer;
}
});
System.out.println(list);
}
Spting事物操做
事物的傳播行爲
指在一個事物中調用另一個事物
利用配置文件控制事物和
事物的傳播行爲
事物管理API:PlatformTransactionManager(事物管理器)
<!-- 配置JdbcTemplate -->
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置Spring的JdbcTemplate模板的事物控制 -->
<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>
<!-- method:指定要執行事物的方法名稱
propagation:指定事物傳播行爲方式
isolation:指定事物的隔離級別
-->
<tx:method name="*" propagation="REQUIRED" isolation="DEFAULT"/>
</tx:attributes>
</tx:advice>
<!-- 配置切面 -->
<aop:config>
<aop:pointcut expression="execution(* cn.zz.spring.service.*.*(..))" id="p1"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="p1"/>
</aop:config>
利用註解控制事物和事物的傳播行爲
<!-- 開啓IOC註解掃描 :只會掃描屬性上的註解-->
<context:annotation-config></context:annotation-config>
<!-- 開啓AOP註解掃描 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
<!-- 開啓事物註解掃描 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- 配置transactionManager的 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置C3P0的DataSource -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${driver}"></property>
<property name="jdbcUrl" value="${url}"></property>
<property name="user" value="${username}"></property>
<property name="password" value="${password}"></property>
</bean>
<!-- 加載配置c3p0參數的Properties文件 -->
<!-- <context:property-placeholder location="classpath:c3p0.properties"/> -->
<!-- 得到外部引入的方式的鏈接池配置參數 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:c3p0.properties"></property>
</bean>
<!-- 配置各類Bean信息 -->
<bean id="userService2" class="cn.zz.spring.service2.UserService2"></bean>
<bean id="userDao" class="cn.zz.spring.dao.UserDao"></bean>
<bean id="template" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
在須要進行事物控制的類或者方法上添加註解
@Transactional