Spring学习笔记2
2016-12-17 10:11
274 查看
一、自动装配(xml方式、不推荐)
1.一般方式
<bean id="otherBean" class="spring_autowired_xml.OtherBean" /> <bean id="someBean" class="spring_autowired_xml.SomeBean"> <property name="otherBean" ref="otherBean" /> </bean>
2.自动装配
<bean autowire="" /> -default :不自动注入 -no :不自动注入 -byName :按照名字注入(按照属性的名字在spring中找bean) -byType :按照依赖对象的类型注入 -constructor:按照对象的构造器上面的参数类型注入 注意: 1,如果按照byName自动注入,要求所有的属性名字和id的名字必须保证一种规范的命名方式; 2,如果按照byType注入,如果spring中同一个类型有多个实例----报bean不是唯一类型错误;
<bean id="otherBean" class="spring_autowired_xml.OtherBean" /> <bean id="someBean" class="spring_autowired_xml.SomeBean" autowire="byType" />
<bean id="otherBean" class="spring_autowired_xml.OtherBean" /> <bean id="someBean" class="spring_autowired_xml.SomeBean" autowire="byName" />
二、自动装配(注解方式)
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd "> <bean id="otherBean" class="spring_autowired_ann.OtherBean" /> <bean id="otherBean2" class="spring_autowired_ann.OtherBean2" /> <bean id="someBean" class="spring_autowired_ann.SomeBean"/> </beans>
public class SomeBean { //@Autowired private OtherBean otherBean; //@Autowired private OtherBean2 otherBean2; @Autowired public void setXXX(OtherBean otherBean,OtherBean2 otherBean2){ this.otherBean = otherBean; this.otherBean2 = otherBean2; } @Override public String toString() { return "SomeBean [otherBean=" + otherBean + ", otherBean2=" + otherBean2 + "]"; } }
1,@Autowired标签:
1,通过@Autowired标签可以让spring自动的把属性需要的对象从容器中找出来,并注入给对象.2,autowired标签可以放在字段或者setter方法上面
3,使用autowired标签可以注入一些spring内置的重要对象,比如BeanFactory,ApplicationContext;
4,默认情况下,@Autowired标签必须要能找到对应的对象,否则报错;通过required=false来避免这个问题:@Autowired(required=false)
5,@Autowired找bean的方式:
1),首先按照依赖对象的类型找;如果找到,就是用setter或者字段直接注入;
2),如果在Spring上下文中找到多个匹配的类型,再按照名字去找;如果没有匹配,报错;
3),可以通过使用@Qualifier(“otherBean”)标签来规定依赖对象按照bean的id+类型去找;
2,@Resource标签:
1,@Resource标签是JavaEE规范的标签;2,@Resource标签也可以作用于字段或者setter方法;
3,也可以使用@Resource标签注入一些spring内置的重要对象,比如BeanFactory.ApplicationContext;
4,@Resource必须要求有匹配的对象;
5,
<context:annotation-config>既引入了@Autowired标签的解析器,也引入了@Resource的解析器;
6,@Resource标签找bean的方式:
1),首先按照名字去找,如果找到,就使用setter或者字段注入;
2),如果按照名字找不到,再按照类型去找,但如果找到多个匹配类型,报错;
3),可以直接使用name属性指定bean的名称;但是,如果指定的name,就只能按照name去找,如果找不到,就不会再按照类型去找;
3,@Autowired标签和@Resource标签如何择选
1.@Autowired是Spring的标签,使用,和Spring耦合,有可能有未知的错误.---Spring 2,@Resouce:是J2EE的规范,所以稳定,在J2EE规范容器中也能正常使用;
三、使用注解简化IoC
<?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" 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.xsd "> <!-- @Component:把该对象交给Spring进行管理 扫描哪些包及其子包中@Component注解 若要扫描多个包,用逗号分隔,也可以定义多个<context:component-scan base-package=""/> --> <context:annotation-config /> <context:component-scan base-package="spring_ann_IoC" /> </beans>
package spring_ann_IoC; import org.springframework.stereotype.Component; @Component public class OtherBean { }
package spring_ann_IoC; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.stereotype.Component; @Component public class SomeBean { @Autowired @Qualifier("otherBean") //@Qualifier("sb") private OtherBean otherBean; @Override public String toString() { return "SomeBean [otherBean=" + otherBean + "]"; } }
1.标注Bean的注解:@Component
默认情况,直接使用类的名字(首字母小写作为bean的名字)如果要修改bean的名称;直接使用value属性来重新定义bean的名称
OtherBean类 package spring_ann_IoC; import org.springframework.stereotype.Component; @Component("sb") public class OtherBean { }
SomeBean类 @Component public class SomeBean { @Autowired //@Qualifier("otherBean") @Qualifier("sb") private OtherBean otherBean; @Override public String toString() { return "SomeBean [otherBean=" + otherBean + "]"; } }
2.使用@Component的限制:
1),不能运用到静态工厂方法和实例工厂方法,但是可以使用到FactoryBean;2),对于没有源代码的类(框架内部的预定义类),只能用XML配置;
3.是否是单例的
在我们自己用xml配置bean的时候我们可以设置Scope对于注解方式如何实现?注解方式默认也是单例的。
我们只需要设置@Scope(“prototype”)
@Component @Scope("prototype") public class SomeBean { @Autowired //@Qualifier("otherBean") @Qualifier("sb") private OtherBean otherBean; @Override public String toString() { return "SomeBean [otherBean=" + otherBean + "]"; } }
3.初始化和销毁
@PostConstruct public void init(){ System.out.println("init()..........."); } @PreDestroy public void destroy(){ System.out.println("destroy........"); }
4.bean组件版型标签
bean组件版型:@Service用于标注业务层组件、
@Controller用于标注控制层组件(如struts中的action)、
@Repository用于标注数据访问组件,即DAO组件。
@Component泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。
bean组件版型用法和@Component一样,仅仅是名字不同,用的地方不同。
三、代理
1.静态代理
1,代理对象完全包含真实对象,客户端使用的都是代理对象上面的方法,和真实对象无关;2,静态代理能够处理:
1),把不是真实对象该做的事情从真实对象上面撇开;
3,静态代理带来的问题:
1),还是需要在每一个方法上面处理额外的业务;业务代码(大家都需要做的事情,公共的事情)还是分散在各个方法中的;
2),需要为每一个真实对象都得创建一个代理对象
public interface Rent { public void rent(); }
Host public class Host implements Rent { @Override public void rent() { System.out.println("出租房屋。。。。。。"); } }
Proxy public class Proxy implements Rent{ private Host host; @Override public void rent() { seeHouse(); host.rent(); fee(); } public void seeHouse(){ System.out.println("看房。。。。"); } public void fee(){ System.out.println("收费....."); } public void setHost(Host host) { this.host = host; } }
配置文件 <?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" 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.xsd "> <bean id="host" class="cn.bdqn.staticproxy01.Host"></bean> <bean id="proxy" class="cn.bdqn.staticproxy01.Proxy"> <property name="host" ref="host"></property> </bean> </beans>
测试 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class TestStaticProxy { @Autowired private ApplicationContext ac; @Test public void testAnnIoC(){ Proxy proxy = ac.getBean("proxy",Proxy.class); proxy.rent(); } }
2.动态代理(JDK)
JDK动态代理:1,我代理的对象必须要实现一个接口;
2,需要为每个对象创建代理对象;
3,动态代理的最小单位是类(所有类中的方法都会被处理);
public interface Rent { public void rent(); }
Host public class Host implements Rent { @Override public void rent() { System.out.println("出租房屋。。。。。。"); } }
动态代理类 public class PynamicProxy implements InvocationHandler{ private Object target; //真是目标对象 //创建代理对象 public Object createProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this); } //执行增强操作 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { seeHouse(); Object result = method.invoke(target, args); fee(); return result; } public void seeHouse(){ System.out.println("看房。。。。。。"); } public void fee(){ System.out.println("收费。。。。。。"); } 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" 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.xsd "> <bean id="host" class="cn.bdqn.dynamicproxy.jdk01.Host"></bean> <bean id="proxy" class="cn.bdqn.dynamicproxy.jdk01.PynamicProxy"> <property name="target" ref="host"></property> </bean> </beans>
测试 public class TestPynamicProxy { @Autowired @Qualifier("proxy") private PynamicProxy proxy; @Test public void testPynamicProxy(){ Rent p= (Rent)proxy.createProxy(); p.rent(); } }
JDK动态代理总结:
1,JAVA动态代理是使用java.lang.reflect包中的Proxy类与InvocationHandler接口这两个来完成的。
2,要使用JDK动态代理,必须要定义接口。
3,JDK动态代理将会拦截所有pubic的方法(因为只能调用接口中定义的方法),这样即使在接口中增加了新的方法,不用修改代码也会被拦截。
4,如果只想拦截一部分方法,可以在invoke方法中对要执行的方法名进行判断。
2.动态代理(CGLib)
若一个类,没有接口如何代理?javassist.jar:Hibernate和Struts2的代理实现方案.
cglib.jar:Spring的代理实现方案:
实现类 public class EmployeeServiceImpl{ public void save() { System.out.println("------保存员工------"); } }
事务管理类 /** * 事务管理器 * @author Administrator * */ public class TransactionManager { public void beginTransaction(){ System.out.println("开启事务。。。。"); } public void commit(){ System.out.println("提交事务。。。。"); } public void rollback(){ System.out.println("回滚事务。。。。"); } }
代理类 public class ProxyCallBack implements org.springframework.cglib.proxy.InvocationHandler { private Object target; //真实对象 private TransactionManager txManager; //创建代理对象 public Object createProxy(){ //增强器 Enhancer enhancer = new Enhancer(); //把真实对象作为代理父类 enhancer.setSuperclass(target.getClass()); //设置增强的操作 enhancer.setCallback(this); //创建代理对象 return enhancer.create(); } //执行增强操作 @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object obj = null; txManager.beginTransaction(); try { obj= method.invoke(target, args); txManager.commit(); } catch (Exception e) { txManager.rollback(); } return obj; } public void setTarget(Object target) { this.target = target; } public void setTxManager(TransactionManager txManager) { this.txManager = txManager; } }
测试 @Autowired private ProxyCallBack proxy; @Test public void testStaticProxy(){ EmployeeServiceImpl p = (EmployeeServiceImpl)proxy.createProxy(); p.save(); }
CGLIB代理总结: 1,CGLIB可以生成目标类的子类,并重写父类非final修饰符的方法。 2,要求类不能是final的,要拦截的方法要是非final、非static、非private的。 3,动态代理的最小单位是类(所有类中的方法都会被处理); 代理总结: Spring中: 1,若目标对象实现了若干接口,spring就会使用JDK动态代理。 2,若目标对象没有实现任何接口,spring就使用CGLIB库生成目标对象的子类。
四、AOP
1.1. AOP—Aspect Oriented Programming
面向切面编程——弥补面向对象编程(OOP)的不足AOP和IOC是Spring的两个核心。AOP是对IOC的补充,他们之间不存在依赖关系。
2. AOP的作用
提供显式的事物管理允许用户自定义切面
3. AOP的优点
通过静态代理可以使业务类更加纯粹 公共业务由代理完成—实现分工 公共业务高度集中便于扩展和修改
4. 名词
1.关注点:除正常业务以外需要重点注意的事项。如:日志、同步等业务。2.连接点(Joinpoint):特定方法的调用就可以称为连接点
3.切入点:Pointcut:在哪些类,哪些方法上面切(where);
4.通知/增强Advice:在方法的什么时机(when:方法前/方法后/方法前后)做什么(what:增强的功能);连接点上特定方法执行的动作就称为通知
通知可以分为前置通知(Before advice)、后置通知(After returning advice)、环绕通知(Around Advice)、异常通知(After throwing advice)、最终通知(After (finally) advice)
5.切面(Aspect):一个关注点的模块化就称为切面。也就是切入点+通知: 什么时机,什么地点,干啥!
6.,织入Weaving:把切面加入到对象,并创建出代理对象的过程.(Spring来做的)
5.AOP的配置(xml)
1,依赖的jar包
spring-aop-4.3.3.RELEASE.jaraopalliance.jar
aspectjweaver.jar
2,引入aop命名空间
3,aop配置
什么时机:什么地点,做什么<aop:config> <aop:aspect ref="txManager">:做什么 <aop:pointcut expression="execution(* cn.itcast.cd.day2._6aop_xml.*Service.*(..))" id="txPoint"/>:什么地点(哪些方法上) <aop:before method="beginTransaction" pointcut-ref="txPoint"/>:时机:方法前/方法后/方法前后
4,aspectJ
AOP思想广泛应用于java,专门有一个组织负责aop的一切事物(AOP联盟) 首先就要解决一个问题,怎么表示在那些方法上切。---->aspectJ(语言) 通过表达式语言在那些包下那些类中的那些方法上切(增强)
5,实现
接口 public interface IEmployeeService { public void save(); }
实现 public class EmployeeServiceImpl implements IEmployeeService { @Override public void save() { System.out.println("------保存员工------"); throw new RuntimeException("出现异常"); } }
事务管理类 /** * 事务管理器 * @author Administrator * */ public class TransactionManager { //在业务方法被调用前,如何获取业务方法的信息 public void beginTransaction(JoinPoint jp){ System.out.println("开启事务。。。。"); //void cn.bdqn.aop_xml.IEmployeeService.save() //System.out.println(jp.getSignature()); //得到方法的签名 //System.out.println(jp.getTarget()); //真是主题对象 //System.out.println(jp.getArgs()); //方法参数 } public void commit(){ System.out.println("提交事务。。。。"); } public void rollback(Throwable ex){ System.out.println("回滚事务。。。。"); System.out.println(ex.getMessage()); } public void close(){ System.out.println("关闭Session。。。。"); } /*//环绕业务方法的增强 //如何调用真正的业务方法 public void around(){ System.out.println("开启事务"); try { System.out.println("执行业务方法。。"); System.out.println("提交事务"); } catch (Exception e) { System.out.println("回滚事务"); }finally{ System.out.println("关闭Session"); } }*/ //调用真正的业务方法,真正的业务方法可能有返回值 public Object around(ProceedingJoinPoint pjp) throws Throwable{ System.out.println("开启事务"); try { Object result = pjp.proceed(); //调用业务方法 System.out.println("提交事务"); return result; } catch (Exception e) { System.out.println("回滚事务"); }finally{ System.out.println("关闭Session"); } return null; } }
<?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.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd "> <!-- AOP思想广泛应用于java,专门有一个组织负责aop的一切事物(AOP联盟) 首先就要解决一个问题,怎么表示在那些方法上切。 aspectJ(语言) 通过表达式语言在那些包下那些类中的那些方法上切(增强) --> <bean id="txManager" class="cn.bdqn.aop_xml.TransactionManager" /> <bean id="employeeService" class="cn.bdqn.aop_xml.EmployeeServiceImpl" /> <aop:config> <aop:aspect ref="txManager"> <aop:pointcut expression="execution(* cn.bdqn.aop_xml.*Service.*(..))" id="txManagerPoint"/> <!-- 前置通知:在业务方法执行之前执行增强操作(增强类中的指定增强方法) --> <aop:before method="beginTransaction" pointcut-ref="txManagerPoint"/> <!-- 后置通知:在业务方法成功调用之后增强操作 <aop:after-returning method="commit" pointcut-ref="txManagerPoint"/>--> <!-- 异常通知:在业务方法中出现异常,需要调用增强操作 throwing="ex":决定方法定义为:public void rollback(Throwable ex) <aop:after-throwing method="rollback" pointcut-ref="txManagerPoint" throwing="ex" />--> <!-- 最终通知:finally里的,都要制定增强操作 <aop:after method="close" pointcut-ref="txManagerPoint"/>--> <!-- 环绕通知:前4个的综合,环绕着业务方法的增强 <aop:around method="around" pointcut-ref="txManagerPoint"/>--> </aop:aspect> </aop:config> </beans>
Test @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration public class AopTest { @Autowired private IEmployeeService service; @Test public void testAop(){ service.save(); } }
相关文章推荐
- Spring学习笔记:1、概念理解
- ★(转)Spring学习笔记1
- Spring学习笔记二
- Spring学习笔记
- 学习Struts+spring+Hibernate的笔记.
- Spring 学习笔记 (二)--AOP
- 学习Struts+spring+hibernate的笔记
- Spring的AOP学习笔记
- Spring in Action 学习笔记—开始Spring之旅
- Spring学习笔记一
- spring学习笔记(1)
- Spring学习笔记:第三章 IoC中的国际化
- Spring学习笔记:第二章 Spring中IoC的入门实例
- Spring in Action 学习笔记—第一章 开始Spring之旅(转贴)
- Spring学习笔记(一)
- Spring学习笔记:第三章 IoC中的国际化
- Professional Java Development with the Spring Framework学习笔记(1) - JdbcTemplate
- Spring学习笔记:1、概念理解
- Spring学习笔记:2-Spring中IoC的入门实例
- Spring学习笔记:1、概念理解