目录
- 狂神视频地址
-
- 1、Spring
- 2、IOC理论推导
- 3、IOC本质
- 4、Spring 入门程序
- 5、IOC创建对象的方式
- 6、Spring配置
- 7、依赖注入
- 9、bean的作用域
- 10.Bean的自动装配
- 11、注解实现自动装配
- 12、使用注解开发
- 13、java的方式配置Spring
- 14、代理模式
- 15、静态代理
- 16、动态代理
- 17、基于Proxy类和InvocationHandler 实现动态代理
- 17-2.被代理的接口
- 18、基于Proxy类和InvocationHandler 实现动态代理 2
- 19、动态代理和静态代理总结
- 20、什么是Aop
- 21、Aop 实现方式1-基于原生API
- 22、Aop 实现方式2-切面方式
- 23、Aop 实现方式3-注解方式
- 24、Spring 整合Mybatis
- 25、声明式事务
- 26、声明式事务代码
狂神视频地址
1、Spring
1-1.Spring 简介
Spring:春天------>给软件行业带来了春天!
2002,首次推出了Spring框架的雏形:interface21框架!
Spring框架即以interface21框架为基础,经过重新设计,并不断丰富其内涵,于2004年3月24日发布了1.0正式版。
Rod Johnson,Spring Framework创始人,著名作者。很难想象Rod Johnson的学历,真的让好多人大吃一惊,他是悉尼大学的博士,然而他的专业不是计算机,而是音乐学。
Spring理念:使现有的技术更加容易使用,本身是一个大杂烩,整合了现有的技术框架!
1-2.Spring 的优点
- Spring是一个开源的免费的框架(容器)!
- Spring是一个轻量级的、非入侵式的框架!
- 控制反转(IOC),面向切面编程(AOP)!
- 支持事务的处理,对框架整合的支持!
总结一句话:Spring就是一个轻量级的控制反转(IOC)和面向切面编程(AOP)的框架!
1-3.Spring 组成
1-4.Spring 拓展
现代化的Java开发!说白就是基于Spring的开发!
Spring Boot
- 一个快速开发的脚手架。
- 基于SpringBoot可以快速的开发单个微服务。
- 约定大于配置。
Spring Cloud
- SpringCloud是基于SpringBoot实现的。
- 因为现在大多数公司都在使用SpringBoot进行快速开发,学习SpringBoot的前提,需要完全掌握Spring及SpringMVC!承上启下的作用!
弊端:发展了太久之后,违背了原来的理念!配置十分繁琐,人称:“配置地狱!”
2、IOC理论推导
2-1.UserDao 接口
public interface UserDao {
<span class="token keyword">void</span> <span class="token function">getUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
2-2.UserDaoImpl 实现类
public class UserDaoImpl implements UserDao {
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">getUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"获取用户数据"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
2-3.UserService 业务接口
public interface UserService {
<span class="token keyword">void</span> <span class="token function">getUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
2-4.UserServiceImpl 业务实现类
public class UserServiceImpl implements UserService {
<span class="token class-name">UserDao</span> userDao <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserDaoImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">getUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> userDao<span class="token punctuation">.</span><span class="token function">getUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
2-5.测试
public class Test { public static void main(String[] args) {
<span class="token class-name">UserService</span> userService <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserServiceImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> userService<span class="token punctuation">.</span><span class="token function">getUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在我们之前的业务中,用户的需求可能会影响我们原来的代码,我们需要根据用户的需求去修改原代码!如果程序代码量十分大,修改一次的成本代价十分昂贵!
我们使用一个Set接口实现,已经发生了革命性的变化!
UserDao userDao;
public void setUserDao(UserDao userDao){
this.userDao = userDao;
}
- 1
- 2
- 3
- 4
- 5
之前,程序是主动创建对象!控制权在程序员手上!
使用了set注入后,程序不再具有主动性,而是变成了被动的接受对象!
控制反转了,主动权交给用户了
这种思想,从本质上解决了问题,我们程序猿不用再去管理对象的创建了。系统的耦合性大大降低~,可以更加专注的在业务的实现上!这是IOC的原型!
3、IOC本质
控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中,我们使用面向对象编程,对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。
采用XML方式配置Bean的时候,Bean的定义信息是和实现分离的,而采用注解的方式可以把两者合为一体,Bean的定义信息直接以注解的形式定义在实现类中,从而达到了零配置的目的。
控制反转是一种通过描述(XML或注解)并通过第三方去生产或获取特定对象的方式。在Spring中实现控制反转的是IoC容器,其实现方法是依赖注入(Dependency Injection,DI)。
4、Spring 入门程序
4-1.实体类
public class User { private String name;
<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> name<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setName</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token string">"User{"</span> <span class="token operator">+</span> <span class="token string">"name='"</span> <span class="token operator">+</span> name <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span> <span class="token string">'}'</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
4-2.配置文件
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span>使用<span class="token class-name">Spring</span> 来创建对象,在<span class="token class-name">Spring</span> 中,这些都称为bean 类型 变量名 <span class="token operator">=</span> <span class="token keyword">new</span> 类型<span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">User</span> user <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> bean <span class="token operator">=</span> 对象 <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> id <span class="token operator">=</span> 变量名 <span class="token keyword">class</span> <span class="token operator">=</span> <span class="token keyword">new</span> 的对象<span class="token punctuation">;</span> property 相当于 给对象中的属性设置一个值! <span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>bean id<span class="token operator">=</span><span class="token string">"user"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"cn.bloghut.domain.User"</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"name"</span> value<span class="token operator">=</span><span class="token string">"csdn_闲言"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>bean<span class="token operator">></span>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
4-3.测试
public static void main(String[] args) {
//获取Spring 的上下文对象
ApplicationContext ac = new ClassPathXmlApplicationContext("beans.xml");
//我们的对象现在都在Spring 中管理了,我们要使用,直接去里面取出来就行了
User user = (User)ac.getBean("user");
//打印
System.out.println(user.toString());
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
4-4.结果
User{name='闲言'}
- 1
4-5.思考问题?
Hello对象是谁创建的?
Hello对象是由Spring创建的。
Hello对象的属性是怎么设置的?
Hello对象的属性是由Spring容器设置的。
这个过程就叫控制反转:
控制:谁来控制对象的创建,传统应用程序的对象是由程序本身控制创建的,使用Spring后,对象是由Spring来创建的。
反转:程序本身不创建对象,而变成被动的接收对象。
依赖注入:就是利用set方法来进行注入的。
IOC是一种编程思想,由主动的编程变成被动的接收。
可以通过new ClassPathXmlApplicationContext去浏览一下底层源码。
到了现在,不用在程序中去改动了,要实现不同的操作,只需要在xml配置文件中进行修改,所谓的IOC,一句话搞定:对象由Spring来创建,管理,装配!
5、IOC创建对象的方式
5-1.使用无参构造创建对象,默认!
public User() {
System.out.println("User 空参构造方法执行了");
}
<!–注入user–>
<bean id=“user” class=“cn.bloghut.pojo.User”>
<property name=“name” value=“csdn_闲言”/>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
5-2.使用有参构造创建对象
下标赋值
public User(String name) {
this.name = name;
}
<bean id=“user” class=“cn.bloghut.pojo.User”>
<constructor-arg index=“0” value=“csdn_闲言”/>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5-3.类型
public User(String name) {
this.name = name;
}
<!--通过类型-->
<bean id="user" class="cn.bloghut.pojo.User">
<constructor-arg type="java.lang.String" value="csdn_闲言"/>
</bean>
参数名
<!–参数名–>
<bean id=“user” class=“cn.bloghut.pojo.User”>
<constructor-arg name=“name” value=“csnd_闲言”/>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
总结:在配置文件加载的时候,容器中管理的对象就已经初始化了!
Spring 容器,就类似于婚介网站。
- 信息都注册在里面
- 你想查看(获取)的时候再拿
6、Spring配置
6-1.别名
<bean id="user" class="cn.bloghut.pojo.User">
<constructor-arg name="name" value="csnd_闲言"/>
</bean>
<alias name="user" alias="user2"/>
ApplicationContext ac = new ClassPathXmlApplicationContext(“bean.xml”);
User user = (User)ac.getBean(“user2”);
user.show();
输出:csnd_闲言
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
6-2.Bean的配置
别名可以通过很多种方式分割
空格分割
逗号分割
分号分割
<bean id=“user” class=“cn.bloghut.pojo.User” name=“user2 u2,u3;u4”>
<property name=“name” value=“csdn_闲言”/>
</bean>
// User user = (User)ac.getBean(“user”);
// User user = (User)ac.getBean(“user2”);
// User user = (User)ac.getBean(“u2”);
// User user = (User)ac.getBean(“u3”);
User user = (User)ac.getBean(“u4”);
user.show();
输出:csdn_闲言
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
6-3.import
这个import。一般用于团队开发使用,它可以将多个配置文件,导入合并为一个。
假设,现在项目中有多个人开发,这三个人负责不同的类开发,不同的类需要注册在不同的bean中,我们可以利用import将所有人的beans.xml合并为一个总的!
- 张三
- 李四
- 王五
使用的时候,直接使用总的配置就可以了。
7、依赖注入
7-1.构造器注入
略
7-2.Set 注入
依赖:bean对象的创建依赖于容器!
注入:bean对象中的所有属性,由容器来注入!
Address类
public class Address {
private String address;
省略setter
}
- 1
- 2
- 3
- 4
student类
public class Student {
<span class="token keyword">private</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">Address</span> address<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">String</span><span class="token punctuation">[</span><span class="token punctuation">]</span> books<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">List</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">></span></span> hobbies<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">Map</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">,</span><span class="token class-name">String</span><span class="token punctuation">></span></span> card<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">Set</span><span class="token generics"><span class="token punctuation"><</span><span class="token class-name">String</span><span class="token punctuation">></span></span> games<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">String</span> wife<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">Properties</span> info<span class="token punctuation">;</span> 省略setter
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
bean.xml
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="token operator"><</span>bean id<span class="token operator">=</span><span class="token string">"address"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"cn.bloghut.domain.Address"</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"address"</span> value<span class="token operator">=</span><span class="token string">"csdn_闲言"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>bean<span class="token operator">></span> <span class="token operator"><</span>bean id<span class="token operator">=</span><span class="token string">"student"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"cn.bloghut.domain.Student"</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span>注入address 类型<span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"address"</span> ref<span class="token operator">=</span><span class="token string">"address"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span><span class="token class-name">String</span> 类型<span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"name"</span> value<span class="token operator">=</span><span class="token string">"csdn_闲言"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span><span class="token class-name">String</span> 类型<span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"books"</span><span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>array<span class="token punctuation">></span></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span><span class="token class-name">JavaSE</span><span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span><span class="token class-name">JavaWeb</span><span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span><span class="token class-name">Spring</span><span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span><span class="token class-name">SpringMVC</span><span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span><span class="token class-name">Mybatis</span><span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>array<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span><span class="token class-name">List</span><span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"hobbies"</span><span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>list<span class="token punctuation">></span></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span>唱<span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span>跳<span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span>rap<span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span>篮球<span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>list<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span><span class="token class-name">Map</span><span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"card"</span><span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>map<span class="token punctuation">></span></span> <span class="token operator"><</span>entry key<span class="token operator">=</span><span class="token string">"闲言"</span> value<span class="token operator">=</span><span class="token string">"csdn——闲言"</span><span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>entry<span class="token operator">></span> <span class="token operator"><</span>entry key<span class="token operator">=</span><span class="token string">"闲言博客"</span> value<span class="token operator">=</span><span class="token string">"csdn——闲言——博客"</span><span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>entry<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>map<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span>set<span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"games"</span><span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>set<span class="token punctuation">></span></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span>唱<span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span>跳<span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span>rap<span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>value<span class="token punctuation">></span></span>篮球<span class="token operator"><</span><span class="token operator">/</span>value<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>set<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span><span class="token class-name">String</span><span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"wife"</span> value<span class="token operator">=</span><span class="token string">"xxx"</span><span class="token operator">></span><span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span><span class="token class-name">Properties</span><span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>property name<span class="token operator">=</span><span class="token string">"info"</span><span class="token operator">></span> <span class="token generics"><span class="token punctuation"><</span>props<span class="token punctuation">></span></span> <span class="token operator"><</span>prop key<span class="token operator">=</span><span class="token string">"p1"</span><span class="token operator">></span>v1<span class="token operator"><</span><span class="token operator">/</span>prop<span class="token operator">></span> <span class="token operator"><</span>prop key<span class="token operator">=</span><span class="token string">"p2"</span><span class="token operator">></span>v2<span class="token operator"><</span><span class="token operator">/</span>prop<span class="token operator">></span> <span class="token operator"><</span>prop key<span class="token operator">=</span><span class="token string">"p3"</span><span class="token operator">></span>v3<span class="token operator"><</span><span class="token operator">/</span>prop<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>props<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>property<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">/</span>bean<span class="token operator">></span>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
测试
public static void main(String[] args) {
ApplicationContext ac = new ClassPathXmlApplicationContext("bean.xml");
Student student = (Student)ac.getBean("student");
System.out.println(student);
}
- 1
- 2
- 3
- 4
- 5
输出
Student{
name='csdn_闲言',
address=Address{address='csdn_闲言'},
books=[JavaSE, JavaWeb, Spring, SpringMVC, Mybatis],
hobbies=[唱, 跳, rap, 篮球],
card={闲言=csdn——闲言, 闲言博客=csdn——闲言——博客},
games=[唱, 跳, rap, 篮球],
wife='xxx',
info={p3=v3, p2=v2, p1=v1}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
## 8、拓展方式注入 可以使用**p命名空间**和**c命名空间**进行注入
- p 命名空间对应 setter 方式注入(要提供set方法)
- c 命令空间对应 构造方法 (要提供有参构造方法)
<?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:p="http://www.springframework.org/schema/p"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
bean.xml
<?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:p="http://www.springframework.org/schema/p" xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd">
<span class="token operator"><</span>bean id<span class="token operator">=</span><span class="token string">"user"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"cn.bloghut.domain.User"</span> p<span class="token operator">:</span>name<span class="token operator">=</span><span class="token string">"闲言"</span> p<span class="token operator">:</span>age<span class="token operator">=</span><span class="token string">"18"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>bean id<span class="token operator">=</span><span class="token string">"user2"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"cn.bloghut.domain.User"</span> c<span class="token operator">:</span>name<span class="token operator">=</span><span class="token string">"csdn——闲言"</span> c<span class="token operator">:</span>age<span class="token operator">=</span><span class="token string">"19"</span> <span class="token operator">/</span><span class="token operator">></span>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
pojp
public class User { private String name; private int age;
<span class="token keyword">public</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">,</span> <span class="token keyword">int</span> age<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>age <span class="token operator">=</span> age<span class="token punctuation">;</span> <span class="token punctuation">}</span> 省略setter
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
测试
ApplicationContext ac = new ClassPathXmlApplicationContext("userbeans.xml");
User user = (User)ac.getBean("user");
User user2 = (User)ac.getBean("user2");
System.out.println(user);
System.out.println(user2);
- 1
- 2
- 3
- 4
- 5
输出
User{name='闲言', age=18}
User{name='csdn——闲言', age=19}
- 1
- 2
9、bean的作用域
9-1.单例模式(Spring 默认机制)
scope="singleton"
<bean scope="singleton" id="user2" class="cn.bloghut.domain.User" c:name="csdn——闲言" c:age="19" />
User user2 = (User)ac.getBean(“user2”);
User user3 = (User)ac.getBean(“user2”);
System.out.println(user2.hashCode());
System.out.println(user3.hashCode());
- 1
- 2
- 3
- 4
- 5
- 6
- 7
输出
817406040
817406040
- 1
- 2
9-2.原型模式:每次从容器中get的时候,都会产生一个新对象
<bean scope="prototype" id="user" class="cn.bloghut.domain.User" p:name="闲言" p:age="18"/>
ApplicationContext ac = new ClassPathXmlApplicationContext(“userbeans.xml”);
for (int i = 0;i< 5;i++){
System.out.println(ac.getBean(“user”).hashCode());
}
- 1
- 2
- 3
- 4
- 5
- 6
输出
817406040
1955915048
1270855946
2083117811
157683534
- 1
- 2
- 3
- 4
- 5
单线程—单例
多线程—多例
10.Bean的自动装配
自动装配是Spring 满足bean依赖的一种方式!
Spring 会在上下文自动寻找,并自动给bean 装配属性!
在Spring 中有三种装配的方式
- 在xml 中显示的配置
- 在java中显示配置
- 隐式 的自动装配bean【重要】
ByName方法自动装配
- autowire=“byName”
- 会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id!
- 弊端:set 方法后面的值和 id 相同
bean.xml
<bean id="cat" class="cn.bloghut.domin.Cat"/>
<bean id="dog" class="cn.bloghut.domin.Dog"/>
<!–
byName:会自动在容器上下文中查找,和自己对象set方法后面的值对应的bean id!
–>
<bean id=“people” class=“cn.bloghut.domin.People” autowire=“byName”>
<property name=“name” value=“csdn_闲言”/>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
测试
public static void main(String[] args) {
<span class="token class-name">ApplicationContext</span> ac <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ClassPathXmlApplicationContext</span><span class="token punctuation">(</span><span class="token string">"bean.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">People</span> people <span class="token operator">=</span> ac<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token string">"people"</span><span class="token punctuation">,</span> <span class="token class-name">People</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> people<span class="token punctuation">.</span><span class="token function">getCat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">shout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> people<span class="token punctuation">.</span><span class="token function">getDog</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">shout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
ByName方法自动装配
- autowire=“byType”
- 会自动在容器上下文中查找,和自己对象属性类型相同的bean
- 弊端:它必须保证类型全局唯一(在IOC容器中只能由一个)。
<bean id="cat" class="cn.bloghut.domin.Cat"/>
<bean id="dog11" class="cn.bloghut.domin.Dog"/>
<!--
byType:会自动在容器上下文中查找,和自己对象属性类型相同的bean
–>
<bean id=“people” class=“cn.bloghut.domin.People” autowire=“byType”>
<property name=“name” value=“csdn_闲言”/>
</bean>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
测试
public static void main(String[] args) {
<span class="token class-name">ApplicationContext</span> ac <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ClassPathXmlApplicationContext</span><span class="token punctuation">(</span><span class="token string">"bean.xml"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">People</span> people <span class="token operator">=</span> ac<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token string">"people"</span><span class="token punctuation">,</span> <span class="token class-name">People</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> people<span class="token punctuation">.</span><span class="token function">getCat</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">shout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> people<span class="token punctuation">.</span><span class="token function">getDog</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">shout</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
总结:
byName的时候,需要保证所有bean的id唯一,并且这个bean需要和自动注入的属性的set方法的值一致
byType的时候,需要保证所有bean的class唯一,并且这个bean需要和自动注入的属性的类型一致
11、注解实现自动装配
-
jdk1.5支持的注解 Spring2.5支持的注解
-
The introduction of annotation-based configuration raised the question of whether this approach is “better” than XML
-
@Autowired
-
@Quelifier
-
@Resource
xml头文件约束
<?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
https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
https://www.springframework.org/schema/context/spring-context.xsd
http://www.springframework.org/schema/aop
https://www.springframework.org/schema/aop/spring-aop.xsd">
<!–开启注解支持–>
<context:annotation-config/>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
11-1.@Autowired
- 在属性上使用
- 在set方式上使用
- 使用Autowired 可以不用编写set方法了,前提是你这个自动装配的属性在IOC(Spring)容器中存在(需要通过其他方式注入进容器),且符合名字byName。
public class People { @Autowired private Dog dog;
<span class="token annotation punctuation">@Autowired</span> <span class="token keyword">private</span> <span class="token class-name">Cat</span> cat<span class="token punctuation">;</span> <span class="token keyword">private</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token class-name">People</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token class-name">People</span><span class="token punctuation">(</span><span class="token class-name">Dog</span> dog<span class="token punctuation">,</span> <span class="token class-name">Cat</span> cat<span class="token punctuation">,</span> <span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>dog <span class="token operator">=</span> dog<span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>cat <span class="token operator">=</span> cat<span class="token punctuation">;</span> <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span> <span class="token punctuation">}</span> 省略setter
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
Autowired 有一个个唯一的属性( required )
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Autowired {
boolean required() default true;
}
- 1
- 2
- 3
- 4
- 5
- 6
@Nullable
字段标记了这个注解,表示这个字段可以为null
@Qualifier
- 当我们的容器存在多个相同类型,不同名称的bean。使用@Autowired 无法完成自动装配了
- 这个时候需要使用@Qualifier 和@Autowired 注解一起使用。
- 使用@Qualifier 指定一个唯一的bean对象注入!
例如
IOC容器中存在多个 相同类型不同id的bean
通过@Qualifier 指定一个唯一的bean
测试
11-2.@Resource
不指定name值,先去判断byName和byType,有一个能注入即成功
根据类型查找
11-3.根据类型和id查找
如果IOC容器中存在多个不同名称,相同类型的bean,可以通过@Resource注解的name属性指定唯一的id;
总结:
- 都是用来自动装配的,都可以放在*属性字段*上
- @Autowired通过byType(类型)的方式实现,而且必须要求这个对象存在!
- @Resource默认通过byName(id)的方式实现,如果找不到名字,则通过byType实现!如果两个都找不到的情况下,就报错!
- 执行顺序不同:@Autowired通过byType的方式实现。@Resource默认通过byName的方式实现。
12、使用注解开发
在Spring4之后,要使用注解开发,必须保证aop的包导入了
使用注解需要导入context约束,增加注解的支持!
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd"> <!--开启注解扫描--> <context:component-scan base-package="cn.bloghut"/>
<span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span>开启注解支持<span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>context<span class="token operator">:</span>annotation<span class="token operator">-</span>config<span class="token operator">/</span><span class="token operator">></span>
</beans>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
bean注入使用@Componet注解
等价于<bean id="user" class="cn.bloghut.domain.User">
@Component
public class User {
}
- 1
- 2
- 3
- 4
属性注入使用@Value注解
<property name="name" value="闲言"> @Component public class User {
<span class="token keyword">private</span> <span class="token class-name">String</span> name<span class="token punctuation">;</span> <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">"闲言"</span><span class="token punctuation">)</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setName</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
衍生注解
- @Componet有几个衍生注解,在web开发中,会按照mvc三层架构分层!
- @Service--------业务层注解
- @Repository—持久层注解
- @Controller-----控制层注解
这四个注解功能都是一样的,都是代表将某个类注册到Spring中,装配Bean
自动装配
- @Autowired 自动装配通过类型、名字
如果Autowired不能唯一自动装配上属性,则需要通过@Qualifier(value=“xxx”) - @Nullable 字段标记了这个注解,说明这个字段可以为null
- @Resource 自动装配通过名字,类型
作用域
@Scope(“singleton”)单例
- 1
总结
XML 与 注解
- xml更加万能,适用于任何场合!维护简单方便
- 注解不是自己类使用不了, 维护相对复杂
XML 与 注解最佳实践
- xml用来管理bean
- 注解只负责完成属性的注入
- 我们在使用过程中,只需要注意一个问题:必须让注解生效,就需要开启注解的支持
<!--开启注解扫描-->
<context:component-scan base-package="cn.bloghut"/>
<!–开启注解支持–>
<context:annotation-config/>
- 1
- 2
- 3
- 4
- 5
13、java的方式配置Spring
JavaConfig 是Spring的 一个子项目,在Spring 4之后,它成为了新功能
- 首先定义一个类,在类上添加@Component注解,让它加载到Spring IOC容器(让Spring 管理)
- 定义Java 配置类,在其类上添加@Configuration 注解,说明该类是一个配置类,这个类也会被Spring 托管,因为它本身是一个@Component
- 在Myconfig 类中 添加getUser 方法,返回一个user对象
- getUser 方法上的@Bean 注解 则是注册一个bean功能,相当于
<bean id="getUser" class="cn.bloghut.domain.User">
- 1
- 方法的名字,相当于bean 标签中的id 属性。
- 方法的返回值,相当于bean 标签中的class属性。(因为我们导包了,Spring 知道是哪一个)
- 如果完全使用了配置类方式去做,我们只能通过AnnotationConfigApplicationContext 上下文来获取容器,通过配置类的class 对象加载!
完整代码
- @Configuration 这个一个配置类
- @ComponentScan 用于扫描包
- @Import 用于导入其他配置类
13-1.主配置类
@Configuration @ComponentScan(basePackages = {"cn.bloghut.domain"}) @Import({MyConfig2.class}) public class MyConfig {
<span class="token comment">/** * 返回一个User Bean * @return */</span> <span class="token annotation punctuation">@Bean</span> <span class="token keyword">public</span> <span class="token class-name">User</span> <span class="token function">getUser</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">User</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
13-2.配置类2
@Configuration
public class MyConfig2 {
}
- 1
- 2
- 3
- 4
- 5
13-3.User实体类
@Component public class User { private String name;
<span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> name<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Value</span><span class="token punctuation">(</span><span class="token string">"闲言"</span><span class="token punctuation">)</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setName</span><span class="token punctuation">(</span><span class="token class-name">String</span> name<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>name <span class="token operator">=</span> name<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">toString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token string">"User{"</span> <span class="token operator">+</span> <span class="token string">"name='"</span> <span class="token operator">+</span> name <span class="token operator">+</span> <span class="token string">'\''</span> <span class="token operator">+</span> <span class="token string">'}'</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
13-4.测试类
public class MyTest { public static void main(String[] args) {
<span class="token class-name">ApplicationContext</span> ac <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">AnnotationConfigApplicationContext</span><span class="token punctuation">(</span><span class="token class-name">MyConfig</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">User</span> user <span class="token operator">=</span> ac<span class="token punctuation">.</span><span class="token function">getBean</span><span class="token punctuation">(</span><span class="token string">"getUser"</span><span class="token punctuation">,</span> <span class="token class-name">User</span><span class="token punctuation">.</span><span class="token keyword">class</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>user<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
14、代理模式
14-1.角色分析:
- 抽象角色:一般会使用接口或者抽象类来解决
- 真实角色:被代理的角色
- 代理角色:代理 真实角色,代理真实角色后,我们一般会做一些附属操作
- 客户:访问代理对象的人
代码步骤:
14-2.接口
public interface Rent {
/**
* 租房
*/
void rent();
}
- 1
- 2
- 3
- 4
- 5
- 6
14-3.真实角色
public class Host implements Rent{
<span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">rent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"房东要出租房子"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
14-4.代理角色
public class Proxy implements Rent{
<span class="token keyword">private</span> <span class="token class-name">Host</span> host<span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token class-name">Proxy</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token class-name">Proxy</span><span class="token punctuation">(</span><span class="token class-name">Host</span> host<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>host <span class="token operator">=</span> host<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">rent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token function">seeHouse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> host<span class="token punctuation">.</span><span class="token function">rent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">fare</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">hetong</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//看房</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">seeHouse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"中介带你看房"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//收中介费</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">fare</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"收中介费"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//签合同</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">hetong</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"签合同"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
14-5.客户端访问代理角色
public class Client { public static void main(String[] args) {
<span class="token class-name">Host</span> host <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Host</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//代理,中介帮房东,但是呢?代理角色一般会有一些附属操作!</span> <span class="token class-name">Proxy</span> proxy <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Proxy</span><span class="token punctuation">(</span>host<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//你不用面对房东,直接找中介租房即可!</span> proxy<span class="token punctuation">.</span><span class="token function">rent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
14-6.代理模式的好处:
- 可以使真实角色的操作更加存粹!不用去关注一些公共的业务
2. 公共交给了代理角色,实现了业务的分工 - 公共业务发生扩展的时候,方便集中管理
14-7.缺点:
- 一个真实角色就会产生一个代理角色,代码量会翻倍 开发效率变低
15、静态代理
- 有一天,公司领导要求我为 某个类的所有方法新增日志输出功能。
- 怎么做呢?
- 在原来的类上的每一个方法添加日志输出?
- 这就是改变原来人家的代码了。
- 改动原有的业务代码,在公司中是大忌!
- 有可能人家你修改了人家的代码,可能给改蹦了。
- 新增一个类,制作成本小,职责单一。
原来的开发方式(纵向开发)
添加日志功能(横切进去)
代码如下:
业务接口:
public interface UserService { void add();
<span class="token keyword">void</span> <span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">void</span> <span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">void</span> <span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
原来业务类
public class UserServiceImpl implements UserService { @Override public void add() { System.out.println("新增用户"); }
<span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"删除用户"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"修改用户"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"查询用户"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
代理类
public class UserServiceProxy implements UserService {
<span class="token keyword">private</span> <span class="token class-name">UserService</span> userService<span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setUserService</span><span class="token punctuation">(</span><span class="token class-name">UserService</span> userService<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>userService <span class="token operator">=</span> userService<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"add"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> userService<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"delete"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> userService<span class="token punctuation">.</span><span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token function">log</span><span class="token punctuation">(</span><span class="token string">"update"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> userService<span class="token punctuation">.</span><span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"query"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> userService<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//日志方法</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">log</span><span class="token punctuation">(</span><span class="token class-name">String</span> msg<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"【Debug 】使用了"</span><span class="token operator">+</span>msg<span class="token operator">+</span><span class="token string">"方法"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
测试类
public static void main(String[] args) {
<span class="token class-name">UserServiceProxy</span> userService <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserServiceProxy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> userService<span class="token punctuation">.</span><span class="token function">setUserService</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">UserServiceImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span> userService<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
16、动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的,不是我们直接写好的
动态代理分为两大类:基于接口的动态代理,基于类的动态代理 - 基于接口:JDK动态代理
- 基于类: cglib
- java字节码实现: javasist
需要了解两个类:Proxy :代理 InvocationHandler:调用处理程序
java.lang.reflect.Proxy
- 1
Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。(大白话:这是一个静态类,类里边有方法得到代理类)
动态代理类 (以下简称为代理类 )是一个实现在类创建时在运行时指定的接口列表的类,具有如下所述的行为。 代理接口是由代理类实现的接口。 代理实例是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序对象,它实现了接口
通过其代理接口之一的代理实例上的方法调用将被分派到实例调用处理程序的invoke方法,传递代理实例, java.lang.reflect.Method被调用方法的java.lang.reflect.Method对象以及包含参数的类型Object Object的数组。 调用处理程序适当地处理编码方法调用,并且返回的结果将作为方法在代理实例上调用的结果返回。
代理类具有以下属性:
- 代理类是公共的,最终的,而不是抽象的,如果所有代理接口都是公共的。
- 如果任何代理接口是非公开的,代理类是非公开的,最终的,而不是抽象的 。
- 代理类的不合格名称未指定。 然而,以字符串"$Proxy"开头的类名空间应该保留给代理类。
- 一个代理类扩展了java.lang.reflect.Proxy 。
- 代理类完全按照相同的顺序实现其创建时指定的接口。
- 如果一个代理类实现一个非公共接口,那么它将被定义在与该接口相同的包中。 否则,代理类的包也是未指定的。 请注意,程序包密封不会阻止在运行时在特定程序包中成功定义代理类,并且类也不会由同一类加载器定义,并且与特定签名者具有相同的包。
- 由于代理类实现了在其创建时指定的所有接口, getInterfaces在其类对象上调用getInterfaces将返回一个包含相同列表接口的数组(按其创建时指定的顺序),在其类对象上调用getMethods将返回一个数组的方法对象,其中包括这些接口中的所有方法,并调用getMethod将在代理接口中找到可以预期的方法。
- Proxy.isProxyClass方法将返回true,如果它通过代理类 - 由Proxy.getProxyClass返回的类或由Proxy.newProxyInstance返回的对象的类 - 否则为false。
- 所述java.security.ProtectionDomain代理类的是相同由引导类装载程序装载系统类,如java.lang.Object ,因为是由受信任的系统代码生成代理类的代码。 此保护域通常将被授予java.security.AllPermission 。
- 每个代理类有一个公共构造一个参数,该接口的实现InvocationHandler ,设置调用处理程序的代理实例。 而不必使用反射API来访问公共构造函数,也可以通过调用Proxy.newProxyInstance方法来创建代理实例,该方法将调用Proxy.getProxyClass的操作与调用处理程序一起调用构造函数。
17、基于Proxy类和InvocationHandler 实现动态代理
17-1.真实的角色
public class Host implements Rent{
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">rent</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"租房"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
17-2.被代理的接口
public interface Rent {
<span class="token keyword">void</span> <span class="token function">rent</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
17-3.代理 真实的角色 ProxyInvocationHandler
public class ProxyInvocationHandler implements InvocationHandler {
<span class="token comment">//被代理的接口</span> <span class="token keyword">private</span> <span class="token class-name">Rent</span> rent<span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setRent</span><span class="token punctuation">(</span><span class="token class-name">Rent</span> rent<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>rent <span class="token operator">=</span> rent<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//生成得到代理类</span> <span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">getProxy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token class-name">Proxy</span><span class="token punctuation">.</span><span class="token function">newProxyInstance</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getClassLoader</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>rent<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getInterfaces</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">/** * 处理代理实例,并返回结果 * @param proxy * @param method * @param args * @return * @throws Throwable */</span> <span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">invoke</span><span class="token punctuation">(</span><span class="token class-name">Object</span> proxy<span class="token punctuation">,</span> <span class="token class-name">Method</span> method<span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//动态代理的本质,就是使用反射机制</span> <span class="token comment">//在方法调用前调用</span> <span class="token function">seeHouse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">Object</span> result <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>rent<span class="token punctuation">,</span>args<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//在方法调用后调用</span> <span class="token function">heTong</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">seeHouse</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"看房子"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">heTong</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"签合同"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
}
17-4.用户
public class Client {
public static void main(String[] args) {
//创建真实角色
Host host = new Host();
//创建代理角色 不存在
ProxyInvocationHandler proxyInvocationHandler = new ProxyInvocationHandler();
//设置要代理的对象
proxyInvocationHandler.setRent(host);
//获取代理对象,并强制转换
Rent proxy = (Rent)proxyInvocationHandler.getProxy();
//调用
proxy.rent();
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
17-5.输出结果
看房子
租房
签合同
- 1
- 2
- 3
18、基于Proxy类和InvocationHandler 实现动态代理 2
Proxy:生成动态代理实例的
InvocationHandler:调用处理程序并返回结果的
万能的自动生成代理类
package cn.bloghut.demo3;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
/**
-
@Classname ProxyInvocationHandler
-
@Description 自动生成代理类
-
@Date 2021/5/17 15:44
-
@Created by 闲言
*/
public class ProxyInvocationHandler implements InvocationHandler {//1.被代理的接口
public Object target;public void setTarget(Object target){
this.target = target;
}//2.生成得到代理类(代理谁)
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),
target.getClass().getInterfaces(),this);
}//3.处理代理实例,并返回结果(代用代理程序)
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//动态获取方法名称
log(method.getName());
Object result = method.invoke(target, args);
return result;
}
/**- 打印日志方法
- @param msg
*/
public void log(String msg){
System.out.println("[debug]===> 执行可"+msg+“方法”);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
public static void main(String[] args) {
<span class="token comment">//真实角色</span> <span class="token class-name">UserServiceImpl</span> userService <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">UserServiceImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//代理角色,不存在</span> <span class="token class-name">ProxyInvocationHandler</span> invocationHandler <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ProxyInvocationHandler</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//设置要代理的对象</span> invocationHandler<span class="token punctuation">.</span><span class="token function">setTarget</span><span class="token punctuation">(</span>userService<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//获取代理对象</span> <span class="token class-name">UserService</span> proxy <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">UserService</span><span class="token punctuation">)</span>invocationHandler<span class="token punctuation">.</span><span class="token function">getProxy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//执行方法</span> proxy<span class="token punctuation">.</span><span class="token function">query</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
[debug]===> 执行可query方法
query
- 1
- 2
19、动态代理和静态代理总结
19-1.静态代理
- 由程序员创建或由特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
- 静态代理通常只代理一个类
- 静态代理事先知道要代理的是什么
代码如下:
- 如下, HelloServiceProxy类是代理类,HelloServiceImpl类是委托类,这两个类都实现了HelloService接口。
- 其中HelloServiceImpl类是HelloService接口的真正实现者,而HelloServiceProxy类是通过调用HelloServiceImpl类的相关方法来提供特定服务的。
- HelloServiceProxy类的echo()方法和getTime()方法会分别调用被代理的HelloServiceImpl对象的echo()方法和getTime()方法,并且在方法调用前后都会执行一些简单的打印操作。
- 由此可见,代理类可以为委托类预处理消息、把消息转发给委托类和事后处理消息等。
HelloService接口
public interface HelloService { String echo(String msg);
<span class="token class-name">Date</span> <span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
HelloServiceImpl委托类
public class HelloServiceImpl implements HelloService {
@Override
public String echo(String msg) {
return “echo:” + msg;
}
<span class="token annotation punctuation">@Override</span>
<span class="token keyword">public</span> <span class="token class-name">Date</span> <span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
HelloServiceProxy代理类
public class HelloServiceProxy implements HelloService {
<span class="token comment">//表示被代理的HelloService 实例</span> <span class="token keyword">private</span> <span class="token class-name">HelloService</span> helloService<span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token class-name">HelloServiceProxy</span><span class="token punctuation">(</span><span class="token class-name">HelloService</span> helloService<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>helloService <span class="token operator">=</span> helloService<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setHelloServiceProxy</span><span class="token punctuation">(</span><span class="token class-name">HelloService</span> helloService<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>helloService <span class="token operator">=</span> helloService<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token class-name">String</span> <span class="token function">echo</span><span class="token punctuation">(</span><span class="token class-name">String</span> msg<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//预处理</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"before calling echo()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//调用被代理的HelloService 实例的echo()方法</span> <span class="token class-name">String</span> result <span class="token operator">=</span> helloService<span class="token punctuation">.</span><span class="token function">echo</span><span class="token punctuation">(</span>msg<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//事后处理</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"after calling echo()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token class-name">Date</span> <span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token comment">//预处理</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"before calling getTime()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//调用被代理的HelloService 实例的getTime()方法</span> <span class="token class-name">Date</span> date <span class="token operator">=</span> helloService<span class="token punctuation">.</span><span class="token function">getTime</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//事后处理</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"after calling getTime()"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> date<span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
测试
public class Test {
public static void main(String[] args) {
//创建委托类
HelloServiceImpl helloService = new HelloServiceImpl();
//创建代理类
HelloServiceProxy helloServiceProxy = new HelloServiceProxy(helloService);
//调用方法
Date time = helloServiceProxy.getTime();
System.out.println(time);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
19-2.动态代理
- 在程序运行时,运用反射机制动态创建而成
- 动态代理是代理一个接口下的多个实现类
- 动态代理不知道要代理什么东西,只有在运行时才知道
与静态代理类对照的是动态代理类,动态代理类的字节码在程序运行时由Java反射机制动态生成,无需程序员手工编写它的源代码。动态代理类不仅简化了编程工作,而且提高了软件系统的可扩展性,因为Java反射机制可以生成任意类型的动态代理类。java.lang.reflect 包中的Proxy类和InvocationHandler接口提供了生成动态代理类的能力。
Proxy类提供了创建动态代理类及其实例的静态方法。
代码如下:
public static void main(String[] args) {
<span class="token comment">//真实角色</span> <span class="token class-name">HelloServiceImpl</span> helloService <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">HelloServiceImpl</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//代理角色 不存在</span> <span class="token class-name">ProxyInvocationHandler</span> proxyInvocationHandler <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">ProxyInvocationHandler</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> proxyInvocationHandler<span class="token punctuation">.</span><span class="token function">setTarget</span><span class="token punctuation">(</span>helloService<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">HelloService</span> proxy <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token class-name">HelloService</span><span class="token punctuation">)</span>proxyInvocationHandler<span class="token punctuation">.</span><span class="token function">getProxy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//执行方法</span> <span class="token class-name">String</span> echo <span class="token operator">=</span> proxy<span class="token punctuation">.</span><span class="token function">echo</span><span class="token punctuation">(</span><span class="token string">"Proxy InvocationHandler 实现动态代理"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>echo<span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
输出
代理方法执行前调用
代理方法执行后调用
echo:Proxy InvocationHandler 实现动态代理
- 1
- 2
- 3
public class ProxyInvocationHandler implements InvocationHandler {
<span class="token comment">//要代理的类</span> <span class="token keyword">private</span> <span class="token class-name">Object</span> target<span class="token punctuation">;</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">setTarget</span><span class="token punctuation">(</span><span class="token class-name">Object</span> target<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">this</span><span class="token punctuation">.</span>target <span class="token operator">=</span> target<span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//获取要代理的实例</span> <span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">getProxy</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span> <span class="token keyword">return</span> <span class="token class-name">Proxy</span><span class="token punctuation">.</span><span class="token function">newProxyInstance</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getClassLoader</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span>target<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getInterfaces</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token comment">//执行代理的方法</span> <span class="token annotation punctuation">@Override</span> <span class="token keyword">public</span> <span class="token class-name">Object</span> <span class="token function">invoke</span><span class="token punctuation">(</span><span class="token class-name">Object</span> proxy<span class="token punctuation">,</span> <span class="token class-name">Method</span> method<span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"代理方法执行前调用"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">//执行方法</span> <span class="token class-name">Object</span> result <span class="token operator">=</span> method<span class="token punctuation">.</span><span class="token function">invoke</span><span class="token punctuation">(</span>target<span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"代理方法执行后调用"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> result<span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
20、什么是Aop
AOP(Aspect Oriented Programming)意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术,AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生泛型。利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。
20-1.Aop在Spring中的作用
提供声明事务:允许用户自定义切面
- 横切关注点:跨越应用程序多个模块的方法或功能。即与我们的业务逻辑无关的,但是我们需要关注的部分,就是横切关注点。如日志,安全,缓存,事务等等。。。
- 切面(ASPECT):横切关注点 被模块化的特殊对象。即 它是一个类
- 通知(Advice):切面必须要完成的工作,即 他是类中的一个方法
- 目标(target):被通知的对象
- 代理(Proxy):向目标对象应用通知之后创建的对象
- 切入点(PointCut):切面通知 执行的"地点"的定义
- 连接点(jointPoint):与切入点匹配的执行点
Spring Aop中,通过Advice定义横切逻辑,Spring中支持的5种类型的Advice
21、Aop 实现方式1-基于原生API
21-1.导入依赖
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>
- 1
- 2
- 3
- 4
- 5
21-2.在执行UserService实现类的所有方法前,增加日志功能
public class Log implements MethodBeforeAdvice {
<span class="token comment">/** * * @param method 要执行的目标对象方法 * @param args 参数 * @param target 目标对象 * @throws Throwable */</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">before</span><span class="token punctuation">(</span><span class="token class-name">Method</span> method<span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">,</span> <span class="token class-name">Object</span> target<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span>target<span class="token punctuation">.</span><span class="token function">getClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">" 的 "</span><span class="token operator">+</span>method<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">"方法执行了"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
21-3.在执行UserService实现类的所有方法后,增加日志功能
public class AfterLog implements AfterReturningAdvice {
<span class="token comment">/** * * @param returnValue 返回值 * @param method * @param args * @param target * @throws Throwable */</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">afterReturning</span><span class="token punctuation">(</span><span class="token class-name">Object</span> returnValue<span class="token punctuation">,</span> <span class="token class-name">Method</span> method<span class="token punctuation">,</span> <span class="token class-name">Object</span><span class="token punctuation">[</span><span class="token punctuation">]</span> args<span class="token punctuation">,</span> <span class="token class-name">Object</span> target<span class="token punctuation">)</span> <span class="token keyword">throws</span> <span class="token class-name">Throwable</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"执行了"</span><span class="token operator">+</span>method<span class="token punctuation">.</span><span class="token function">getName</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">+</span><span class="token string">"方法, 返回结果为"</span><span class="token operator">+</span>returnValue<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
21-4.UserService 接口
public interface UserService { void add();
<span class="token keyword">void</span> <span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">void</span> <span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">void</span> <span class="token function">select</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
21-5.UserServiceImpl 接口
public class UserServiceImpl implements UserService { public void add() { System.out.println("add"); }
<span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">delete</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"delete"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">update</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"update"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span> <span class="token keyword">public</span> <span class="token keyword">void</span> <span class="token function">select</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> <span class="token class-name">System</span><span class="token punctuation">.</span>out<span class="token punctuation">.</span><span class="token function">println</span><span class="token punctuation">(</span><span class="token string">"select"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
21-6.bean.xml 文件
<?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 https://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop.xsd">
<span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span>注册bean<span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>bean id<span class="token operator">=</span><span class="token string">"userService"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"cn.bloghut.service.UserServiceImpl"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>bean id<span class="token operator">=</span><span class="token string">"afterLog"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"cn.bloghut.log.AfterLog"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span>bean id<span class="token operator">=</span><span class="token string">"log"</span> <span class="token keyword">class</span><span class="token operator">=</span><span class="token string">"cn.bloghut.log.Log"</span><span class="token operator">/</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span>方式一,使用原生的<span class="token class-name">Api</span> 接口<span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span>配置aop<span class="token operator">--</span><span class="token operator">></span> <span class="token operator"><</span>aop<span class="token operator">:</span>config<span class="token operator">></span> <span class="token operator"><</span><span class="token operator">!</span><span class="token operator">--</span><span class="token number">1.</span>配置切入点 pointcut 切入点 expression 表达式<span class="token punctuation">,</span> <span class="token function">execution</span><span class="token punctuation">(</span>要执行的位置<span class="token operator">!</span><span class="token punctuation"