spring
spring就是ioc(依赖注入 控制反转) aop(面向切片编程 (实现是动态代理 cglib jdk )) 事物管理
bean对象的实例 ApplicationContext 和 BeanFactory的区别:
ApplicationContext是实现了BeanFactory这个接口
即 applicationContext < beanFactory
1.通过相对路径加载
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml");
2.通过绝对路径加载
BeanFactory beanFactory = new FileSystemXmlApplicationContext("C:\java项目\spring\src\main\resources\spring.xml");
3.当个配置文件加载和多个配置文件加载
1.通过可变参数设置多个配置文件
BeanFactory beanFactory = new ClassPathXmlApplicationContext("spring.xml","beans.xml");
2.设置一个总的配置配置文件
就是创建一个总的 使用
使用实例
//得到spring的上下文环境
ApplicationContext ac = new ClassPathXmlApplicationContext("spring.xml");
//得到对应的实例化对象
UserService userService = (UserService) ac.getBean("userService");
userService.test();
2.ioc
2.1依赖注入
2.1.1 手动(静态)注入
使用标签内部的标签
set方法注入 (注意要在目标的类中set对应的private属性)
name : 属性字段的名称
value : 具体的值
ref : 对应的bean标签的id属性值
具体标签
<bean id="typeService" class="com.heyongqiang.service.TypeService">
<property name="typeDao" ref="typeDao"></property>
<property name="host" value="localhost"></property>
</bean>
构造器注入 (注意要在对应的类中生成构造器)
通过constructor-arg
name: 属性字段的名称
ref : 对应bean标签的id
value: 具体的值
index: 参数的下标
具体标签
<bean id="typeService" class="com.heyongqiang.service.TypeService">
<constructor-arg name="typeDao" ref="typeDao"/>
<constructor-arg name="host" value="localhost"/>
<constructor-arg name="code" value="8080"/>
</bean>
2.1.2 自动注入(注解)
首先开启自动注入
<context:annotation-config/>
然后在配置对应的bean标签
<bean id="typeService" class="com.heyongqiang.service.TypeService"><bean>
最后在指定的private上加入对应的resource就可以了
@Resource注解
实现bean对象的自动注入
- 默认会根据bean标签的id属性值查找 (属性字段名和bean标签的id属性值相等)
- 如果属性名称未找到 则会根据class查找
- 属性字段可以提供set方法 也可以不提供
- 注解可以申明在属性级别 或者 set方法级别
- .可以设置注解的name属性 但是设置了name那么 name属性值 必须要和bean标签的id属性值一致
- .如果注入的是接口 接口只有一个实现类的时候可以正常注入 但是多个实现类就要使用id来表示一下具体的实现类
@Autowired
也是实现bean对象的自动注入
-
.默认根据类型(class) 查找 和属性字段名称无关
-
.属性字段可以提供set方法 也可以不提供
-
.注解可以申明在属性级别 或者 set方法级别
-
.如果许哟啊设置属性字段通过id属性值查找 则需要结合@QuaLifier注解使用 并设置注解的value属性值 (value属性值和bean标签id属性值一致)
2.2扫描器
因为bean的标签书写太多 因此就出现了扫描器 可以在对应的类上加上对应的扫描器 这样就不用在xml中书写bean了 开启自动扫描 设置扫描包的范围 可以对bean对象进行统一的管理 简化配置信息 提高开发效率
使用
- .在配置文件中开启自动扫描 设置扫描范围 (引用 context命名空间)
- .在许哟啊实例化的bean对象上添加指定的注解 (声明在类级别 bean对象的id属性默认是 首字母的小写)
Controller 层(控制层)
@Controller
Service层: (业务逻辑)
@Service
Dao层 : (数据访问层)
@Repository
任意类
@Component
注 : 开发过程中建议按照指定的规则声明注解
实例:
<context:component-scan base-package="com.heyongqiang"/>
3.bean
作用域
1.单例作用域 (singleton作用域)
spring容器在启动时会实例化bean对象 并将对象设置到单例缓存池中 下次获取的时候会直接从缓存中得到
scope = "singleton" 默认情况下 spring容器中加载的bean对象都是单例
lazy-init属性
表示懒加载 默认是false
如果值为true表示容器在启动时不会自动实例化bean对象 而是在程序调用的时候才会实例化
如果false那么容器一启动就会实例化bean对象
为什么要设置false
1.可以提前发现配置的潜在问题
2.bean对象在缓存中 调用的效率高
什么对象好设置为单例
无状态或者不可改变的对象(不存在会改变对象状态的成员变量)
2.原型作用域
spring容器在启动的时候会实例化bean对象 不会将对象设置到单例缓存池中 每次请求都会重新创建一个新的bean对象
scope = "prototype"
生命周期
在spring容器中bean的生命周期分为4个阶段 定义 初始化 使用 销毁
1.定义
在配置文件中定义bean标签设置id和class属性值就是定义
2.初始化
在spring 容器中默认启动的时候初始化
spring查看实例化的两种方式
- .在bean标签上设置init-method属性 属性值对应bean对象中的方法 当bean对象实例化时 方法会被调用
- .实现 org.springframework.beans.factory.InitializingBead接口 接口中的方法会在bean对象实例化时调用
使用
- ApplicationContext ac = new ClassPathCmlApplication(“配置文件”); ac.getBead(“id属性”)
- BeanFactory ac = new ClassPathXmlApplicationContext(“配置文件”)ac,getBead(“id属性”)
销毁
- 通过AbstractApplicationContext 对象 调用close方法实现bean的销毁过程
- 通过在bean标签上设置destroy-method方法 查看销毁时机
4.task定时任务
4.1 使用注解
首先加入task自动解析
<task:annotation-driven/>
然后在对应的方法上加上注解
@Scheduled(cron = "0/2 * * * * ?")
4.2使用手动配置xml
首先在对应的xml中加入 (会根据ref的类名查找 通过method定位到方法)
<task:scheduled-tasks>
<task:scheduled ref="taskJob" method="job1" cron="0/2 * * * * ?"/>
<task:scheduled ref="taskJob" method="job2" cron="0/5 * * * * ?"/>
</task:scheduled-tasks>
cron表达式的详解
“0 0 12 * * ?” 每天中午12点触发
“0 15 10 ? * *” 每天上午10:15触发
“0 15 10 * * ?” 每天上午10:15触发
“0 15 10 * * ? *” 每天上午10:15触发
“0 15 10 * * ? 2005” 2005年的每天上午10:15 触发
“0 * 14 * * ?” 在每天下午2点到下午2:59期间的每1分钟触发
“0 0/5 14 * * ?” 在每天下午2点到下午2:55期间的每5分钟触发
“0 0/5 14,18 * * ?” 在每天下午2点到2:55期间和下午6点到6:55期间的每5分钟触发
“0 0-5 14 * * ?” 在每天下午2点到下午2:05期间的每1分钟触发
“0 10,44 14 ? 3 WED” 每年三月的星期三的下午2:10和2:44触发
“0 15 10 ? * MON-FRI” 周一至周五的上午10:15触发
“0 15 10 15 * ?” 每月15日上午10:15触发
“0 15 10 L * ?” 每月最后一日的上午10:15触发
“0 15 10 ? * 6L” 每月的最后一个星期五上午10:15触发
“0 15 10 ? * 6L 2002-2005” 2002年至2005年的每月的最后一个星期五上午10:15触发
“0 15 10 ? * 6#3” 每月的第三个星期五上午10:15触发
0 6 * * * 每天早上6点
0 /2 * * 每两个小时
0 23-7/2,8 * * * 晚上11点到早上8点之间每两个小时,早上八点
0 11 4 * 1-3 每个月的4号和每个礼拜的礼拜一到礼拜三的早上11点
5.代理模式
使用jdk的反射机制,创建对象的能力, 创建的是代理类的对象。 而不用你创建类文件。不用写java文件。
5.1静态代理
有父类或者父接口
实际上就是两个类一个代理类 一个目标类 一个共同的接口
在代理类中通过构造器得到目标类class 然后使用该类重写共同接口的方法
5.2 cglib动态代理
具体的类可以看jdkProxy类和cglib类
区别是jdk动态代理必须要目标类有一个接口 不然无法使用
而cglib不需要有接口
实现原理
代理类继承了委托类, 在代理方法中, 会判断是否存在实现了 MethodInterceptor 接口的对象, 若存在则调用对象的 invoke() 方法, 对委托方法进行代理.
cglib的 enhancer
Enhancer 创建代理对象的大概步骤如下:
1.生成代理类 Class 二进制字节码.
2.通过 Class.forname() 加载字节码文件, 生成 Class 对象.
3.通过反射机制获得实例构造, 并创建代理类对象.原理可以看类
5.3 jkd动态代理
代理类继承 Proxy 类, 并且实现委托类接口, 主要通过代理类调用 InvocationHandler 实现类的重写方法 invoke() 来实现动态代理.
创建接口,定义目标类要完成的功能
创建目标类实现接口
创建InvocationHandler接口的实现类,在invoke方法中完成代理类的功能
- 调用目标方法
- 增强功能
使用Proxy类的静态方法,创建代理对象。 并把返回值转为接口类型。
6.aop 面向切片编程
定义切面
切面是 切入点 通知的结合
在切面类中定义切入点何通知
切入点:定义规则 定义切面而要拦截那些类那些方法
通知 : 方法拦截后要做什么事情
6.1注解实现
首先在xml中加上自动代理
<aop:aspectj-autoproxy/>
定义切面类
@Component //将类交给ioc容器实例化
@Aspect //声明当前类是一个切面类
定义切入点
通过@Pointcut定义规则
1.拦截所有的方法
@Pointcut("execution(* * (..))")
2.拦截所有共有的set方法
@Pointcut("execution(public set*(..))")
3.拦截com.heyongqiang.service下面的所有方法
@Pointcut("execution(* com.heyongqiang.service.*.*(..))")
4.拦截com.heyongqiang.service包及其自包下的所有类的所有方法
@Pointcut("execution(* com.heyongqiang.service..*.*(..))")
ips: 规则表达式第一个位置表示方法的修饰范围
使用通知
@Before(value = "cut()") 前置通知
@AfterReturning(value = "cut()") 返回通知
@After(value = "cut()") 最终通知 应用在指定的切入点上
@AfterThrowing(value = "cut()" , throwing = "e") 异常通知
@Around(value = "cut()") 环绕通知 (可以定义其他的四种通知
6.2xml文件实现
繁琐没看
7.spring事物 集成mybatis
事务是mysql的一种处理方式
7.1xml配置
首先开启注解支持
<tx:annotation-driven transaction-manager="txManager"/>
然后 配置事物管理器
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
接着 设置事物增强 (这里的tx使用表示将以name开头的方法都设置为事物)
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="add" propagation="REQUIRED"/>
<tx:method name="insert" propagation="REQUIRED"/>
<tx:method name="update" propagation="REQUIRED"/>
<tx:method name="delete" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>
</tx:advice>
最后aop切面配置
<aop:config>
<aop:pointcut id="serviccePointcut" expression="execution(* com.heyongqiang02.service..*.*(..))"/>
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviccePointcut"/>
</aop:config>
7.2使用注解
首先配置事物管理器
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
然后配置注解支持
<tx:annotation-driven transaction-manager="txManager"/>
最后在指定方法上加入注解
@Transactional(propagation = Propagation.REQUIRED)
总结
学就完事了