之前分享过hibernate框架, 这次分享一下关于spring框架的一些内容,都是自我理解的一些内容,仅供参考哦。
首先
介绍一下spring框架:
Spring是一个开源框架,是一个一站式框架
Spring是一个容器,你给他安装什么,他就拥有了什么功能
Struts2他就是一个web层,给他安装hibernate他就是一个dao层的框架。Service也可以使用spring框架来管理。
Spring springMVC springBoot都是web层的框架
JbdcTemplate spring中也提供了dao层的框架
spring核心思想的介绍:
Ioc (控制反转)
Di (依赖注入) (技术点)
Aop (面向切面) 事务的管理
简单的对spring有一些了解之后,就是如何对spring的环境搭建:
Spring环境搭建:
- 导包(需要导入三个依赖:)
<dependencies> <!-- https://mvnrepository.com/artifact/org.springframework/spring-context --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-core --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>5.0.2.RELEASE</version> </dependency> <!-- https://mvnrepository.com/artifact/org.springframework/spring-beans --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-beans</artifactId> <version>5.0.2.RELEASE</version> </dependency> </dependencies>
-
然后再准备一个类
-
书写配置文件(applicationContext.xml) 引入约束 配置实体类,在spring容器中
-
书写测试代码
public class Demo { public static void main(String[] args) { ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml"); User user = (User) ac.getBean("user"); System.out.println(user); }
spring核心配置文件的详解:
1. 名字和位置
配置文件名字没有要求,
位置:maven 放在resource中
2. bean 属性的配置
功能:配置类 用来创建对象
Class
Name
创建对象的方式:
a) 通过无参的构造函数来创建(默认)
b)通过静态工厂来实例化对象
提供静态工厂 类中提供一个静态方法,返回一个实体对象
public class UserFactory {
public static User createUser(){
return new User();
}
配置文件:
<bean name="userFactory" class="com.hd.create.UserFactory" factory-method="createUser"></bean>
测试类:
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("applicationContext.xml");
User user = (User) ac.getBean("userFactory");
System.out.println(user);
}
c) 通过实例化工厂创建对象
准备一个工厂 提供创建对象的方法 public
配置文件中,既要配置要创建的对象,也要配置工厂
在对象的创建时要指定是哪个工厂中的方法
spring属性注入:
1. set方法注入(重点)
基础类型 8大基础类型和string value注入
<bean name="car" class="com.hd.injection.Car">
<property name="name" value="加长林肯"></property>
<property name="color" value="黑色"></property>
</bean>
引用类型 对象 ref注入
<bean name="user" class="com.hd.test.User">
<property name="name" value="郭婷婷"></property>
<property name="address" value="河南"></property>
<property name="userId" value="0123"></property>
<property name="car" ref="car"></property>
</bean>
2. 构造函数的注入
创建对象用的是制定构造函数创建(按照顺序进行注入)
name (构造函数中参数的名字) value(属性的值) index(该参数的位置) type(该参数的类型)
<constructor-arg name="age" value="12" index="0" type="java.lang.Integer"></constructor-arg>
3. p空间的注入
导入约束
这种方式虽然简单,但是不被业界认可
4. spel 注入
<bean name="teacher1" class="com.hd.injection.TeacherP">
<property name="name" value="#{teacher.name}"></property>
</bean>
适用于已经在spring容器中有一个对象,重新创建一个对象要用到原来对象中的内容
复杂属性的注入:
数组属性注入:
数组属性注入
<bean name="order" class="com.hd.complexInjection.Order">
<property name="productIds">
<array>
<value>1</value>
<value>2</value>
<value>3</value>
<value>4</value>
</array>
</property>
集合:
list Map
<property name="list">
<list>
<value>list集合</value>
<ref bean="car"></ref>
</list>
</property>
<property name="map">
<map>
<entry key="id" value="1123"></entry>
<entry key="car" value-ref="car"></entry>
</map>
</property>
Properties
<property name="properties">
<props>
<prop key="url">jdbc:mysql:localhost:3306</prop>
</props>
</property>
</bean>
注解方式:
1. 开启注解 制定扫描的包
<context:component-scan base-package="com.hd"></context:component-scan>
2. 使用注解管理对象
@Component //以下三合一注解
@Repository //dao层注解
@Service
@Controller //外部层注解
四种注解,没有本质区别,只是为了区分web项目的结构
如果想给对象起个名字在上面小括号中写入名字即可,如果不写默认与类型保持一致(首字母小写)
3. 对象的范围
@Scope(scopeName = "prototype")
在类上面进行书写
4. 在创建对象后和销毁对象前调用的方法
@PostConstruct
public void init(){
System.out.println("创建对象后调用");
}
@PreDestroy
public void destroy(){
System.out.println("销毁对象前调用");
}
5. 依赖管理
普通属性
在属性或者set方法上面注解
@Value("张三")//在属性上面注解, set方法可以省略
private String name;
private Integer age;
或者
@Value("21")
public void setAge(Integer age) {
this.age = age;
}
引出类型:
如果该对象在spring中只有一个
@Autowired
private Car car;
如果有多个还想使用自动装配,就必须指定
@Autowired
@Qualifier("car2")
private Car car;
如果是多个写两个比较麻烦,提供一个新的
@Resource(name = "car2")
private Car car;
导包
Maven项目依赖
<!-- https://mvnrepository.com/artifact/org.springframework/spring-test -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>
<version>5.0.2.RELEASE</version>
<scope>test</scope>
</dependency>
面向切面编程
代理技术:spring aop用到了java中代理技术,给目标对象生成一个代理对象,生成的目标对象会拥有目标对象的所有方法,只要在调用目标对象方法前执行代理对象代码即可。
Spring 实现代理有两种方式:
- 动态代理(优先考虑): 该目标对象必须实现接口,才能生成代理对象
- Cglib 代理: 不用实现接口,第三方代理技术,实现代理技术原理是使用继承,要求目标对象不能使用final修饰。
手动实现代理动态代理:
加强service 开启事务 提交事务
- 准备一个service接口
- 实现service接口
- 创建service的代理对象工厂
Spring 实现代理有两种方式:
1. 动态代理(优先考虑): 该目标对象必须实现接口,才能生成代理对象
2. Cglib 代理: 不用实现接口,第三方代理技术,实现代理技术原理是使用继承,要求目标对象不能使用final修饰。
手动实现代理动态代理:
加强service 开启事务 提交事务
-
准备一个service接口
- 实现service接口
- 创建service的代理对象工厂
public class UserServiceProxyFactory implements InvocationHandler{
private UserService userService;
public UserServiceProxyFactory(UserService userService) {
this.userService = userService;
}
public UserService getUserServiceProxy() {
UserService userServiceProxy = (UserService) Proxy.newProxyInstance(UserServiceProxyFactory.class.getClassLoader(),
UserServiceImpl.class.getInterfaces(), this);
return userServiceProxy;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("开启事务");
Object invoke = null;
try{
invoke= method.invoke(userService,args);
System.out.println("提交事务");
}catch (Exception e) {
e.printStackTrace();
System.out.println("回滚事务");
}
return invoke;
}
}
cgilb实现代理方法:
- 准备一个类
- 创建生成代理对象的类
public class UserServiceProxyFactory1 implements MethodInterceptor{
public UserService getUserServiceProxy(){
//cglib 提供的api 用来创建代理对象
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(UserServiceImpl.class);
enhancer.setCallback(this);
UserService o = (UserService) enhancer.create();
return o;
}
@Override
public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {
System.out.println("开启事务");
Object invoke = methodProxy.invokeSuper(o, objects);
System.out.println("提交事务");
return invoke;
}
7个专业名词:
连接点 joinPoint 被代理对象拥有所有可以加强的方法
切入点 pointCut 已经被加强的方法
通知 adivce 加强的代码
目标对象 target 被代理的对象
织入 weaving 将通知应用到目标对象的连接点
代理 proxy 生成目标对象的代理对象
切面 aspect 通知+切点
1. 导包(aspect)
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.6.12</version>
</dependency>
2. 准备一个通知
3. 配置切点和切面
<context:component-scan base-package="com.hd"></context:component-scan>
<bean name="myAdvice" class="com.hd.springAop.MyAdvice"></bean>
<aop:config>
<aop:pointcut id="pt" expression="execution( * com.hd.springAop.*ServiceImpl.*(..) )"></aop:pointcut>
<aop:aspect ref="myAdvice">
<aop:before method="before" pointcut-ref="pt"></aop:before>
<aop:after method="after" pointcut-ref="pt"></aop:after>
<aop:after-returning method="afterReturning" pointcut-ref="pt"></aop:after-returning>
<aop:after-throwing method="afterThrowing" pointcut-ref="pt"></aop:after-throwing>
</aop:aspect>
</aop:config>
- 开启注解模式
- 在通知中使用注解配置
@Before("MyAdvice.pt()")
public void before(){
System.out.println("注解模式---方法前使用");
}
@After("MyAdvice.pt()")
public void after(){
System.out.println("有异常也正常调用");
}
Spring整合JDBC
Spring是一个容器
Dao层 hibernate mybatis jdbcTemplate
- 导包 spring-jdbc 数据库驱动包 c3p0连接池 spring-tx
- 准备好数据库
手动管理对象测试代码:
1)获得数据库连接 连接池
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/springjdbc?CharacterEncoding=UTF-8");
dataSource.setUser("root");
dataSource.setPassword("root");
2)获得springjdbc提供的api jdbcTemplate
JdbcTemplate jt = new JdbcTemplate();
jt.setDataSource(dataSource);
3)调用JdbcTemplate方法
String sql = "insert into t_user VALUE (null,'王','199')";
int update = jt.update(sql);
System.out.println(update);
Spring 容器管理对象的方式开启dao方法
Spring管理事务
事务的传播行为 propagation
1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行。‘
3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
配置xml:
<tx:advice id = "myAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="transform" isolation="DEFAULT" rollback-for="false" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="myPt" expression="execution(* com.hd.jdbc.*ServiceImpl.*(..))"></aop:pointcut>
<aop:advisor advice-ref="myAdvice" pointcut-ref="myPt"></aop:advisor>
</aop:config>
注解模式:
1. 开启注解
<tx:annotation-driven></tx:annotation-driven>
2. 在对应的类上面加上注解,则该类的所有方法都会采取事务管理。只对某个方法进行事务管理,在放发明上面加上注解,两个地方都有,则以方法上面的为准
@Transactional(isolation = Isolation.DEFAULT,readOnly = false,propagation = Propagation.REQUIRED)
我所理解的只有这么多,希望你们不要介意,如果觉得哪里有不对的,希望指出,加以修改。