1、Spring是一个免费的框架,也可以说是容器。
2大特点IOC和AOP
2、什么是IOC?
(1)IOC就是控制反转,是指创建对象的控制权的转移,以前创建对象的主动权和时机是由自己把控的,而现在这种权力转移到Spring容器中,并由容器根据配置文件去创建实例和管理各个实例之间的依赖关系,对象与对象之间松散耦合,也利于功能的复用。DI依赖注入,和控制反转是同一个概念的不同角度的描述,即 应用程序在运行时依赖IoC容器来动态注入对象需要的外部资源。
(2)最直观的表达就是,IOC让对象的创建不用去new了,可以由spring自动生产,使用java的反射机制,根据配置文件在运行时动态的去创建对象以及管理对象,并调用对象的方法的。
(3)Spring的IOC有三种注入方式 :构造器注入、setter方法注入、根据注解注入。
3、Spring对象的创建方式
-使用无参构造方法
<bean id="user" class="com.kuang.pojo.User">
<property name="name" value="秦疆"/>
</bean>
-使用有参数构器
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg index="0" value="狂神说Java"/>
</bean>
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg type="java.lang.String" value="qinjiang"/>
</bean>
-通过参数名字
<bean id="user" class="com.kuang.pojo.User">
<constructor-arg name="name" value="秦疆"/>
</bean>
4、DI注入
- 构造器注入
- set注入
- P命名空间注入
构造器注入上面已经说过了
下面是set注入。上面这两种写法都可以,spring会将name值的每个单词首字母转换成大写,然后再在前面拼接上”set”构成一个方法名,然后去对应的类中查找该方法,通过反射调用,实现注入。
private String name;
private Address address;
private String[] books;
private List<String> hobbys;
private Map<String,String> card;
private Set<String> games;
private Properties info;
private String wife;**
class Address {
private String address;
<bean id="student" class="com.kuang.pojo.Student">
<!-- 第一种普通值-->
<property name="name">
<value>名字</value>
</property>
<!-- 第二种注入 bean注入-->
<property name="address" ref="address"/>
<!-- 第三种,数组注入-->
<property name="books">
<array>
<value>红楼梦</value>
<value>西游记</value>
</array>
</property>
<!-- List-->
<property name="hobbys">
<list>
<value>听歌</value>
<value>敲代码</value>
<value>看电影</value>
</list>
</property>
<!-- Map-->
<property name="card">
<map>
<entry key="身份证" value="123"></entry>
<entry key="银行卡" value="5667"></entry>
</map>
</property>
<!-- Set-->
<property name="games">
<set>
<value>LOL</value>
<value>CF</value>
</set>
</property>
<!-- null-->
<property name="wife" value="null"/>
<!-- properties-->
<property name="info">
<props>
<prop key="学号">201210536</prop>
<prop key="班级">125</prop>
<prop key="性别">男</prop>
</props>
</property>
</bean>
p命名空间注入
class User {
private String name;
private int age;
<bean id="user" class="com.kuang.pojo.User" p:name="名字" p:age="28"/>
5、bean的自动装配
- 注解方式@Autowired( 开启注解支持 context:annotation-config/)
class Person {
//如果现实定了Autowired的required属性为false,说明这个对象可以为null,否则不允许为空
@Autowired(required = false)
private Cat cat;
@Autowired
private Dog dog;
private String name;
public Person() {
}
class Cat {
public void bark(){
System.out.println("瞄。。。。");
}
class Dog {
public void bark(){
System.out.println("汪。。。。");
}
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<bean id="person" class="com.kuang.pojo.Person">
<!-- <property name="name" value="asd"/>-->
</bean>
- xml装配
<bean id="cat" class="com.kuang.pojo.Cat"/>
<bean id="dog" class="com.kuang.pojo.Dog"/>
<!--
byName: 会自动在容器上下文中查找,和自己对象set方法后面的值对应的beanid
byType:会自动在容器上下文中查找,和自己属性类型相同的bean
-->
<bean id="person" class="com.kuang.pojo.Person" autowire="byType">
<property name="name" value="名字"/>
<property name="dog" ref="dog"/>
<property name="cat" ref="cat"/>
</bean>
6、Spring的注解开发
想要使用注解开发,首先开启注解支持,然后添加扫描包
<!-- 指明要扫描哪个包,这个包下的注解就会生效-->
<context:component-scan base-package="com.kuang.pojo"/>
<!-- 开启注解支持-->
<context:annotation-config/>
-Component:在类上使用相当于
<bean id=user class="com.kaung.pojo.User"/>
- @Value在属性上添加,相当于
//等价于 <property name="name" value="名字"/>
@Value("名字")
7、AOP面向切面编程
7.1静态代理模式
代理模式的好处
- 可以使角色的操作更加纯粹,不用关注一些公共业务
- 公共业务交给代理角色
- 业务扩展的时候,方便业务的管理
代理模式的好处
- 可以使角色的操作更加纯粹,不用关注一些公共业务
- 公共业务交给代理角色
- 业务扩展的时候,方便业务的管理
缺点
- 每个角色都需要一个代理,比较麻烦
接下来我们来实现下静态代理的过程:
我们来创建一个租房子接口:
interface Rent {
public void rent();
}
接下来,创建一个房东类,实现租房子接口
class Host implements Rent{
public void rent() {
System.out.println("房东要出租房子");
}
然后创建一个代理类,同样实现租房子功能,创建构造方法传递房东对象
class Proxy implements Rent {
private Host host;
public Proxy() {
}
public Proxy(Host host) {
seeHouse();
this.host = host;
heTong();
fare();
}
public void rent() {
host.rent();
}
//看房
public void seeHouse(){
System.out.println("中介带你看房子");
}
//合同
public void heTong(){
System.out.println("签署租赁合同");
}
//收中介费
public void fare(){
System.out.println("中介带你看房子");
}
}
然后创建测试类
class Client {
public static void main(String[] args) {
//代理 帮房东出租房子,有一些附属操作
Proxy proxy = new Proxy(new Host());
//不用面对房东
proxy.rent();
}
总结下静态代理的实现思路:
创建接口,实现类,实现具体功能。创建代理类,代理类实现接口功能,方法体实际为,实现类对象调用实现方法。测试类,测试。可能有点绕。
A 接口
B A的实现类
C 代理类,实现A。有参构造器传递B的对象
C 中的实现方法用B的对象去调用B的实现方法
D 测试类,创建代理类对象,传递B的对象,然后代理对象调用本类实现A的方法。
如果在看不懂,那只能恕我表达能力有限。
7.2 动态代理
实现InvocationHandler接口
//生成得到代理类
public Object getProxy() {
return Proxy.newProxyInstance(this.getClass().getClassLoader(), target.getClass().getInterfaces(), this);
}
//处理代理实例,并返回结果
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
log(method.getName());
//动态代理的本质,就是使用反射
return method.invoke(target, args);
}
public void log(String msg){
System.out.println("执行了"+msg+"方法");
}