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!
结束了--

时间: 2024-12-10 08:11:04

spring - ioc和aop的相关文章

Spring IOC及AOP学习总结

一.Spring IOC体系学习总结: Spring中有两个容器体系,一类是BeanFactory.另一类是ApplicationContext.BeanFactory提供了基础的容器功能.ApplicationContext则是基于BeanFactory建立的一套更加丰富的容器体系,基于ApplicationContext构建了Spring AOP体系(基于AOP体系又构建了声明式事务模型),I18n的支持,基于观察者模式的事件模型,多渠道的Bean资源的载入(比如从文件系统,从interne

Spring IOC 和 AOP

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器框架. 1.控制反转(IOC)/依赖注入(DI): 在传统的程序设计中,当调用者须要被调用者的协助时,通常由调用者来创建被调用者的实例. 但在spring里创建被调用者的工作不再由调用者来完毕.因此控制反转(IoC),为什么称为反转呢?反转是相对于正向而言的,那么什么算是正向的呢?考虑一下常规情况下的应用程序,假设要在A里面使用C,你会怎么做呢?当然是直接去创建C的对象,也就是说,是在A类中主动去获取所须要的外部资源C.这样的

spring ioc和aop理解

spring IOC 1.目的:就是解决程序间的依赖关系 2.原理:通过反射原理将我们控制层中的 dao层. service层类以工厂模式在static代码块中实现加载后存放入map中 , 并实现单列 . 原文地址:https://www.cnblogs.com/cwone/p/11939192.html

Spring+IOC(DI)+AOP概念及优缺点

Spring pring是一个轻量级的DI和AOP容器框架. 说它轻量级有一大部分原因是相对与EJB的(虽然本人从没有接触过EJB的应用),重要的是,Spring是非侵入式的,基于spring开发的应用一般不依赖于spring的类. 容器:Spring是个容器,因为它包含并且管理应用对象的生命周期和配置.如对象的创建.销毁.回调等. 框架:Spring作为一个框架,提供了一些基础功能,(如事务管理,持久层集成等),使开发人员更专注于开发应用逻辑. Spring的优点1.降低了组件之间的耦合性 ,

Spring IOC 和 AOP概述

IoC(控制反转,(Inversion of Control):本来是由应用程序管理的对象之间的依赖关系,现在交给了容器管理,这就叫控制反转,即交给了IoC容器,Spring的IoC容器主要使用DI方式实现的. 不需要主动查找,对象的查找.定位和创建全部由容器管理 DI(Dependency Injection) : IOC 的另一种表述方式:即组件以一些预先定义好的方式(例如: setter 方法)接受来自如容器的资源注入. 相对于 IOC 而言,这种表述更直接 1.大量减少了Factory和

对Spring IOC和AOP的理解

控制反转(IOC)是什么?(理解好Ioc的关键是要明确"谁控制谁,控制什么,为何是反转(有反转就应该有正转了),哪些方面反转了") 1.Ioc-Inversion of Control:即"控制反转",不是什么技术,而是一种设计思想.在Java开发中,Ioc意味着将你设计好的对象交给容器控制,而不是传统的在你的对象内部直接控制. 2.谁控制谁,控制什么:传统Java SE程序设计,我们直接在对象内部通过new进行创建对象,是程序主动去创建依赖对象:而IoC是有专门一

Spring IoC和AOP使用扩展(二)

一.IOC的实现方式: Set注入:熟悉必须有公共set方法: 构造器注入:可以根据构造器参数名称.下标注入: p命名空间注入:要求有set方法: 内部bean的实现: <bean id="userService" class="com.service.UserService"> <property name="userDao"> <bean class="com.dao.UserDao">

关于spring,IOC和AOP的解析原理和举例

引用自:https://blog.csdn.net/paincupid/article/details/43152397 IOC:就是DAO接口的实现不再是业务逻辑层调用工厂类去获取,而是通过容器(比如spring)来自动的为我们的业务层设置DAO的实现类.这样整个过程就反过来,以前是我们业务层主动去获取DAO,而现在是DAO主动被设置到业务逻辑层中来了,这也就是反转控制的由来.通过IOC,我们就可以在不修改任何代码的情况下,无缝的实现数据库的换库迁移,当然前提还是必须得写一个实现特定数据库的D

对于Spring IOC 和 AOP 简单理解

IOC IOC(Inversion Of Controll,控制反转)是一种设计思想,将原本在程序中手动创建对象的控制权,交由给Spring框架来管理.IOC容器是Spring用来实现IOC的载体,IOC容器实际上就是一个Map(key, value),Map中存放的是各种对象. 这样可以很大程度上简化应用的开发,把应用从复杂的依赖关系中解放出来.IOC容器就像是一个工厂,当需要创建一个对象,只需要配置好配置文件/注解即可,不用考虑对象是如何被创建出来的,大大增加了项目的可维护性且降低了开发难度