Springioc和aop⼩结
IOC
什么是IOC
控制反转,把对象创建和对象之间的调⽤过程交给Spring进⾏管理
使⽤IOC的⽬的:为了降低耦合度
IOC底层原理
解析xml⽂件,获取bean标签的class属性,即全类名,通过反射获取到其Class对象,调⽤newInstance⽅法来创建⼀个对象。
IOC容器
IOC思想基于IOC容器完成,IOC容器底层就是对象⼯⼚。
Spring提供IOC容器实现的两种⽅式(两个接⼝)
两个接⼝作⽤相似,都可以通过加载配置⽂件,通过对象⼯⼚创建对象。不过两者有⼀定的区别。
BeanFactory
IOC容器的基本实现,是Spring内部使⽤的接⼝,不提供开发⼈员进⾏使⽤。
特点:延迟加载,调⽤的时候再创建对象。
ApplicationContext
BeanFactory接⼝的⼦接⼝,提供更多更强⼤的功能,⼀般由开发⼈员进⾏使⽤。 基本上所有场合都能直接⽤ApplicationContext。
在加载配置⽂件时就会创建全部对象。
Application的三个实现类:
1. ClassPathXmlApplicationContext:它可以加载类路径下的配置⽂件,要求配置⽂件必须在类路径下。不在的话加载不了
2. FileSystemXmlApplicationContext:它可以加载磁盘任意路径下的配置⽂件(必须要有访问权限)
3. AnnotationConfigApplicationContext:他是⽤于读取注解注解配置容器的类
IOC操作Bean管理
什么是Bean管理
Bean管理指的是两个操作:1. Spring创建对象。2. Spring注⼊属性
在XML中Bean对象的三种创建⽅式
通过调⽤⽆参构造器创建。如果类中没有⽆参构造器,就会创建失败。
使⽤普通⼯⼚中的成员⽅法创建对象。先注册Bean⼯⼚,然后注册需要的Bean对象,通过factory-bean属性指定⼯⼚,factory-method指定⼯⼚中的⽅法,就能够创建Bean对象。
使⽤⼯⼚的静态⽅法创建对象。通过Bean标签的class属性指向⼯⼚⽅法,factory-method指向静态⽅法,这样就可以获得⼀个Bean 对象。相⽐于上⾯使⽤成员⽅法创建对象,可以少注册⼀个⼯⼚的Bean对象。
Bean管理操作的两种⽅式
基于xml配置⽂件⽅式实现
基于注解⽅式实现
基于xml⽅式
1. 基于xml⽅式创建对象
<!--配置xx对象的创建-->
<bean id="xx"class=""/>
1. 在xml⽂件中,使⽤bean标签,标签⾥添加对应的属性,就可以实现对象创建
2. bean标签的常⽤属性
1. id属性:容器中的唯⼀标识,不允许重复
2. class属性:类全路径(包类路径)
3. 创建对象时候,默认是执⾏⽆参数构造⽅法完成对象创建
2. 基于xml⽅式注⼊属性
DI(Dependency Injection,依赖注⼊): DI是IOC的⼀种具体实现,就是注⼊属性,有以下两种⽅式在xml中注⼊属性
1. 使⽤set⽅法注⼊:使⽤bean标签的property属性进⾏注⼊。
<bean class="pojo.Dog" id="dog">
<property name="name" value="汪酱"/>
<property name="weight" value="20"/>
</bean>
2. 使⽤有参构造注⼊属性
<bean class="pojo.Dog" id="dog">
<constructor-arg name="name" value="汪酱"/>
<constructor-arg name="weight" value="20"/>
</bean>
基于注解⽅式
1. 基于注解创建对象,在类上加⼊注解@Component,@Service,@Controller,@Repository,可以⾃动在xml中创建相应的Bean
实例。这四个注解的功能是完全⼀样的,名字不同可以快速确定当前这个类是什么类型的服务。
/*
这⾥的value对应的是bean标签中的id属性,class属性会获取当前的类的包类路径。
如果不加value属性,默认是⾸字母⼩写的类名
*/
@Service(value ="xxService")
2. 基于注解⽅式实现属性注⼊
1. @Autowired
根据属性类型进⾏注⼊,在属性上添加@Autowired后,可以不添加该属性的setter⽅法,因为该注解底层是通过反射进⾏注⼊了,并不需要⾛setter⽅法。
2. @Qualifier
根据属性名称进⾏注⼊,可以与@Autowired注解⼀起使⽤。
3. @Resource
可以根据类型注⼊,也可以根据名称注⼊
4. @Value
⽤在成员属性上,给属性添加基本类型+String的值
Bean的作⽤域
通过bean标签中的scope管理Bean对象的作⽤域
1. singleton(默认):单例,在解析xml⽂件时创建,并全局唯⼀
2. prototype:多例(原型),在调⽤getBean⽅法时创建对象,每个对象独⽴,互不⼲扰。
3. request:作⽤于web应⽤的请求范围
4. session:作⽤于web应⽤的会话范围
Bean的⽣命周期
⽣命周期:从对象创建到对象销毁的过程
Bean标签中有两个属性⽤于配置bean对象在⽣命周期的⼀些⽅法。
init-method=“”:配置初始化⽅法。
destroy-method=“”:配置销毁⽅法。
1. 通过构造器创建Bean实例 bean(⽆参构造)
2. 为bean的属性设置值和对其他bean的引⽤(调⽤set⽅法)
3. 调⽤bean的初始化⽅法(需要配置init-method)
4. bean可以使⽤了(对象获取到了)
5. 当容器关闭时,调⽤bean的销毁⽅法(需要配置destroy-method)
单例对象的⽣命周期:与容器的⽣命的周期相同,容器创建就创建,容器销毁就销毁。
多例对象的⽣命周期:在被调⽤时创建,当⽆⽤时销毁。
Bean的⾃动装配
使⽤bean标签的autowire属性进⾏⾃动注⼊。
⼀般autowire常⽤属性有两个:
1. byType ,根据对象类型进⾏⾃动注⼊,在xml搜索与当前bean中的属性的类型相同的bean,然后进⾏set注⼊。
2. byName,根据name或者id进⾏查,查到与属性的属性名相同的bean时进⾏注⼊。
全注解开发
在Java类上使⽤注解@Configuration表明该Java类是Spring的配置类,⽤于替代xml配置⽂件,这样⼀来就可以不写xml⽂件。
关于在Junit中⽆法⾃动装配的问题
如果出现在Junit单元测试中使⽤@Autowired⽆法⾃动装配,完成以下步骤以可。
1. 导⼊spring-test依赖,然后在Test类上加⼊注解@RunWith(SpringJUnit4ClassRunner.class)
2. 加⼊注解@ContextConfiguration,来标明想要导⼊这个测试类的Bean。
3. 如果使⽤的是xml⽂件作为配置,则使⽤@ContextConfiguration的locations属性,写⼊所有配置了Bean的xml⽂件。要注意xml⽂
件中需要写component-scan标签,扫描所有的bean对象。
4. 如果使⽤全注解开发,则使⽤classes属性添加作为配置的Java类。要注意使⽤@ComponentScan注解扫描Bean对象所在的位置。AOP
什么是AOP
⾯向切⾯编程,利⽤AOP可以对业务逻辑的各个部分进⾏隔离,从⽽使得业务逻辑各部分之间的耦合度降低,提⾼程序的可重⽤性,同时提⾼了开发的效率。
通俗描述:不通过修改源代码的⽅式,在主⼲功能中添加⼀个新功能。
底层原理
AOP底层使⽤动态代理,有两种情况的动态代理
1. 有接⼝情况,使⽤JDK动态代理,通过创建⼀个接⼝实现类的代理对象并加⼊额外的功能,最终完成功能的添加。
2. 没有接⼝情况,使⽤CGLIB动态代理,通过继承创建⼀个⼦类的代理对象,加⼊额外的功能,最终完成功能的添加。
JDK动态代理
使⽤Proxy类(在flect中)⾥⾯的⽅法创建对象。通过调⽤⾥⾯的newProxyInstance⽅法返回指定接⼝的代理类的实例。⽅法有三个参数。
1. 第⼀个参数是类加载器。可以通过调⽤对象的getClass⽅法获得Class对象,然后调⽤getClassLoader获得类加载器。
2. 第⼆个参数是该类实现的接⼝。与上述步骤差不多,获得Class对象后,调⽤getInterfaces获取该类实现的接⼝。
3. 第三个参数是InvocationHandler(接⼝),需要⾃⼰写⼀个其实现类,在⾥⾯完成功能的增强。
步骤
1. 创建接⼝,定义⽅法
public interface CalculateDao {
int add(int a,int b);
CalculateDao update(String id);
}
2. 创建接⼝实现类,实现⽅法
public class CalculateDaoImpl implements CalculateDao {
@Override
public int add(int a,int b){
System.out.println("add⽅法执⾏了");
return a+b;
}
@Override
public CalculateDao update(String id){
System.out.println("update⽅法执⾏了");
System.out.println(id);
return this;
}
}
3. 使⽤Proxy类创建接⼝代理对象前需要实现InvocationHandler
spring ioc注解class ProxyFactory implements InvocationHandler {
private Object obj;
/**
* @param obj Object包容所有传进来对象
*/
public ProxyFactory(Object obj){
this.obj = obj;
}
/**
* @param proxy 代理对象信息
* @param method 被调⽤的⽅法
* @param method 被调⽤的⽅法
* @param args ⽅法传⼊的参数
* @return 返回值
* @throws Throwable 抛异常
*/
@Override
public Object invoke(Object proxy, Method method, Object[] args)throws Throwable {
if("update".Name())){
method.invoke(obj, args);
return proxy;
}
System.out.println("⽅法执⾏前....."+Name()+":传递的参数"+ String(args));
Object result = method.invoke(obj, args);
System.out.println("⽅法执⾏后....."+obj);
return result;
}
}
4. 调⽤Proxy的newInstance⽅法创建代理对象
CalculateDao cal =(CalculateDao) wProxyInstance(ClassLoader(), Interfaces(),new ProxyFa ctory(new CalculateDaoImpl()));
System.out.println("结果为:"+cal.add(1,5));
/*
控制台输出:
⽅法执⾏前.....add:传递的参数[1, 5]
add⽅法执⾏了
⽅法执⾏后.....
结果为:6
*/
关于Invoke⽅法中的第⼀个参数proxy
⽤法:可以在特定条件下让⽅法返回proxy,达到对该代理对象的连续调⽤。
注意事项:如果要返回proxy并连续调⽤,那么被调⽤的⽅法的返回值⼀定要是接⼝类型
//在Main⽅法中
CalculateDao cal =(CalculateDao) wProxyInstance(ClassLoader(), Interfaces(),new ProxyFactory( new CalculateDaoImpl()));
cal.update("13").update("12");
/*
结果为:
update⽅法执⾏了
13
update⽅法执⾏了
12
*/
AOP术语
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论