6.通过javaConfig配置Spring
- 完全通过JavaConfig来配置Spring
- pojo包
- 创建一个实体类,并使用@Component注解,将该类注册到Spring容器中
//使用该注解,将User类注册到Spring容器,装配Bean
@Component
public class User {
private String name;
public String getName() {
return name;
}
@Value("晴明")
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "User{" +
"name='" + name + '\'' +
'}';
}
}
- config包
- 使用@Configuration将该配置类注册到Spring容器中
//使用这个注解后,该类也会被注册到Spring容器中,@Configuration也属于一个@Component
//使用@Configuration代表这是一个配置类,类似applicationContext.xml
@Configuration
public class EicomaConfig {
//@Bean 该注解可注册一个Bean
//该方法的名字,相当于xml中bean的id
//该方法的返回值,相当于xml中bean的class
@Bean
public User getUser(){
//返回要注入到Spring容器中的对象
return new User();
}
}
- 使用@Bean将要注册的类注册到Spring容器中
//@Bean 该注解可注册一个Bean
//该方法的名字,相当于xml中bean的id
//该方法的返回值,相当于xml中bean的class
@Bean
public User getUser(){
//返回要注入到Spring容器中的对象
return new User();
}
- 使用@ComponentScan(“com.eicoma.pojo”)注册配置类,和@Component相似
//@ComponentScan("com.eicoma.pojo")的功能和Configuration一致
@ComponentScan("com.eicoma.pojo")
public class EicomaConfig {
//@Bean 该注解可注册一个Bean
//该方法的名字,相当于xml中bean的id
//该方法的返回值,相当于xml中bean的class
@Bean
public User getUser(){
//返回要注入到Spring容器中的对象
return new User();
}
}
7.代理模式
- 代理模式
- 静态代理
- 动态代理
7.1静态代理
-
角色分类
- 抽象角色(用接口或抽象类表示)
public interface Rent { public void rent(); }
- 真实角色(被代理的角色)
public class Host implements Rent{ public void rent() { //房东只需考虑交出房子,其他的一切交给代理 System.out.println("房东出租房子!"); } }
- 代理
public class Proxy implements Rent{ private Host host; public Proxy(){ } public Proxy(Host host){ this.host = host; } //代理租房的一切动作 public void rent() { host.rent(); seeHose(); qianHeTong(); shouFei(); } //看房 private void seeHose(){ System.out.println("看房子!"); } //签合同 private void qianHeTong(){ System.out.println("签合同!"); } //收费 private void shouFei(){ System.out.println("收取中介费!"); } }
- 客户(访问代理)
public class Client { public static void main(String[] args) { Host host = new Host(); //代理帮助房东出租房子 Proxy proxy = new Proxy(host); //租客直接面代理,无需直接面对房东 proxy.rent(); } }
-
代理模式优点
- 使真实角色不必关注公共的业务
- 公共业务交给代理,实现业务的分工
- 方便公共业务扩展
-
代理模式缺点
- 每一种类型的真实角色,就会产生一种对应的代理!会导致代码量提升!
加深理解
-
当需要扩展原有真实角色类的功能时,可以使用代理
- 抽象角色
该接口有四个功能需求
public interface UserService { public void add(); public void delete(); public void update(); public void query(); }
- 真实角色
实现接口功能
public class UserServiceImpl implements UserService{ public void add() { System.out.println("添加了一个用户!"); } public void delete() { System.out.println("删除了一个用户!"); } public void update() { System.out.println("修改了一个用户!"); } public void query() { System.out.println("查询了一个用户!"); } }
- 代理
增加需求,在原有功能实现时额外输出日志信息
public class UserServiceProxy implements UserService{ private UserServiceImpl userService; public void setUserService(UserServiceImpl userService){ this.userService = userService; } public void add() { log("add"); userService.add(); } public void delete() { log("delete"); userService.delete(); } public void update() { log("update"); userService.update(); } public void query() { log("query"); userService.query(); } private void log(String msg){ System.out.println("当前使用了"+msg+"方法"); } }
- 客户
引入真实角色对象及代理对象,调用代理对象的方法
public class Client { public static void main(String[] args) { // UserService userService = new UserServiceImpl(); // userService.add(); UserServiceImpl userService = new UserServiceImpl(); UserServiceProxy userServiceProxy = new UserServiceProxy(); userServiceProxy.setUserService( userService); userServiceProxy.add(); } }
-
AOP
不改动原有代码的前提下,通过代理的方式扩展功能!—【面向切面编程】
7.2动态代理
- 动态代理和静态代理角色一样
- 动态代理的代理类是动态生成的!
- 动态代理分为两大类:基于接口的动态代理,基于类的动态代理
- 基于接口:JDK动态代理
- 基于类:cglib
- java字节码实现:javasist
要了解两个类:
-
Proxy:代理
-
InvocationHandler:调用处理程序
动态代理好处:
-
使真实角色不必关注公共的业务
-
公共业务交给代理,实现业务的分工
-
方便公共业务扩展
-
**动态代理类代理的是一个接口!!**代表可代理一类业务!!只要是实现了该接口的实现类,均可以由此动态生成代理,无需重复编写静态代理!!
而静态代理代理的仅仅只是一个接口的实现类(真实角色),因此导致每有一个接口实现类,就需要再写一个静态代理!
代码示例
- 抽象角色
public interface UserService2 {
public void add();
public void delete();
public void update();
public void query();
}
- 真实角色
public class UserService2Impl implements UserService2 {
public void add() {
System.out.println("添加了一个用户!");
}
public void delete() {
System.out.println("删除了一个用户!");
}
public void update() {
System.out.println("修改了一个用户!");
}
public void query() {
System.out.println("查询了一个用户!");
}
}
- 动态代理类
- proxy:生成动态代理对象
- InvocationHandler:调用处理程序,返回结果(返回了真实角色+扩展的方法的结果)
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
public class ProxyInvocationHandler implements InvocationHandler {
//UserService2 userService2可替换为Object target(通用类型)
private UserService2 userService2;
public void setUserService2(UserService2 userService2) {
this.userService2 = userService2;
}
public Object getProxy(){
return Proxy.newProxyInstance(this.getClass().getClassLoader(),userService2.getClass().getInterfaces(),this);
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//log()为扩展的方法
//method.getName()返回了当前在Client层所调用的方法的名称
log(method.getName());
//这个invoke()返回了接口实现类对象UserService2Impl内部方法的所有结果----【重点!!!】
Object result = method.invoke(userService2,args);
return result;
}
public void log(String msg){
System.out.println("当前使用了"+msg+"方法");
}
}
- 客户
public class Client {
public static void main(String[] args) {
//获取接口对象(抽象角色)
UserService2 userService2 = new UserService2Impl();
//获取动态代理生成器类对象
ProxyInvocationHandler pih = new ProxyInvocationHandler();
//将接口对象传入pih对象中
pih.setUserService2(userService2);
//动态获取Proxy代理
//此处getProxy()返回的是Object对象,需要强转
UserService2 proxy= (UserService2) pih.getProxy();
//现在就能通过proxy代理调用方法啦!
proxy.add();
}
}
注:动态代理和静态代理最大的区别
动态代理通过反射,使代理从单纯代理某一个接口实现类,跨越到代理某一个接口!
从而使实现同一个接口的实现类均可由该动态代理进行代理!!