1.简介:
Spring 是分层的 Java SE/EE 应用 full-stack 轻量级开源框架,以 IoC(Inverse Of Control: 反转控制)和 AOP(Aspect Oriented Programming:面向切面编程)为内核,提供了展现层 Spring MVC 和持久层 Spring JDBC 以及业务层事务管理等众多的企业级应用技术,还能整合开源世界众多 著名的第三方框架和类库,逐渐成为使用最多的 Java EE 企业应用开源框架。
2.好处
方便解耦,简化开发
AOP 编程的支持
声明式事务的支持
方便程序的测试
方便集成各种优秀框架
降低 JavaEE API 的使用难度
3.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"> <!--把对象的创建交给spring来管理--> <!--spring对bean的管理细节 1.创建bean的三种方式 2.bean对象的作用范围 3.bean对象的生命周期 --> <!--创建bean的三种方式--> <!--第一种:使用默认构造函数创建,具体如下,没有默认构造方法则无法创建--> <!-- <bean id="accountService" class="com.xmz.service.impl.AccountServiceImpl" scope="singleton" init-method="init" destroy-method="destroy"></bean>--> <!--bean作用范围调整 bean标签的scope属性:用于指定bean作用范围,常用前两种 singleton:单例(默认值) prototype:多例的 request: 作用于web应用的请求范围 session:作用于web应用的会话范围 global-session: 作用于集群环境的会话范围(全局会话范围,当不是集群就是session) --> <bean id="accountDao" class="com.xmz.dao.impl.AccountDaoImpl" scope="prototype" ></bean> <!--第二种:使用普通工厂中的方法创建对象,(使用某个类中的方法创建对象,并存入spring容器中--> <!-- <bean id="instanceFactory" class="com.xmz.factory.InstanceFactory"></bean>--> <!-- <bean id="accountService1" factory-bean="instanceFactory" factory-method="getAccountService"></bean>--> <!--第三种方法:使用工厂中的静态方法创建对象(使用某个类中的静态方法创建对象)--> <!-- <bean id="accountService2" class="com.xmz.factory.StaticFactory" factory-method="getAccountService"></bean>--> <!--spring中的依赖注入 依赖注入: Dependency Injection 在当前累需要用到其他类的对象,由spring为我们提供,我们只需要在配置文件中说明 依赖注入: 能注入的数据:三类 基本类型和String 其他Bean类型(在配置文件中或者注解配置过的bean) 复杂类型/集合类型 注入的方式:三种 第一种:使用构造函数提供 第二种:使用set方法提供 第三种:使用注解提供 --> <!-- 构造函数注入 使用标签:constructor-arg 标签出现的位置:bean标签的内部 标签中的属性: type:用于指定要注入的数据类型,该类型也是构造函数中某个或某些参数的类型 index:用于指定要注入的数据给构造函数中指定索引位置的参数赋值,索引的位置是从0开始的 name: 用于指定都给构造函数指定名称的参数赋值 ==========以上参数用于赋值 value:基本类型 ref:其他Bean类型 特点:获取对象时,注入数据是必须的操作,如果用不到这些数据也必须提供 --> <bean id="accountService" class="com.xmz.service.impl.AccountServiceImpl"> <constructor-arg name="name" value="test"></constructor-arg> <constructor-arg name="age" value="18"></constructor-arg> <constructor-arg name="birthday" ref="now"></constructor-arg> </bean> <!--配置一个日期对象--> <bean id="now" class="java.util.Date"></bean> <!--方式二:set方法注入,常用该方法 涉及标签:property 属性:name,value,ref 优势:没有明确的限制,可以直接使用默认构造函数 --> <bean id="accountService1" class="com.xmz.service.impl.AccountServiceImpl1"> <property name="name" value="TEST"></property> <property name="age" value="21"></property> <property name="birthday" ref="now"></property> </bean> <!--复杂类型\集合类型的注入--> <bean id="accountService2" class="com.xmz.service.impl.AccountServiceImpl2"> <property name="myStrs"> <array> <value>111</value> <value>222</value> <value>333</value> </array> </property> <property name="myList"> <array> <value>111</value> <value>222</value> <value>333</value> </array> </property> <property name="mySet"> <array> <value>111</value> <value>222</value> <value>333</value> </array> </property> <property name="myMap"> <props> <prop key="testA">111</prop> <prop key="testB">222</prop> <prop key="testC">333</prop> </props> </property> <property name="myProps"> <map> <entry key="testA"> <value>111</value> </entry> <entry key="testB" value="222"></entry> <entry key="testC" value="333"></entry> </map> </property> </bean> </beans>
<?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名称空间和约束--> <context:component-scan base-package="com.xmz"></context:component-scan> </beans>
4.获取spring的ioc容器
public class Client { /** * 获取spring的ioc核心容器,并根据id获取对象 * ApplicationContext的三个常用实现类 实际开发更多使用这种方法 * ClassPathXmlApplicationContext:能且仅能加载类路径下的配置文件 * FileSystemXmlApplicationContext: 可以加载磁盘任意路径的配置文件(需要有访问权限) * AnnotationConfigApplicationContext: 用于读取注解创建容器 *读取完配置文件立即创建配置文件中的对象 单例对象适用 * * BeanFactory:构建核心容器时,创建对象采取的策略是延迟加载,根据id获取具体对象时,创建对象 * 多例对象适用 * @param args */ public static void main(String[] args) { // ApplicationContext ac = new FileSystemXmlApplicationContext("磁盘具体路径"); ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml"); // IAccountService as = (IAccountService) ac.getBean("accountService"); // IAccountService as = (IAccountService) ac.getBean("accountService1"); IAccountService as = (IAccountService) ac.getBean("accountService2"); as.saveAccount(); // IAccountDao adao = ac.getBean("accountDao", IAccountDao.class); System.out.println(as); // System.out.println(adao); } }
5.与xml对应的注解形式
/** * 曾经的xml配置 * <bean id="accountService" class="com.xmz.service.impl.AccountServiceImpl" * scope=" init-method="", destroy-method=""> * <property name="" value=""/ref=""></property> * </bean> * * 用于创建对象的 bean === @Component * 属性value:指定bean的id,不写默认是当前类名,且首字母改小写 * Controller:表现层 * Service:业务层 * Reposity:持久层 * 以上三个作用和属性和Component作用一样,是spring框架为我们提供明确的三层使用的注解,使我们三层对象更加清晰 * 用于注入数据的 property * Autowired: * 作用:自动注入,只要有bean对象类型和要注入的变量类型匹配一对一,就可以注入成功 * 若是没有,或者有多个则需要再通过变量名匹配,若匹配后还是一样则报错 * 出现位置可以是变量成员,也可以是方法 * Qualifier: * 作用:在按照类注入的基础上再按名称注入,在给类成员注入时不能单独使用,但是给方法参数注入时可以使用 * 属性:value指定注入bean的id * Resource: * 作用:直接按照bean的id注入 * 属性:name用于指定id * 以上三种只能注入其他bean类型的数据,而基本类型和string类型无法实现注入 * 另外集合类型的注入之只能通过xml来实现 * * Value: * 作用:用于注入基本类型和string类型 * 属性: * value:用于指定数据的值,可以使用spring的SpEL(也就是spring的el表达式)Spel的写法:${表达式} * * * * 用于改变作用范围的 scope * Scope * 作用:用于指定Bean的作用范围 * 属性:value-》指定范围的取值,常用singLeton和prototype,默认前者即单例 * 和生命周期有关的 init destroy * PreDestroy:指定销毁方法 * PostConstruct:指定初始化方法 */ @Component @Scope("prototype") public class AccountServiceImpl3 implements IAccountService { // @Autowired // @Qualifier("accountDao2") //必须和Autowired配合 @Resource(name = "accountDao2") private IAccountDao accountDao; // private IAccountDao accountDao1; // private IAccountDao accountDao2; public AccountServiceImpl3(){ System.out.println("对象创建了"); } public void saveAccount() { accountDao.saveAccount(); } }
6、事务管理,控制相关
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"> <!-- 配置Service --> <bean id="accountService" class="com.xmz.service.impl.AccountServiceImpl"> <!-- 注入dao --> <property name="accountDao" ref="accountDao"></property> <!--注入事务管理器--> <!-- <property name="transactionManager" ref="transactionManager"></property>--> </bean> <!--配置Dao对象--> <bean id="accountDao" class="com.xmz.dao.impl.AccountDaoImpl"> <!-- 注入QueryRunner --> <property name="runner" ref="runner"></property> <!--注入connectionUtils--> <property name="connectionUtils" ref="connectionUtils"></property> </bean> <!--配置QueryRunner--> <!-- <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype">--> <!-- <!–注入数据源–>--> <!-- <constructor-arg name="ds" ref="dataSource"></constructor-arg>--> <!-- </bean>--> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean> <!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--连接数据库的必备信息--> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis"></property> <property name="user" value="root"></property> <property name="password" value="WANan123"></property> </bean> <!--配置Connection的工具类ConnectionUtils--> <bean id="connectionUtils" class="com.xmz.utils.ConnectionUtils"> <property name="dataSource" ref="dataSource"></property> </bean> <!--配置事务管理器--> <bean id="transactionManager" class="com.xmz.utils.TransactionManager"> <property name="connectionUtils" ref="connectionUtils"></property> </bean> <!--配置aop--> <aop:config> <aop:pointcut id="pt1" expression="execution(* com.xmz.service.impl.*.*(..))"/> <aop:aspect id="txAdvice" ref="transactionManager"> <aop:before method="beginTransaction" pointcut-ref="pt1"></aop:before> <aop:after-returning method="commit" pointcut-ref="pt1"></aop:after-returning> <aop:after-throwing method="rollback" pointcut-ref="pt1"></aop:after-throwing> <aop:after method="release" pointcut-ref="pt1"></aop:after> </aop:aspect> </aop:config> </beans>
/** * 使用Junit单元测试:测试我们的配置 */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = "classpath:bean.xml") public class AccountServiceTest { @Autowired private IAccountService as; @Test public void tranfer(){ as.transfer("1","2",100f); } }
@Override public List<Account> findAllAccount() { try{ return runner.query(connectionUtils.getThreadConnection(),"select * from account1",new BeanListHandler<Account>(Account.class)); }catch (Exception e) { throw new RuntimeException(e); } }
private IAccountService accountService; private TransactionManager transactionManager; public void setTransactionManager(TransactionManager transactionManager) { this.transactionManager = transactionManager; } public final void setAccountService(IAccountService accountService){ this.accountService = accountService; } public IAccountService getAccountService(){ return (IAccountService)Proxy.newProxyInstance(accountService.getClass().getClassLoader(), accountService.getClass().getInterfaces(), new InvocationHandler() { /** * 添加事务的支持 * @param proxy * @param method * @param args * @return * @throws Throwable */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object rtValue = null; try{ transactionManager.beginTransaction(); method.invoke(accountService, args); transactionManager.commit(); return rtValue; }catch (Exception e){ transactionManager.rollback(); throw new RuntimeException(e); }finally { transactionManager.release(); }
7、xml+注解型
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: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/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"> <!--创建容器时要扫描的包--> <context:component-scan base-package="com.xmz"></context:component-scan> <bean id="runner" class="org.apache.commons.dbutils.QueryRunner" scope="prototype"></bean> <!-- 配置数据源 --> <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <!--连接数据库的必备信息--> <property name="driverClass" value="com.mysql.jdbc.Driver"></property> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis"></property> <property name="user" value="root"></property> <property name="password" value="WANan123"></property> </bean> <!--开启spring对注解AOP的支持--> <aop:aspectj-autoproxy></aop:aspectj-autoproxy> </beans>
** * 账户的持久层实现类 */ @Repository("accountDao") public class AccountDaoImpl implements IAccountDao { @Autowired private QueryRunner runner; @Autowired private ConnectionUtils connectionUtils;
/** * 账户的业务层实现类 */ @Service("accountService") public class AccountServiceImpl implements IAccountService{ @Autowired private IAccountDao accountDao; private TransactionManager transactionManager; public void setTransactionManager(TransactionManager transactionManager) { this.transactionManager = transactionManager; }
@Component("txManager") @Aspect public class TransactionManager { @Autowired private ConnectionUtils connectionUtils; @Pointcut("execution(* com.xmz.service.impl.*.*(..))") private void pt1(){};
@Component("connectionUtils") public class ConnectionUtils { private ThreadLocal<Connection> t1 = new ThreadLocal<Connection>(); @Autowired private DataSource dataSource;