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..."); } }