spring原理 ioc和aop

spring核心是面向接口编程

一、ioc(控制反转 inverse of control)由spring框架管理对象,而不需要自己去new对象

spring属性注入的过程:

格式如下:

<bean name="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory ">
        <property name="brokerURL" value="tcp://localhost:61616" />
    </bean>

    <bean name="jmsTemplate" class="org.springframework.jms.core.JmsTemplate">
        <property name="connectionFactory" ref="connectionFactory" />
    </bean>

 

1、去配置文件中找属性对应的类型

2、从bean容器中去找这个类型的对象

3、如果不存在:Class.forName("类名全路径").newInstance();生成这个对象

4、调用属性的set方法:

①根据属性名拼接处set方法名;

②根据方法名从类中获取方法的对象:o.getClass().getMethod("方法名",beanObject.getClass().getInterfaces()[0]);

③调用set方法:m.invoke(o,beanObject);

 

spring注入对象的四种方式:

1、使用set方法注入

package com.bless.springdemo.action;  
public class SpringAction {  
        //注入对象springDao  
    private SpringDao springDao;  
        //一定要写被注入对象的set方法  
        public void setSpringDao(SpringDao springDao) {  
        this.springDao = springDao;  
    }  
  
        public void ok(){  
        springDao.ok();  
    }  
}  
 <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(1)依赖注入,配置当前类中相应的属性-->  
        <property name="springDao" ref="springDao"></property>  
    </bean>  
<bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  

2、使用构造方法注入

public class SpringAction {  
    //注入对象springDao  
    private SpringDao springDao;  
    private User user;  
      
    public SpringAction(SpringDao springDao,User user){  
        this.springDao = springDao;  
        this.user = user;  
        System.out.println("构造方法调用springDao和user");  
    }  
          
        public void save(){  
        user.setName("卡卡");  
        springDao.save(user);  
    }  
}  
 <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(2)创建构造器注入,如果主类有带参的构造方法则需添加此配置-->  
        <constructor-arg ref="springDao"></constructor-arg>  
        <constructor-arg ref="user"></constructor-arg>  
    </bean>  
        <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  
         <bean name="user" class="com.bless.springdemo.vo.User"></bean>  

3、使用静态工厂方法注入

ackage com.bless.springdemo.factory;  
  
import com.bless.springdemo.dao.FactoryDao;  
import com.bless.springdemo.dao.impl.FactoryDaoImpl;  
import com.bless.springdemo.dao.impl.StaticFacotryDaoImpl;  
  
public class DaoFactory {  
    //静态工厂  
    public static final FactoryDao getStaticFactoryDaoImpl(){  
        return new StaticFacotryDaoImpl();  
    }  
}  
<!--配置bean,配置后该类由spring管理-->  
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction" >  
        <!--(3)使用静态工厂的方法注入对象,对应下面的配置文件(3)-->  
        <property name="staticFactoryDao" ref="staticFactoryDao"></property>  
                </property>  
    </bean>  
    <!--(3)此处获取对象的方式是从工厂类中获取静态方法-->  
    <bean name="staticFactoryDao" class="com.bless.springdemo.factory.DaoFactory" factory-method="getStaticFactoryDaoImpl"></bean> 

4、使用实例工厂的方式注入

public class DaoFactory {  
    //实例工厂  
    public FactoryDao getFactoryDaoImpl(){  
        return new FactoryDaoImpl();  
    }  
}  
<!--配置bean,配置后该类由spring管理-->  
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(4)使用实例工厂的方法注入对象,对应下面的配置文件(4)-->  
        <property name="factoryDao" ref="factoryDao"></property>  
    </bean>  
      
    <!--(4)此处获取对象的方式是从工厂类中获取实例方法-->  
    <bean name="daoFactory" class="com.bless.springdemo.factory.DaoFactory"></bean>  
    <bean name="factoryDao" factory-bean="daoFactory" factory-method="getFactoryDaoImpl"></bean>  

名词解释:

①依赖注入(DI dependance injection):接口调用的方法依赖于注入的是哪个实现;类中的对象依赖于配置文件中的注入的对象,这个过程有spring来控制

 

 

 

二、AOP(面向切面 Aspect Oriented Programming)

问题:

在已有业务的前后添加新的业务逻辑

a、直接在代码前后添加新的代码;b、继承原有的实现类,派生出一个新的实现类;c、和原来的实现类实现相同的接口,引入原来的实现的一个对象,调用原来的实现;

d、将要嵌入的逻辑抽象为一个类,然后和原来的实现进行组合,使用动态代理产生新的类(没有实现接口的类无法产生动态代理);

动态代理的一个演示:

建立一个InvocationHandler:

package com.hy.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * 动态代理的测试类
 * @author Administrator
 *
 */
public class LogIntercepter implements InvocationHandler{
    
    private Object target;//被代理对象
    
    private void beforeMethod() {
        System.out.println("method start...");
    }
    
    private void afterMethod() {
        System.out.println("method end...");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        beforeMethod();
        method.invoke(target, args);//调用被代理对象的方法
        afterMethod();
        return null;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }
    
    
}

测试生成代理对象:

package com.hy.aop;

import java.lang.reflect.Proxy;

import org.junit.Test;

import com.hy.dao.UserDAO;
import com.hy.dao.impl.UserDAOImpl;

/**
 * 测试产生代理对象
 * @author Administrator
 *
 */
public class TestProxy {
    
    
    @Test
    public void testProxy() {
        //生成被代理对象
        UserDAO userDAO = new UserDAOImpl();
        LogIntercepter li = new LogIntercepter();
        li.setTarget(userDAO);//将被代理对象交给InvocationHandler
        UserDAO userDAOProxy = (UserDAO)Proxy.newProxyInstance(userDAO.getClass().getClassLoader(), userDAO.getClass().getInterfaces(), li);//生成代理对象
        userDAOProxy.save();
    }
    
}

这样就把我们需要的日志业务插入到保存的业务当中了。

动态代理应用:日志、权限、事务、性能检测

 

sping aop是使用aspectj实现,aspectj是一种专门产生动态代理或者面向切面编程的框架。

spring只能在自己管理的bean上织入业务逻辑

1、bean使用Component注解然后定义扫描的包<context:component-scan base-package=""/>

2、<aop:aspectj-autoproxy /> 对Apect注解的类按照AspectJ语法自动生成代理。

一个简单的示例:

package com.hy.aop;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

/**
 * 动态代理的测试类
 * @author Administrator
 *
 */
@Component
@Aspect
public class LogIntercepter implements InvocationHandler{
    
    private Object target;//被代理对象
    
    @Before("execution(public void com.hy.dao.impl.UserDAOImpl.save())")
    private void beforeMethod() {
        System.out.println("method start...");
    }
    
    private void afterMethod() {
        System.out.println("method end...");
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {
        beforeMethod();
        method.invoke(target, args);//调用被代理对象的方法
        afterMethod();
        return null;
    }

    public Object getTarget() {
        return target;
    }

    public void setTarget(Object target) {
        this.target = target;
    }
    
    
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.3.xsd">

    <!-- <context:annotation-config /> -->
    <context:component-scan base-package="com.hy"></context:component-scan>
    <aop:aspectj-autoproxy />

</beans>
package com.hy.dao.impl;

import org.springframework.stereotype.Component;

import com.hy.dao.UserDAO;

@Component
public class UserDAOImpl implements UserDAO{

    @Override
    public void save() {
        System.out.println("user save...");
    }

}

 

posted on 2017-02-27 13:04  _故乡的原风景  阅读(349)  评论(0编辑  收藏  举报