标签:-o value 管理机 企业 curl long 数据源配置 icc filesyste
Spring是一个开源框架
Spring为简化企业级英语开发而生。使用Spring可以使简单的JavaBean实现以前只有EJB才能实现的功能
Spring是一个IOC(DI)和AOP容器框架
具体描述Spring:
示例:
<!--
配置bean
class: bean 的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参数的构造器
id: 标识容器中的bean,id 唯一
-->
<!-- 通过全类名的方式来配置bean -->
<bean id="helloWorld" class="com.ljf.spring.beans.HelloWorld">
<property name="name2" value="Spring"> </property>
</bean>
// 1.创建Spring的IOC容器对象,在创建这个容器的时候会调用类的构造器对配置文件(xml)中的Bean初始化,同时调用set方法对属性就行赋值
// ApplicationContext 代表IOC容器
// ClassPathXmlApplicationContext:是ApplicationContext接口的实现类,该实现类从类路径下加载配置文件
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
// 2.从IOC容器中获取Bean实例
// 利用id定位到IOC容器中的bean
HelloWorld helloworld = (HelloWorld) ctx.getBean("helloWorld");
// 利用类型返回IOC容器中的Bean,但要求IOC容器中必须只能有一个该类型的Bean
//HelloWorld helloWorld = ctx.getBean(HelloWorld.class);
// 3.调用hello方法
helloWorld.hello();
IOC & DI概述
IOC(Inversion of Control):其思想是反转资源获取的方向。传统的资源查找方式要求组件向容器发起请求查找资源。作为回应,容器适时的返回资源。而应用了IOC之后,则是容器主动地将资源推送给它所管理的组件,组件所要做的仅是选择一种合适的方式来接受资源。这种行为也被称为查找的被动形式。
DI(Dependency Injection)--IOC的另一种表述方式:即组件以一些预先定义好的方式(例如:setter方法)接受来自如容器的资源注入。相对于IOC而言,这种表述更直接。
<!--
配置bean
class: bean 的全类名,通过反射的方式在IOC容器中创建Bean,所以要求Bean中必须有无参数的构造器
id: 标识容器中的bean,id 唯一
-->
ApplicationContext:
ConfigurableApplicationContext扩展于ApplicationContext,新增加两个主要方法:refresh()和close(),让ApplicationContext具有启动、刷新和关闭上下文的能力
WebApplicationContext是专门为WEB应用而准备的,它允许从相对于WEB根目录的路径中完成初始化工作。
属性注入:
<!-- 通过全类名的方式来配置bean -->
<bean id="helloWorld" class="com.ljf.spring.beans.HelloWorld">
<property name="name2" value="Spring"> </property>
</bean>
构造方法注入:
<!--
通过构造方法来配置bean的属性
使用构造器注入属性值可以指定参数的位置和参数的类型,以区分重载的构造器
-->
<bean id="car" class="com.ljf.spring.beans.Car">
<constructor-arg value="Audi" index="0"></constructor-arg>
<constructor-arg value="ShangHai" index="1"></constructor-arg>
<constructor-arg value="300000" type="double"></constructor-arg>
</bean>
字面值:
引用其他Bean
<bean id="person" class="com.ljf.spring.beans.Person">
<property name="name" value="Jack"> </property>
<property age="age" value="24"> </property>
<!-- 可以使用property的ref属性建立bean之间的引用联系 -->
<property name="car" ref="car2"> </property>
<!-- 内部bean -->
</bean>
继承Bean配置
依赖Bean配置
bean的作用域:singleton;prototype;WEB环境作用域
使用bean的 scope 属性来配置bean的作用域
PropertyPlaceholderConfigurer
的BeanFactory后置处理器,这个处理器允许用户将Bean配置的部分内容外移到属性文件中。可以在Bean配置文件里使用形式为${var}
的变量,PropertyPlaceholderConfigurer
从属性文件里加载属性,并使用这些属性来替换变量${propName}
,以实现属性之间的相互引用。 <!-- 导入属性文件,配置数据库相关参数properties的属性:${url} -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<!-- 使用外部化属性文件的属性 -->
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
#{...}
作为定界符,所有在大大括号中的字符都将被认为是SpEL配置Bean的后置处理器
<!--
实现BeanPostProcessor接口,并具体提供
Object postProcessBeforeInitialization(Object bean, String beanName): init-method 之前被调用
Object postProcessAfterInitialization(Object bean, String beanName): init-method 之后被调用
bean: bean 实例本身
beanName: IOC 容器配置的bean的名字
返回值:是实际上返回给用户的那个Bean,注意:可以在以上两个方法中修改返回的bean,甚至返回一个新的bean
-->
<!-- 配置bean的后置处理器:不需要配置id,IOC容器自动识别是一个BeanPostProcessor -->
<bean class="com.ljf.MyBeanPostProcessor"></bean>
public class StaticCarFactory {
private static Map<String, Car> cars = new HashMap<String, Car>();
static {
cars.put("audi", new Car("audi", 30000));
cars.put("ford", new Car("ford"m 40000));
}
// 静态工厂方法
public static Car getCar(String name) {
return cars.get(name);
}
}
<!-- 通过静态工厂方法来配置 bean。注意补水配置静态工厂方法实例,而是配置bean实例 -->
<!--
class 属性:指向静态工厂方法的全类名
factory-method: 指向静态工厂方法的名字
constructor-arg: 如果工厂方法需要传入参数,则使用constructor-arg 来配置参数
-->
<bean id="car1"
class="com.ljf.beans.StaticCarFactory"
factory-method="getCar">
<constructor-arg value="audi"></constructor-arg>
</bean>
通过实例工厂方法配置bean
FactoryBean
<!--
通过FactoryBean 来配置Bean的实例
class: 指向FactoryBean的全类名
property: 配置FactoryBean的getObject() 方法返回的实例
但实际返回的实例是 FactoryBean的getObject() 方法返回的实例
-->
<bean id="car" class="com.ljf.bean.factorybean.CarFactoryBean">
<property name="brand" value="BMW"></property>
</bean>
public class CarfactoyBean implements FactoryBean<Car> {
...
Override 3 个方法
}
在classpath中扫描组件
对于扫描到的组件,Spring有默认的命名策略:使用非限定类名,第一个字母小写;也可以在注解中通过value属性值标识组件的名称
当在组件类上使用了特定的注解之后,还需要在Spring的配置文件中声明<context:component-scan>
<context:component-scan
base-package="com.ljf.spring.beans"
resource-pattern="autowire/*.class"/>
组件装配
使用@Autowired自动装配Bean
@Resource 注解要求提供一个Bean名称的属性,若该属性为空,则自动采用标注处的变量或方法名作为Bean的名称
@Inject 和 @Autowired 注解一样也是按类型匹配注入的Bean,但没有required属性
Spring 4.x新特性:泛型依赖注入
问题:
public class ArithmeticCalculatorLoggingProxy {
// 要代理的对象
private ArithmeticCalculator target;
private ArithmeticCalculator getLoggingProxy() {
ArithmeticCalculator proxy = null;
// 代理对象由哪一个类加载器负责加载
ClassLoader loader = target.getClass().getClassLoader();
// 代理对象的类型,即其中有哪些方法
Class[] interfaces = new Class[]{ArithmeticCalculator.class};
// 当调用代理对象其中的方法时,该执行的代码
InvocationHandler h = new InvocationHandler() {
/**
* proxy: 正在返回的那个代理对象,一般情况下,在invoke方法中都不使用该对象
* method: 正在被调用的方法
* args: 调用方法时,传入的参数
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String methodName = method.getName();
// 日志
System.out.println("ATGUIGU-> The method " + methodName + " bengins with " + Arrays.asList(args));
// 执行方法
Object result = method.invoke(target, args);
// 日志
return result;
}
};
proxy = (ArithmeticCalculator) Proxy.newProxyInstance(loader, interfaces, h);
return proxy;
}
}
AOP术语:
在Spring中启用AspectJ注解支持
步骤:
1)加入jar包
2)在配置文件中加入aop命名空间,配置自动扫描包
3)基于注解的方式
<context:component-scan base-package="com.ljf.spring.aop.impl"> </context:component-scan>
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
@Aspect
@Component
public class LoggingAspect {
// 声明该方法是一个前置通知:在目标方法开始之前执行
@Before("execution(* com.ljf.spring.aop.impl.*.*(int, int))")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = JoinPoint.getSignature().getName();
List<Object> args = Arrays.asList(JoinPoint.getArgs());
System.out.println("The method " + methodName + " begins with " + args);
}
// 后置通知:在目标方法执行后(无论是否发生异常),执行通知
// 在后置通知中还不能访问目标方法执行的结果
@After("execution(* com.ljf.spring.aop.impl.*.*(int, int))")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = JoinPoint.getSignature().getName();
System.out.println("The method " + methodName + " ends.");
}
// 在方法正常结束后执行的代码
// 返回通知是可以访问到方法的返回值
@AfterReturning(value="execution(* com.ljf.spring.aop.impl.*.*(..))", returning="result")
public void AfterReturning(JoinPoint joinPoint, Object result) {
String methodName = JoinPoint.getSignature().getName();
System.out.println("The method " + methodName + " ends with." + result);
}
// 在目标方法出现异常时执行的代码
// 可以访问到异常对象;且可以指定在出现特定异常时再执行通知代码
@AfterThrowing(value="execution(* com.ljf.spring.aop.impl.*.*(..))", throwing="ex")
public void AfterThrowing(JoinPoint joinPoint, Exception ex) {
String methodName = JoinPoint.getSignature().getName();
System.out.println("The method " + methodName + " occurs excetion: " + ex);
}
// 环绕通知需要携带 ProceedingJoinPoint 类型的参数
// 环绕通知类似于动态代理的全过程:ProceedingJoinPoint 类型的参数可以决定是否执行目标方法
// 且环绕通知必须由返回值,返回值即为目标方法的返回值
@Around(value="execution(* com.ljf.spring.aop.impl.*.*(..))")
public void AroundMethod(ProceedingJoinPoint pjd, Exception ex) {
System.out.println("aroundMethod");
return 100;
}
}
@Order(x)指定切面的优先级,x为值,值越小,优先级越高
重用切点表达式
@Aspect
@Component
public class LoggingAspect {
@Pointcut("execution(* com.ljf.spring.aop.impl.*.*(..))"")
public void declareJointPointExpression(){}
// 声明该方法是一个前置通知:在目标方法开始之前执行
@Before("declareJointPointExpression()")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = JoinPoint.getSignature().getName();
List<Object> args = Arrays.asList(JoinPoint.getArgs());
System.out.println("The method " + methodName + " begins with " + args);
}
// 后置通知:在目标方法执行后(无论是否发生异常),执行通知
// 在后置通知中还不能访问目标方法执行的结果
@After("declareJointPointExpression()")
public void beforeMethod(JoinPoint joinPoint) {
String methodName = JoinPoint.getSignature().getName();
System.out.println("The method " + methodName + " ends.");
}
...
}
基于配置文件的AOP配置
<!-- 配置切面的bean -->
<bean id="LoggingAspect"
class="com.ljf.spring.aop.xml.LoggingAspect"></bean>
<!-- 配置AOP -->
<aop:config>
<!-- 配置切点表达式 -->
<aop:pointcut expression="execution(* com.ljf.spring.aop.impl.*.*(..))" id="pointcut"/>
<!-- 配置切面及通知 -->
<aop:aspect ref="LoggingAspect" order="2">
<aop:before method="beforeMethod" pointcut-ref="pointcut"/>
<aop:after method="afterMethod" pointcut-ref="pointcut"/>
<aop:after-throwing method="afterThrowing" pointcut-ref="pointcut" throwing="e"/>
<aop:after-returning method="afterReturning" pointcut-ref="pointcut" returning="result"/>
</aop:aspect>
<aop:aspect ref="vlidationAspect" order="1">
<aop:around method="aroundMethod" pointcut-ref="pointcut"/>
</aop:aspect>
</aop:config>
JDBCTemplate 简介:
<!-- 配置数据库相关参数properties的属性:${url} -->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!-- 数据库连接池 -->
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driver}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
<property name="minPoolSize" value="${c3p0.minPoolSize}"/>
<property name="autoCommitOnClose" value="${c3p0.autoCommitOnClose}"/>
<property name="checkoutTimeout" value="${c3p0.checkoutTimeout}"/>
<property name="acquireRetryAttempts" value="${c3p0.acquireRetryAttempts}"/>
</bean>
<!-- 配置 Spring 的 JdbcTemplate -->
<bean id="jdbcTemplate"
class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource"></property>
</bean>
public class JDBCTest {
private ApplicationContext ctx = null;
private JdbcTemplate jdbcTemplate;
{
ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
jdbcTemplate = (JdbcTemplate) ctx.getBean("jdbcTemplate");
}
/**
* 调用queryForObject(String sql, RowMapper<Employee> rowMapper, Object... args)
* 1.其中的RowMapper指定如何去映射结果集的行,常用的实例类为BeanPropertyRowMapper
* 2.使用SQL中列的别名完成列名和类的属性名的映射,例如 last_name lastName
* 3.不支持级联属性(如department.id),JdbcTemplate 到底是一个JDBC的小工具,而不是ORM框架
*/
@Test // 查找一个对象
public void testQueryForObject() {
String sql = "SELECT id, last_name lastName, email, dept_id as \"department.id\" FROM employees WHERE id = ?";
RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
Employee employee = jdbcTemplate.queryForObject(sql, rowMapper, 1);
System.out.println(employee);
}
/**
* 查找实体类的集合
*/
@Test // 查找一组对象
public void testQueryForList() {
String sql = "SELECT id, last_name lastName, email FROM employees WHERE id > ?";
RowMapper<Employee> rowMapper = new BeanPropertyRowMapper<>(Employee.class);
List<Employee> employees = jdbcTemplate.query(sql, rowMapper, 5);
System.out.println(employees);
}
/**
* 获取单个列的值,或做统计查询
*/
@Test
public void testQueryForObject2() {
String sql = "SELECT count(id) FROM employees";
long count = jdbcTemplate.queryForObject(sql, Long.class);
System.out.println(count);
}
/**
* 批量执行 INSERT, UPDATE, DELETE
*/
@Test
public void testBatchUpdate() {
String sql = "INSERT INTO employees(last_name, email, dept_id) VALUES(?,?,?)";
List<Object[]> batchArgs = new ArrayList<>();
batchArgs.add(new Object[]{"AA", "aa@163.com", 1});
batchArgs.add(new Object[]{"BB", "bb@163.com", 2});
batchArgs.add(new Object[]{"CC", "cc@163.com", 3});
batchArgs.add(new Object[]{"DD", "dd@163.com", 3});
batchArgs.add(new Object[]{"EE", "ee@163.com", 2});
jdbcTemplate.batchUpdate(sql, batchArgs);
}
}
事务管理是企业级应用程序开发中必不可少的技术,用来确保数据的完整性和一致性。
<!-- 配置事务管理器 -->
<bean id="transactionManager"
class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 启用事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
在对应方法上加上@Transactional
注解
REQUIRED传播行为
@Transactional
注解的propagation属性中定义REQUIRES_NEW传播行为
并发事务所导致的问题:
// 添加事务注解
// 1.使用propagation 指定事务的传播行为,即当前的事务方法被另一个事务方法调用时,如何使用事务,默认取值为 REQUIRED,即使用调用方法的事务
// REQUIRES_NEW:事务自己的事务,调用的事务方法的事务被挂起
// 2.使用isolation 指定事务的隔离级别,最常用的取值为 READ_COMMITTED
// 3.默认情况下 Spring 的声明式事务对所有的运行时异常进行回滚,也可以通过对应的属性进行设置。通常情况下取默认值即可
// 4.使用readOnly 指定事务是否为只读,表示这个事务只读取数据但不更新数据,这样可以帮助数据库引擎优化事务。若真的是一个只读数据库值的方法,应设置 readOnly=true
// 5.使用timeout 指定强制回滚之前事务可以占用的时间
@Transactional(propagation=Propagation.REQUIRES_NEW,
isolation=Isolation.READ_COMMITTED,
readOnly=false,
timeout=3)
<!-- 1.配置事务管理器 -->
<bean id="transactionManager"
class="rg.springframework.jdbc.datasource.DataSourceTransactionManager">
<!-- 注入数据库连接池 -->
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 2.配置事务属性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 传播行为 -->
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="insert*" propagation="REQUIRED" />
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="select*" propagation="SUPPORTS" read-only="true" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!-- 3.配置事务切入点,以及把事务切入点和事务属性关联起来 -->
<aop:config>
<aop:advisor advice-ref="txAdvice"
pointcut="execution(* com.bank.service.*.*(..))" />
</aop:config>
标签:-o value 管理机 企业 curl long 数据源配置 icc filesyste
原文地址:https://www.cnblogs.com/dear_diary/p/10328345.html