spring学习2
使用注解配置spring
步骤:
1. 导包4(core/bean/context/spel)+1(logging)+spring-aop包(新版spring需要导入这个包)
2. 为主配置文件引入新的命名空间(约束) Context约束
3. 开启使用注解代理配置文件
<context:component-scan base-package="com.domain"> 指定扫描 com.domain包下面所有类的注解(同时会扫描子包里面的类)
4. 在类中使用注解完成配置
@Component("user")public class User {
private String name;
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
@Override
public String toString() {
return "User [name=" + name + ", age=" + age + ", car=" + car + "]";
}
}
将对象注册到容器
@Component(“user”)
@Service(“user”) service层
@Controller(“user”) web层
@Repository(“user”) dao层
本质上这四个功能都是一样 只是为了见名知意
修改对象的作用范围
@Scope(scopeName=”prototype”) 指定对象的作用范围 同样也是作用在实体上面
值类型注入
@Value("tom")
private String name;
通过反射来为Field赋值 ,但是这样破坏了封装性
通过set方法来赋值 推荐使用
@Value("24")
public void setAge(Integer age) {
this.age = age;
}
引用类型注入
1.使用AutoWired 自动装配
@Component("user")
public class User {
@Autowired
private Car car;
setCar/getCar ...
}
@Component
class Car{
private String cName;
private String color;
get/set ...
} 注意:使用自动装配,被装配的字段 也要在容器有 可以没有名字
这种方式有一个坏处:如果匹配多个类型一致的对象,将无法选择具体注入哪一个对象
解决办法:使用 Qualifier("car") 通过该注解来告诉 spring容器自动装配哪个名称的对象
注意:Qualifier和AutoWired要一起使用
@Resource(name="car") 手动注入,指定注入哪个名称的对象
@Resource(name="car")
private Car car;
初始化 | 销毁方法
@PostConstruct // 在对象被创建以后调用 相当于配置文件中定义的init-method
public void init() {
System.out.println("init method");
} @PreDestroy // 在对象被销毁前调用 destory-method
public void destory(){
System.out.println("destory method");
}
spring与junit整合测试
1.导包 4+2+aop+test
2.配置注解
@RunWith(SpringJUnit4ClassRunner.class) // 帮我们创建容器
@ContextConfiguration("classpath:applicationContext.xml") //指定创建容器时使用的配置文件
public class Student { @Value("wanglei")
private String name; @Test
public void test() {
System.out.println(name);
} @Value("24")
private Integer age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
spring中的aop
aop思想介绍 横向重复代码 ,纵向抽取
例如:解决乱码问题 管理事务 action拦截器
spring中的aop概念 ------> spring能够为容器中管理的对象生成动态代理对象
以前我们要使用动态代理,需要自己调用下面的方法
Proxy.newProxyInstance(xx,xx,xx) 生成代理对象
现在spring能够帮助我们生成代理对象
spring实现aop的原理
1.动态代理(优先) : 被代理对象必须要实现接口,才能产生代理对象,如果没有接口将不能使用动态代理技术。
2.cglib代理(没有接口) : 第三方代理技术,cglib代理可以对任何类生成代理,代理的原理是对目标对象进行继承代理.
但是如果目标对象被final修饰,那么该类无法被cglib代理.
步骤:
1.创建service的接口是实现类
public interface UserService {
void save();
void add();
void delete();
void find();
}
public class UserServiceIml implements UserService {
public void save() {
System.out.println("save");
}
public void add() {
System.out.println("add");
}
public void delete() {
System.out.println("delete");
}
public void find() {
System.out.println("find");
}
}
2.使用cglib代理生成代理对象
public class Test implements MethodInterceptor{
public UserService getService() {
Enhancer en=new Enhancer(); //用于生成代理对象
en.setSuperclass(UserServiceIml.class);//对谁设置代理
en.setCallback(this); //代理要做什么
UserService service = (UserService) en.create();//创建代理对象
return service;
}
@Override proxyObj 目标类的实例 method 目标类方法的反射实例 arg 参数 methodProxy 代理类实例
public Object intercept(Object proxyObj, Method method, Object[] arg, MethodProxy methodProxy) throws Throwable {
System.out.println("打开事务!");
Object returnValue = methodProxy.invokeSuper(proxyObj, arg);
System.out.println("提交事务!");
return returnValue;
}
}
3.测试
public static void main(String[] args) {
Test test = new Test();
UserService service = test.getService();
service.save();
}
AOP名词学习
Joinpoint(连接点):目标对象中,所有可以增强的方法
Pointcut(切入点): 目标对象,已经增强的方法
Advice(通知/增强):增强的代码
Target(目标对象): 被代理的对象
Weaving(织入):将通知应用到切入点的过程
Proxy(代理):将通知织入到目标对象之后,形成代理对象
Aspect(切面):切入点 + 通知
spring中的aop演示
步骤:
1.导包4(core + bean + spel + context)+2 + 2(aop + aspect) + 2(allowiance + weaving)
aop包 + aspect包 + aopalliance + weaver

2.准备目标对象

用到spring2.5版本的jar文件,如果用jdk1.7可能会有问题
需要升级aspectj组件,即使用aspectj-1.8.2版本中提供jar文件提供
3.准备通知
前置通知 目标方法运行之前调用
后置通知(如果出现异常不会调用) 在目标方法运行之后调用
环绕通知 在目标方法之前和之后都调用
异常拦截通知:如果出现异常,就会调用
后置通知(无论是否出现异常都会调用) :在目标方法运行之后调用
public class MyAdvice {
//前置通知
public void before() {
System.out.println("前置通知");
}
//后置通知
public void afterReturn() {
System.out.println("后置通知(如果出现异常不会被调用)");
}
//环绕通知
public Object around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("这是环绕通知之前的部分");
Object proceed = pjp.proceed();//调用目标方法
System.out.println("这是环绕通知之后的部分");
return proceed;
}
//异常拦截通知
public void afterException() {
System.out.println("出现异常了");
}
//后置通知
public void after() {
System.out.println("后置通知(出现异常也会调用)");
}
}
4.配置进行织入,将通知织入目标对象中
准备工作:导入AOP(约束)命名空间
1.配置目标对象 将具体的实现类(而不是接口添加进来) 因为是为 实现类来创建代理对象
<bean name="userService" class="..."></bean>
2.配置通知对象
<bean name="myAdvice" class="...">
3.配置切入点
<aop:pointcut expression="execution(* cn.itcast.service.*ServiceImpl.*(..))" id="pc"/>
execution有以下几种形式
public void cn.itcast.service.UserServiceImpl.save() 具体的某个方法
void cn.itcast.service.UserServiceImpl.save()
* cn.itcast.service.UserServiceImpl.save() 任意返回值
* cn.itcast.service.UserServiceImpl.*() 任意方法名/任意返回值
* cn.itcast.service.*ServiceImpl.*(..) 任意参数/ 任意返回值/ 任意方法名
* cn.itcast.service..*ServiceImpl.*(..) 还会找这个下面的子包
<aop:config>
<aop:pointcut expression="execution(* com.domin.*Service.*(..))" id="pc"/> //表示拦截哪些方法
<aop:aspect ref="advice">
<aop:before method="before" pointcut-ref="pc"/>
<aop:around method="around" pointcut-ref="pc"/>
<aop:after-throwing method="afterException" pointcut-ref="pc"/>
<aop:after method="after" pointcut-ref="pc"/>
<aop:after-returning method="afterReturn" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>
<!-- 【拦截所有public方法】 -->
<!--<aop:pointcut expression="execution(public * *(..))" id="pt"/>--> <!-- 【拦截所有save开头的方法 】 -->
<!--<aop:pointcut expression="execution(* save*(..))" id="pt"/>--> <!-- 【拦截指定类的指定方法, 拦截时候一定要定位到方法】 -->
<!--<aop:pointcut expression="execution(public * cn.itcast.g_pointcut.OrderDao.save(..))" id="pt"/>--> <!-- 【拦截指定类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.*(..))" id="pt"/>--> <!-- 【拦截指定包,以及其自包下所有类的所有方法】 -->
<!--<aop:pointcut expression="execution(* cn..*.*(..))" id="pt"/>--> <!-- 【多个表达式】 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) || execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) or execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!-- 下面2个且关系的,没有意义 -->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) && execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<!--<aop:pointcut expression="execution(* cn.itcast.g_pointcut.UserDao.save()) and execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>--> <!-- 【取非值】 -->
<!--<aop:pointcut expression="!execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/>-->
<aop:pointcut expression=" not execution(* cn.itcast.g_pointcut.OrderDao.save())" id="pt"/> <!-- 切面 -->
<aop:aspect ref="aop">
<!-- 环绕通知 -->
<aop:around method="around" pointcut-ref="pt"/>
</aop:aspect>
调用顺序
1.没有发生异常的情况下
前置通知
这是环绕通知之前的部分
save method
这是环绕通知之后的部分
后置通知(出现异常也会调用)
后置通知(如果出现异常不会被调用)
2.发生异常的情况下
前置通知
这是环绕通知之前的部分
出现异常了
后置通知(出现异常也会调用)
注解配置实现动态代理
1.导包
2.配置
同样需要加入 <bean name="userService" class="..."></bean> 和 <bean name="myAdvice" class="...">
3.使用注解来实现代理
4.在配置文件中加入 <aop:aspectj-autoproxy></aop:aspectj-autoproxy> 表示开启使用注解完成织入
5.测试
@Aspect 指定一个类为切面类
@Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))") 指定切入点表达式
@Before("pointCut_()") 前置通知: 目标方法之前执行
@After("pointCut_()") 后置通知:目标方法之后执行(始终执行)
@AfterReturning("pointCut_()") 返回后通知: 执行方法结束前执行(异常不执行)
@AfterThrowing("pointCut_()") 异常通知: 出现异常时候执行
@Around("pointCut_()") 环绕通知: 环绕目标方法执行
@Component
@Aspect // 指定当前类为切面类
public class Aop { // 指定切入点表单式: 拦截哪些方法; 即为哪些类生成代理对象 @Pointcut("execution(* cn.itcast.e_aop_anno.*.*(..))")
public void pointCut_(){
} // 前置通知 : 在执行目标方法之前执行
@Before("pointCut_()")
public void begin(){
System.out.println("开始事务/异常");
} // 后置/最终通知:在执行目标方法之后执行 【无论是否出现异常最终都会执行】
@After("pointCut_()")
public void after(){
System.out.println("提交事务/关闭");
} // 返回后通知: 在调用目标方法结束后执行 【出现异常不执行】
@AfterReturning("pointCut_()")
public void afterReturning() {
System.out.println("afterReturning()");
} // 异常通知: 当目标方法执行异常时候执行此关注点代码
@AfterThrowing("pointCut_()")
public void afterThrowing(){
System.out.println("afterThrowing()");
}
// 环绕通知:环绕目标方式执行
@Around("pointCut_()")
public void around(ProceedingJoinPoint pjp) throws Throwable{
System.out.println("环绕前....");
pjp.proceed(); // 执行目标方法
System.out.println("环绕后....");
}
}
<!-- 开启注解扫描 -->
<context:component-scan base-package="cn.itcast.e_aop_anno"></context:component-scan> <!-- 开启aop注解方式 -->
<aop:aspectj-autoproxy></aop:aspectj-autoproxy>
Spring Web Spring对web模块的支持。
可以与struts整合,让struts的action创建交给spring
spring mvc模式
Spring DAO Spring 对jdbc操作的支持 【JdbcTemplate模板工具类】
Spring ORM spring对orm的支持:
既可以与hibernate整合,【session】
也可以使用spring的对hibernate操作的封装
SpringEE spring 对javaEE其他模块的支持
spring学习2的更多相关文章
- spring 学习之 bean 的注入方式 property和constructor-arg的使用方式
spring 学习之 bean 的注入方式 property和constructor-arg的使用方式. bean的注入方式: property 注入是: 通过setxx方法注入. construct ...
- Spring学习之AOP总结帖
AOP(面向方面编程),也可称为面向切面编程,是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP). 在进行 OOP 开发时,都是基于对组件(比如类)进行开发,然后对组件进行组 ...
- Spring学习之第一个AOP程序
IOC和AOP是Spring的两大基石,AOP(面向方面编程),也可称为面向切面编程,是一种编程范式,提供从另一个角度来考虑程序结构从而完善面向对象编程(OOP). 在进行 OOP 开发时,都是基于对 ...
- MyEclipse Spring 学习总结三 SpringMVC
MyEclipse Spring 学习总结三 SpringMVC 一.SpringMVC原理 1.Springmvc 框架介绍 1)Spring 框架停工了构建Web应用程序的全功能MVC模块.Spr ...
- Spring学习 Ioc篇(一 )
一直以来忙于项目的开发,Spring虽然不用,一直想系统地学习一下,想看看它的源码,都没有时间,这段时间比较充裕,就索性先把Spring学习下,熟悉各个功能再去探究它内部的实现.就从Ioc篇开始学习. ...
- Spring学习(三)——Spring中的依赖注入的方式
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...
- Spring学习(二)——Spring中的AOP的初步理解[转]
[前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring. ...
- 【Spring学习笔记-MVC-3.1】SpringMVC返回Json数据-方式1-扩展
<Spring学习笔记-MVC>系列文章,讲解返回json数据的文章共有3篇,分别为: [Spring学习笔记-MVC-3]SpringMVC返回Json数据-方式1:http://www ...
- Spring学习8-Spring事务管理
http://blog.sina.com.cn/s/blog_7ffb8dd501014e0f.html Spring学习8-Spring事务管理(注解式声明事务管理) 标签: spring注 ...
- Spring学习之Ioc控制反转(1)
开始之前: 1. 本博文为原创,转载请注明出处 2. 作者非计算机科班出身,如有错误,请多指正 ---------------------------------------------------- ...
随机推荐
- 推荐一款移动端小视频App声咖视频
推荐一款移动端小视频App声咖视频 1 介绍 声咖app,这款软件是一款声音交友社交软件,在上面你可以轻松互动,找到你的知心朋友,并且可以自由添加好友,与其他人互动,让交友更加轻松!, 2 特色功能介 ...
- 国家虚拟仿真实验教学项目共享平台(实验空间)PHP SDK
使用XJWT标准,此标准基于JSON Web Token (JWT)开发.XJWT包含三个参数:header, payload, signature,因此生成token就要先获得这三个参数. clas ...
- ucore实验Lab1知识点总结
Intel 80386 ucore目前支持的硬件环境是基于Intel 80386以上的计算机系统. Intel 80386是80x86系列中的第一种32位微处理器.80386的内部和外部数据总线都是3 ...
- 极简 Spring Boot 整合 Thymeleaf 页面模板
虽然现在慢慢在流行前后端分离开发,但是据松哥所了解到的,还是有一些公司在做前后端不分的开发,而在前后端不分的开发中,我们就会需要后端页面模板(实际上,即使前后端分离,也会在一些场景下需要使用页面模板, ...
- Python 学习:常用函数整理
整理Python中常用的函数 一,把字符串形式的list转换为list 使用ast模块中的literal_eval函数来实现,把字符串形式的list转换为Python的基础类型list from as ...
- .NET[C#]使用LINQ从List<T>集合中获取最后N条数据记录的方法有哪些?
https://codedefault.com/2018/using-linq-to-get-the-last-n-elements-of-a-collection-in-csharp-applica ...
- jdk8 接口的变化
在jdk8之前,interface之中可以定义变量和方法,变量必须是public.static.final的,方法必须是public.abstract的.由于这些修饰符都是默认的以下写法等价 publ ...
- 用友U9 基础使用文件所在目录
元数据存主位置 D:\yonyou\UBFV50\U9.VOB.Product.Metadata 日志文件位置 D:\yonyou\U9V50\Portal\log UI热插支持文件 D:\yonyo ...
- 我为什么学习Haskell
说起来,Haskell真是相当冷门而小众的一门语言.在我工作第一年的时候,我平时从网络的一些学习资料上时不时看到有人提到这门语言.那时候的认识就是除了我们平时用的“面向对象语言 (OOP: Objec ...
- Python模块File文件操作
Python模块File简介 Python提供了File模块进行文件的操作,他是Python的内置模块.我们在使用File模块的时候,必须先用Popen()函数打开一个文件,在使用结束需要close关 ...