spring - ioc和aop
1.程序中为什么会用到spring的ioc和aop
2.什么是IOC,AOP,以及使用它们的好处,即详细回答了第一个问题
3.原理
关于1:
a:我们平常使用对象的时候,一般都是直接使用关键字类new一个对象,那这样有什么坏处呢?其实很显然的,使用new那么就表示当前模块已经不知不觉的和 new的对象耦合了,而我们通常都是更高层次的抽象模块调用底层的实现模块,这样也就产生了模块依赖于具体的实现,这样与我们JAVA中提倡的面向接口面向抽象编程是相冲突的,而且这样做也带来系统的模块架构问题。很简单的例子,我们在进行数据库操作的时候,总是业务层调用DAO层,当然我们的DAO一般 都是会采用接口开发,这在一定程度上满足了松耦合,使业务逻辑层不依赖于具体的数据库DAO层。但是我们在使用的时候还是会new一个特定数据库的DAO 层,这无形中也与特定的数据库绑定了,虽然我们可以使用抽象工厂模式来获取DAO实现类,但除非我们一次性把所有数据库的DAO写出来,否则在进行数据库 迁移的时候我们还是得修改DAO工厂类,所以我们就思考新的方法
b:
1 public class Hello implements IHello {
2
3 public void sayHello(String name) {
4 // TODO Auto-generated method stub
5 System.out.println("Hello " + name);
6 }
7
8 }
如上图,假设我们要在方法的开始和结束处加上一些业务逻辑,大家想到的最直接的方法,就是在方法前面和后面加上一些代码,如日志,假如不能改变原来的方法了,那你又会想到继承Hello类,重写sayHello方法,如下
public class Hello2 extends Hello {
public void sayHello(String name) {
// TODO Auto-generated method stub
sysstem.out.println("方法前的逻辑");
super.sayHello("。。。。。。");
} }
可能你又会想到,组合的方式
public class Hello3 implements IHello {
private IHello helloDao = new Hello(); public void sayHello(String name) {
// TODO Auto-generated method stub
sysstem.out.println("方法前的逻辑");
helloDao .sayHello("。。。。。。");
} }
假设现在要把这个日志功能加入到20个不同方法的前面,可以考虑把那个日志功能抽离出来封装成一个类的方法,但是那样还是要组合新建20个类,组合20次,如下
public class LogInterceptor {
public void before() {
System.out.println("method before");
}
} public class Hello3 implements IHello {
private IHello helloDao = new Hello(); public void sayHello(String name) {
// TODO Auto-generated method stub
new LogInterceptor().before();
helloDao .sayHello("。。。。。。");
}
} public class hello4 implements 其他接口 {//需要新建类
private IHello qitaDao = new 其他业务类();//需要组合旧的类 public void doHello(String name) {
// TODO Auto-generated method stub
new LogInterceptor().before();
helloDao .sayHello("。。。。。。");
}
}
这样肯定不可靠。我们想新的思路,可以写一个配置文件,在每个需要加日志逻辑的里面,例Hello类的所有方法上配上那个日志类的方法,这样就不用新建20个类,组合20次旧的类,但是问题又来了,程序不会返回你重新组合的那个类(即那个新组合而成的动态类),我们需要思考新的方法
关于2:
IOC:Inversion of Control 控制反转,也叫(Dependency Injection)依赖注入,上述a的逻辑使用IOC,就是DAO接口的实现不再是业务逻辑层调用工厂类去获取,而是通过容器(spring)来自动的为我们的业务层设置DAO的实现类,这样整个过程就反过来,以前是我们业务层主动去获取DAO,而现在是DAO主动被设置到业务逻辑层中来了,这也就是反转控制的由来。通过IOC,我们就可以在不修改任何代码的情况下,无缝的实现数据库的换库迁移
AOP:Aspect Oriented Programming 面向切面编程,上述b的逻辑就使用AOP,就可以解决,他帮助我们生成动态的代理类,织入新的业务逻辑,如事务,日志等等
关于3:
IOC原理:
public class UserService{
//private UserDao userDao = new UserDaoImpl(); //让业务层与数据访问层耦合在一起,不利用以后模块的替换.
private UserDao userDao_IoC = null;
public void setUserDao(UserDao userDao){
this.userDao_IoC = userDao
} public void save(User user){
userDao.save(user);
}
}
//原理:反射
public void ObjectgetInstance(String className) throws Exception {
Object obj = Class.forName(className).newInstance();
Method[] methods = obj.getClass().getMethods();
for (Method method : methods) {
if (method.getName().intern() == "setUserDao") {
method.invoke(obj, "换成实现接口类的名称!");
}
}
}
public class UserService{
//private UserDao userDao = new UserDaoImpl(); //让业务层与数据访问层耦合在一起,不利用以后模块的替换.
private UserDao userDao_IoC = null;
public void setUserDao(UserDao userDao){
this.userDao_IoC = userDao
} public void save(User user){
userDao.save(user);
}
}
//原理:反射
public void ObjectgetInstance(String className) throws Exception {
Object obj = Class.forName(className).newInstance();
Method[] methods = obj.getClass().getMethods();
for (Method method : methods) {
if (method.getName().intern() == "setUserDao") {
method.invoke(obj, "换成实现接口类的名称!");
}
}
}
AOP原理:
package com.s2sh.intercepetor;
public interface IHello {
public void sayHello(String name);
public void sayGoogBye(String name);
}
package com.s2sh.intercepetor;
public class Hello implements IHello {
public void sayGoogBye(String name) {
// TODO Auto-generated method stub
System.out.println(name+" GoodBye!");
}
public void sayHello(String name) {
// TODO Auto-generated method stub
System.out.println("Hello " + name);
}
}
package com.s2sh.intercepetor;
public class Logger {
public static void before() {
System.out.println("开始了");
}
public static void after() {
System.out.println("结束了");
}
}
package com.s2sh.intercepetor;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class DynaProxyHello implements InvocationHandler {
private Object delegate;//被代理的对象
public DynaProxyHello(Object delegate) {
this.delegate = delegate;
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
// TODO Auto-generated method stub
Object result = null;
try {
// 执行原来的方法之前记录日志
Logger.before();
// JVM通过这条语句执行原来的方法(反射机制)
result = method.invoke(this.delegate, args);
// 执行原来的方法之后记录日志
Logger.after();
} catch (Exception e) {
e.printStackTrace();
}
// 返回方法返回值给调用者
return result;
}
}
package com.s2sh.intercepetor;
import java.lang.reflect.Proxy;
public class Test {
public static void main(String[] args) {
// ①目标业务类
IHello target = new Hello();
// ② 将目标业务类和横切代码编织到一起
DynaProxyHello handler = new DynaProxyHello(target);
// 创建代理类
IHello proxy = (IHello) Proxy.newProxyInstance(
target.getClass().getClassLoader(), //返回目标类的类装载器,保持两个类的类装载器一样
target.getClass().getInterfaces(), //返回目标类实现的接口,保证组合而成的代理类也实现这些接口
handler//指派谁去处理方法的对象
);
// ④ 操作代理实例
proxy.sayHello("张三");
proxy.sayGoogBye("李四");
}
}
1 package com.s2sh.intercepetor;
2
3
4 public interface IHello {
5 public void sayHello(String name);
6
7 public void sayGoogBye(String name);
8 }
9
10
11 package com.s2sh.intercepetor;
12
13 public class Hello implements IHello {
14
15
16 public void sayGoogBye(String name) {
17 // TODO Auto-generated method stub
18 System.out.println(name+" GoodBye!");
19 }
20
21
22 public void sayHello(String name) {
23 // TODO Auto-generated method stub
24 System.out.println("Hello " + name);
25 }
26
27 }
28
29 package com.s2sh.intercepetor;
30
31
32 public class Logger {
33 public static void before() {
34 System.out.println("开始了");
35 }
36
37 public static void after() {
38 System.out.println("结束了");
39 }
40 }
41
42
43
44 package com.s2sh.intercepetor;
45
46 import java.lang.reflect.InvocationHandler;
47 import java.lang.reflect.Method;
48 import java.lang.reflect.Proxy;
49
50
51 public class DynaProxyHello implements InvocationHandler {
52 private Object delegate;//被代理的对象
53
54 public DynaProxyHello(Object delegate) {
55 this.delegate = delegate;
56 }
57 public Object invoke(Object proxy, Method method, Object[] args)
58 throws Throwable {
59 // TODO Auto-generated method stub
60 Object result = null;
61 try {
62 // 执行原来的方法之前记录日志
63 Logger.before();
64 // JVM通过这条语句执行原来的方法(反射机制)
65 result = method.invoke(this.delegate, args);
66 // 执行原来的方法之后记录日志
67 Logger.after();
68 } catch (Exception e) {
69 e.printStackTrace();
70 }
71 // 返回方法返回值给调用者
72 return result;
73 }
74
75
76 }
77
78
79 package com.s2sh.intercepetor;
80
81 import java.lang.reflect.Proxy;
82
83 public class Test {
84 public static void main(String[] args) {
85 // ①目标业务类
86 IHello target = new Hello();
87 // ② 将目标业务类和横切代码编织到一起
88 DynaProxyHello handler = new DynaProxyHello(target);
89 // 创建代理类
90 IHello proxy = (IHello) Proxy.newProxyInstance(
target.getClass().getClassLoader(), //返回目标类的类装载器,保持两个类的类装载器一样
target.getClass().getInterfaces(), //返回目标类实现的接口,保证组合而成的代理类也实现这些接口
handler//指派谁去处理方法的对象
);
92 // ④ 操作代理实例
93 proxy.sayHello("张三");
94 proxy.sayGoogBye("李四");
95 }
96 }
运行结果:
开始了--
Hello 张三
结束了--
开始了--
李四 GoodBye!
结束了--
spring - ioc和aop的更多相关文章
- 【转】spring - ioc和aop
[转]spring - ioc和aop 1.程序中为什么会用到spring的ioc和aop 2.什么是IOC,AOP,以及使用它们的好处,即详细回答了第一个问题 3.原理 关于1: a:我们平常使用对 ...
- J2EE进阶(十四)超详细的Java后台开发面试题之Spring IOC与AOP
J2EE进阶(十四)超详细的Java后台开发面试题之Spring IOC与AOP 前言 搜狐畅游笔试题中有一道问答题涉及到回答谈谈对Spring IOC与AOP的理解.特将相关内容进行整理. ...
- Spring IOC及AOP学习总结
一.Spring IOC体系学习总结: Spring中有两个容器体系,一类是BeanFactory.还有一类是ApplicationContext.BeanFactory提供了基础的容器功能.Appl ...
- Spring ioc与aop的理解
一 spring的特点 1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦 2.可以使用容易提供的众多服务,如事务管理,消息服务等 3.容器提供单例模式支持 4.容器提供了AOP技术,利用它很容易 ...
- spring IOC与AOP
Spring IOC容器 spring IOC 容器有两种,分别是 BeanFactory 容器和 ApplicationContext 容器. BeanFactory如下: /*第一步,利用Clas ...
- Spring IOC、AOP、Transaction、MVC小结
1.IOC.AOP:把对象交给Spring进行管理,通过面向切面编程来实现一些“模板式”的操作,使得程序员解放出来,可以更多的关注业务实现. - ...
- BeanPostProcessor —— 连接Spring IOC和AOP的桥梁
之前都是从大Boss的视角,来介绍Spring,比如IOC.AOP. 今天换个视角,从一个小喽啰出发,来加深对Spring的理解. 这个小喽啰就是, BeanPostProcessor (下面简称 B ...
- spring IOC 和AOP 方面
spring 的2大核心 是Ioc 和 aop spring的依赖注入:在程序运行期间,由外部容器动态的将依赖对象注入到组件中 IOC: 实例化spring容器的二种方法 第一种:在类路径下寻找配 ...
- 黑马-Spring(IOC&DI) AOP
IOC(控制翻转) 概念 把对象的创建.初始化.销毁等工作交给spring容器来做 案例 环境 步骤 1. 写一个HelloWorld类 2. 写一个配置文件 把hello类放到spring容 ...
随机推荐
- HDU 3491 最小点权割集
题意:有n个城市,m条双向边,有一群小偷从s前往t偷东西,警察叔叔们想要逮捕小偷们,现在告诉你在每座城市需要多少警察才能抓住这个城市的小偷,为什么说这个城市,因为小偷们会分开跑:然后题目还说不能在s和 ...
- LoadRunner参数化MySQL
准备:安装[msql-ODBC驱动] 一.配置数据源 1.Win7,打开控制面板-系统和安全-管理工具,点击“数据源(ODBC)”. 打开数据源(ODBC),在用户DSN选项卡中点击“添加”按钮,弹出 ...
- usb驱动开发9之设备描述符
前面分析了usb的四大描述符之端点描述符,接口描述符(每一个接口对应一个功能,与之配备相应驱动),配置描述符,最后分析设备如何包括这些描述符.首先记住,在usb的世界里,设备大于配置,配置大于接口,接 ...
- 【MFC】WM_GETMINMAXINFO 设置无边框窗口最大花不遮挡任务栏
LRESULT OnGetMinMaxInfo( UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/ ) { ...
- 【转】【C#】C# 不常用关键字
1.__arglist 让我们先从__arglist开始. __arglist是用来给方法传送参数.通常我们是通过函数头部指定的参数列表给方法传递参数的.如果我们想要给方法传递一组新的参数,我们需要重 ...
- Linux经常用到的命令
1. Linux下用vim打开配置文件乱码,在终端输入:“LANG=”即可. 2. 查看端口是否被占用: 3. netstat -anp | grep port netstat -ltn 4. lso ...
- 自定义progressBar的旋转圆圈
在手工打造下拉刷新功能 自带的progressBar太丑了 做个也不费事,一个简单的圆形 旋转动画加type是sweep的gradient渐变 <rotate //旋转动画xmlns:andro ...
- Java系列:关于Java中的桥接方法
这两天在看<Java核心技术 卷1>的泛型相关章节,其中说到了在泛型子类中override父类的泛型方法时,编译器会自动生成一个桥接方法,这块有点看不明白. 书上的例子代码如下: publ ...
- MVC5 + EF6 + Bootstrap3 (8) HtmlHelper用法大全(上)
文章来源:Slark.NET-博客园 http://www.cnblogs.com/slark/p/mvc5-ef6-bs3-get-started-httphelper-part1.html 上一节 ...
- C#出题库项目的总结(2)
前记:好吧好吧,我好好的自我检讨,这个总结拖了这么久才来写,而且一周多没有看技术相关的东西,实在罪过,不过因为想做的事情太多,所以时间的分配确实是一个很严肃的问题,不是时间不够用,是我自己没有做好时间 ...