spring 的2个核心技术:
ioc/di:控制反转/依赖注入
所谓IoC(控制反转),对于spring框架来说,就是由spring来负责控制对象的生命周期和对象间的关系。
IoC的一个重点(DI 依赖注入)是在系统运行中,动态的向某个对象提供它所需要的其他对象(因此又叫DI)。如对象A定义一个引用B(对象),至于这个B对象怎么构造,何时构造,A不需要知道。在系统运行时,spring会在适当的时候制造一个B对象,然后像打针一样,注射到A当中,这样就完成了对各个对象之间关系的控制。A需要依赖B才能正常运行,而这个B是由spring注入到A中的,依赖注入的名字就这么来的。DI原理:Java 1.3之后一个重要特征是反射(reflection),它允许程序在运行的时候动态的生成对象、执行对象的方法、改变对象的属性,spring就是通过反射来实现注入的。
没有spring时:在一个对象中,如果要使用另外的对象,就必须得到它(自己new一个,或者从JNDI中查询一个),使用完之后还要将对象销毁(比如Connection等),对象始终会和其他的接口或类藕合起来。
有spring时:所有的类都会在spring容器中登记,告诉spring你是个什么东西,你需要什么东西,然后spring会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring来控制,也就是说控制对象生存周期的不再是引用它的对象,而是spring。对于某个具体的对象而言,以前是它控制其他对象,现在是所有对象都被spring控制,所以这叫控制反转。
aop:面向切面:
AOP(Aspect-OrientedProgramming,面向方面编程),可以说是OOP(Object-Oriented Programing,面向对象编程)的补充和完善。
AOP的核心思想就是“将应用程序中的商业逻辑同对其提供支持的通用服务进行分离。”
AOP把软件系统分为两个部分:核心关注点和横切关注点。业务处理的主要流程是核心关注点,与之关系不大的部分是横切关注点。横切关注点的一个特点是,他们经常伴随在核心关注点前后使用,而各处都基本相似。比如权限认证、日志、事务处理。
AOP技术,利用一种称为“横切”的技术,剖解开封装的对象内部,并将那些影响了多个类的公共行为封装到一个可重用模块,并将其名为“Aspect”,简单地说,就是将那些与业务无关,却为业务模块所共同调用的逻辑或责任封装起来,便于减少系统的重复代码,降低模块间的耦合度,并有利于未来的可操作性和可维护性。实现AOP的技术,主要分为两大类:一是采用动态代理技术,利用截取消息的方式,对该消息进行装饰,以取代原有对象行为的执行;二是采用静态织入的方式,引入特定的语法创建“方面”,从而使得编译器可以在编译期间织入有关“方面”的代码。 Spring采用动态代理织入,而AspectJ采用编译器织入和类装载期织入。
Spring AOP使用了两种动态代理机制:一种是基于JDK的动态代理,一种是基于CGLib的动态代理。JDK1.3以后,java提供了动态代理技术,允许开发者在运行期间动态的创建接口的代理实例,JDK的动态代理主要涉及到java.lang.reflect包中的两个类:Proxy和InvocationHandler。CGLib采用非常底层的字节码技术,可以为一个类创建子类,并在子类中采用方法拦截的结束拦截所有父类方法的调用,并顺势织入横切逻辑。
基于JDK的动态代理
//创建代理类 (1)实现InvocationHandler接口
class MyProxy implements InvocationHandler{
//(2)创建一个Object引用 接受被代理者
Object obj;
/*(3)创建一个方法 Proxy.newProxyInstance(Foo.class.getClassLoader(),
new Class[] { Foo.class },
handler);
此方法的作用是让this 拥有被代理者obj所具有的所有(接口中)方法
*/
public Object newProxyInstance(Object obj){
//让代理者和被代理者关联
this.obj=obj;
return Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),
this);
}
@Override
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
String methodName=method.getName();
Object result=null;
if(methodName.equals("add")){
System.out.println("我是add方法只向前加的内容————————————");
result=method.invoke(obj, args);
System.out.println("我是add方法执行后加的内容————————————");
}else if(methodName.equals("nihao")){
System.out.println("我是nihao方法只向前加的内容++++++—");
result=method.invoke(obj, args);
System.out.println("我是nihao方法执行后加的内容+++++———");
}else{
System.out.println("我是hehe方法只向前加的内容");
result=method.invoke(obj, args);
System.out.println("我是hehe方法执行后加的内容");
}
System.out.println();
return result;
}
public static void main(String[] args) {
//创建一被代理者
Demo3 d3=new Demo3();
//创建一个代理者
MyProxy mp=new MyProxy();
//让代理者和被代理者关联 产生一个inter2类型的对象
Inter2 i2=(Inter2)mp.newProxyInstance(d3);
//执行i2的方法
i2.hehe();
CGLib的动态代理
//代理类
public class CglibProxy implements MethodInterceptor { // private static CglibProxy proxy = new CglibProxy(); private Enhancer enhancer = new Enhancer(); public Object getProxy(Class clazz) { enhancer.setSuperclass(clazz);// 设置需要创建子类的类 enhancer.setCallback(this); return enhancer.create();// 通过字节码技术动态创建子类实例 } @Override public Object intercept(Object arg0, Method arg1, Object[] arg2, MethodProxy arg3) throws Throwable { PerformanceMonitor.begin(arg0.getClass().getName() + "." + arg1.getName()); Object result = arg3.invokeSuper(arg0, arg2); PerformanceMonitor.end(); return result; } }
//目标类
public class UserServiceImpl{ public void removeUser(int userId) { System.out.println("模拟删除用户:" + userId); } public void addUser(int userId) { // TODO Auto-generated method stub } public static void main(String[] args) { CglibProxy proxy = new CglibProxy();//代理者 UserServiceImpl userService =(UserServiceImpl)proxy.getProxy(UserServiceImpl.class);//生成目标类的代理类 userService.removeUser(7); } }