您的位置:首页 > 编程语言 > Java开发

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.jar

aopalliance.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